diff --git a/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/go.dbscheme b/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/go.dbscheme
new file mode 100644
index 000000000000..b1341734d687
--- /dev/null
+++ b/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/go.dbscheme
@@ -0,0 +1,563 @@
+/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */
+
+
+/** Duplicate code **/
+
+duplicateCode(
+ unique int id : @duplication,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+similarCode(
+ unique int id : @similarity,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+@duplication_or_similarity = @duplication | @similarity;
+
+tokens(
+ int id : @duplication_or_similarity ref,
+ int offset : int ref,
+ int beginLine : int ref,
+ int beginColumn : int ref,
+ int endLine : int ref,
+ int endColumn : int ref);
+
+/** External data **/
+
+externalData(
+ int id : @externalDataElement,
+ varchar(900) path : string ref,
+ int column: int ref,
+ varchar(900) value : string ref
+);
+
+snapshotDate(unique date snapshotDate : date ref);
+
+sourceLocationPrefix(varchar(900) prefix : string ref);
+
+/** Overlay support **/
+
+databaseMetadata(
+ string metadataKey: string ref,
+ string value: string ref
+);
+
+overlayChangedFiles(
+ string path: string ref
+);
+
+
+/*
+ * XML Files
+ */
+
+xmlEncoding(
+ unique int id: @file ref,
+ string encoding: string ref
+);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref
+);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref
+);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref
+);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref
+);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref
+);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref
+);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref
+);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref
+);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+compilations(unique int id: @compilation, string cwd: string ref);
+
+#keyset[id, num]
+compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
+
+#keyset[id, num, kind]
+compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
+
+diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
+
+compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
+
+#keyset[id, num]
+compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
+
+diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
+ string full_error_message: string ref, int location: @location ref);
+
+locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
+ int endLine: int ref, int endColumn: int ref);
+
+numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
+
+files(unique int id: @file, string name: string ref);
+
+folders(unique int id: @folder, string name: string ref);
+
+containerparent(int parent: @container ref, unique int child: @container ref);
+
+has_location(unique int locatable: @locatable ref, int location: @location ref);
+
+#keyset[parent, idx]
+comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
+
+comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
+
+doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
+
+#keyset[parent, idx]
+exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
+
+literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
+
+constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
+
+fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
+
+typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
+
+scopes(unique int id: @scope, int kind: int ref);
+
+scopenesting(unique int inner: @scope ref, int outer: @scope ref);
+
+scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
+
+objects(unique int id: @object, int kind: int ref, string name: string ref);
+
+objectscopes(unique int object: @object ref, int scope: @scope ref);
+
+objecttypes(unique int object: @object ref, int tp: @type ref);
+
+methodreceivers(unique int method: @object ref, int receiver: @object ref);
+
+fieldstructs(unique int field: @object ref, int struct: @structtype ref);
+
+methodhosts(int method: @object ref, int host: @definedtype ref);
+
+defs(int ident: @ident ref, int object: @object ref);
+
+uses(int ident: @ident ref, int object: @object ref);
+
+types(unique int id: @type, int kind: int ref);
+
+type_of(unique int expr: @expr ref, int tp: @type ref);
+
+typename(unique int tp: @type ref, string name: string ref);
+
+key_type(unique int map: @maptype ref, int tp: @type ref);
+
+element_type(unique int container: @containertype ref, int tp: @type ref);
+
+base_type(unique int ptr: @pointertype ref, int tp: @type ref);
+
+underlying_type(unique int defined: @definedtype ref, int tp: @type ref);
+
+#keyset[parent, index]
+component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
+
+#keyset[parent, index]
+struct_tags(int parent: @structtype ref, int index: int ref, string tag: string ref);
+
+#keyset[interface, index]
+interface_private_method_ids(int interface: @interfacetype ref, int index: int ref, string id: string ref);
+
+array_length(unique int tp: @arraytype ref, string len: string ref);
+
+type_objects(unique int tp: @type ref, int object: @object ref);
+
+packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
+
+#keyset[parent, idx]
+modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
+
+#keyset[package, idx]
+errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
+ string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
+
+has_ellipsis(int id: @callorconversionexpr ref);
+
+variadic(int id: @signaturetype ref);
+
+#keyset[parent, idx]
+typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
+ int parent: @typeparamparentobject ref, int idx: int ref);
+
+@container = @file | @folder;
+
+@locatable = @xmllocatable | @node | @localscope;
+
+@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
+ | @scopenode | @comment_group | @comment;
+
+@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
+
+@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
+
+@modexprparent = @file | @modexpr;
+
+@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
+
+@stmtparent = @funcdef | @stmt | @decl;
+
+@declparent = @file | @declstmt;
+
+@typeparamdeclparent = @funcdecl | @typespec;
+
+@funcdef = @funclit | @funcdecl;
+
+@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
+
+@location = @location_default;
+
+@sourceline = @locatable;
+
+case @comment.kind of
+ 0 = @slashslashcomment
+| 1 = @slashstarcomment;
+
+case @expr.kind of
+ 0 = @badexpr
+| 1 = @ident
+| 2 = @ellipsis
+| 3 = @intlit
+| 4 = @floatlit
+| 5 = @imaglit
+| 6 = @charlit
+| 7 = @stringlit
+| 8 = @funclit
+| 9 = @compositelit
+| 10 = @parenexpr
+| 11 = @selectorexpr
+| 12 = @indexexpr
+| 13 = @genericfunctioninstantiationexpr
+| 14 = @generictypeinstantiationexpr
+| 15 = @sliceexpr
+| 16 = @typeassertexpr
+| 17 = @callorconversionexpr
+| 18 = @starexpr
+| 19 = @keyvalueexpr
+| 20 = @arraytypeexpr
+| 21 = @structtypeexpr
+| 22 = @functypeexpr
+| 23 = @interfacetypeexpr
+| 24 = @maptypeexpr
+| 25 = @typesetliteralexpr
+| 26 = @plusexpr
+| 27 = @minusexpr
+| 28 = @notexpr
+| 29 = @complementexpr
+| 30 = @derefexpr
+| 31 = @addressexpr
+| 32 = @arrowexpr
+| 33 = @lorexpr
+| 34 = @landexpr
+| 35 = @eqlexpr
+| 36 = @neqexpr
+| 37 = @lssexpr
+| 38 = @leqexpr
+| 39 = @gtrexpr
+| 40 = @geqexpr
+| 41 = @addexpr
+| 42 = @subexpr
+| 43 = @orexpr
+| 44 = @xorexpr
+| 45 = @mulexpr
+| 46 = @quoexpr
+| 47 = @remexpr
+| 48 = @shlexpr
+| 49 = @shrexpr
+| 50 = @andexpr
+| 51 = @andnotexpr
+| 52 = @sendchantypeexpr
+| 53 = @recvchantypeexpr
+| 54 = @sendrcvchantypeexpr;
+
+@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
+
+@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
+
+@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
+
+@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
+
+@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
+
+@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
+
+@logicalunaryexpr = @notexpr;
+
+@bitwiseunaryexpr = @complementexpr;
+
+@arithmeticunaryexpr = @plusexpr | @minusexpr;
+
+@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
+
+@logicalbinaryexpr = @lorexpr | @landexpr;
+
+@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
+
+@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
+
+@shiftexpr = @shlexpr | @shrexpr;
+
+@comparison = @equalitytest | @relationalcomparison;
+
+@equalitytest = @eqlexpr | @neqexpr;
+
+@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
+
+@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
+
+case @stmt.kind of
+ 0 = @badstmt
+| 1 = @declstmt
+| 2 = @emptystmt
+| 3 = @labeledstmt
+| 4 = @exprstmt
+| 5 = @sendstmt
+| 6 = @incstmt
+| 7 = @decstmt
+| 8 = @gostmt
+| 9 = @deferstmt
+| 10 = @returnstmt
+| 11 = @breakstmt
+| 12 = @continuestmt
+| 13 = @gotostmt
+| 14 = @fallthroughstmt
+| 15 = @blockstmt
+| 16 = @ifstmt
+| 17 = @caseclause
+| 18 = @exprswitchstmt
+| 19 = @typeswitchstmt
+| 20 = @commclause
+| 21 = @selectstmt
+| 22 = @forstmt
+| 23 = @rangestmt
+| 24 = @assignstmt
+| 25 = @definestmt
+| 26 = @addassignstmt
+| 27 = @subassignstmt
+| 28 = @mulassignstmt
+| 29 = @quoassignstmt
+| 30 = @remassignstmt
+| 31 = @andassignstmt
+| 32 = @orassignstmt
+| 33 = @xorassignstmt
+| 34 = @shlassignstmt
+| 35 = @shrassignstmt
+| 36 = @andnotassignstmt;
+
+@incdecstmt = @incstmt | @decstmt;
+
+@assignment = @simpleassignstmt | @compoundassignstmt;
+
+@simpleassignstmt = @assignstmt | @definestmt;
+
+@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
+ | @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
+
+@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
+
+@switchstmt = @exprswitchstmt | @typeswitchstmt;
+
+@loopstmt = @forstmt | @rangestmt;
+
+case @decl.kind of
+ 0 = @baddecl
+| 1 = @importdecl
+| 2 = @constdecl
+| 3 = @typedecl
+| 4 = @vardecl
+| 5 = @funcdecl;
+
+@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
+
+case @spec.kind of
+ 0 = @importspec
+| 1 = @valuespec
+| 2 = @typedefspec
+| 3 = @aliasspec;
+
+@typespec = @typedefspec | @aliasspec;
+
+case @object.kind of
+ 0 = @pkgobject
+| 1 = @decltypeobject
+| 2 = @builtintypeobject
+| 3 = @declconstobject
+| 4 = @builtinconstobject
+| 5 = @declvarobject
+| 6 = @declfunctionobject
+| 7 = @builtinfunctionobject
+| 8 = @labelobject;
+
+@typeparamparentobject = @decltypeobject | @declfunctionobject;
+
+@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
+
+@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
+
+@typeobject = @decltypeobject | @builtintypeobject;
+
+@valueobject = @constobject | @varobject | @functionobject;
+
+@constobject = @declconstobject | @builtinconstobject;
+
+@varobject = @declvarobject;
+
+@functionobject = @declfunctionobject | @builtinfunctionobject;
+
+case @scope.kind of
+ 0 = @universescope
+| 1 = @packagescope
+| 2 = @localscope;
+
+case @type.kind of
+ 0 = @invalidtype
+| 1 = @boolexprtype
+| 2 = @inttype
+| 3 = @int8type
+| 4 = @int16type
+| 5 = @int32type
+| 6 = @int64type
+| 7 = @uinttype
+| 8 = @uint8type
+| 9 = @uint16type
+| 10 = @uint32type
+| 11 = @uint64type
+| 12 = @uintptrtype
+| 13 = @float32type
+| 14 = @float64type
+| 15 = @complex64type
+| 16 = @complex128type
+| 17 = @stringexprtype
+| 18 = @unsafepointertype
+| 19 = @boolliteraltype
+| 20 = @intliteraltype
+| 21 = @runeliteraltype
+| 22 = @floatliteraltype
+| 23 = @complexliteraltype
+| 24 = @stringliteraltype
+| 25 = @nilliteraltype
+| 26 = @typeparamtype
+| 27 = @arraytype
+| 28 = @slicetype
+| 29 = @structtype
+| 30 = @pointertype
+| 31 = @interfacetype
+| 32 = @tupletype
+| 33 = @signaturetype
+| 34 = @maptype
+| 35 = @sendchantype
+| 36 = @recvchantype
+| 37 = @sendrcvchantype
+| 38 = @definedtype
+| 39 = @typesetliteraltype;
+
+@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
+
+@booltype = @boolexprtype | @boolliteraltype;
+
+@numerictype = @integertype | @floattype | @complextype;
+
+@integertype = @signedintegertype | @unsignedintegertype;
+
+@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
+
+@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
+
+@floattype = @float32type | @float64type | @floatliteraltype;
+
+@complextype = @complex64type | @complex128type | @complexliteraltype;
+
+@stringtype = @stringexprtype | @stringliteraltype;
+
+@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
+ | @stringliteraltype | @nilliteraltype;
+
+@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
+ | @signaturetype | @definedtype | @typesetliteraltype;
+
+@containertype = @arraytype | @slicetype | @maptype | @chantype;
+
+@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
+
+case @modexpr.kind of
+ 0 = @modcommentblock
+| 1 = @modline
+| 2 = @modlineblock
+| 3 = @modlparen
+| 4 = @modrparen;
+
+case @error.kind of
+ 0 = @unknownerror
+| 1 = @listerror
+| 2 = @parseerror
+| 3 = @typeerror;
+
diff --git a/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/old.dbscheme b/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/old.dbscheme
new file mode 100644
index 000000000000..5ff5325d274a
--- /dev/null
+++ b/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/old.dbscheme
@@ -0,0 +1,563 @@
+/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */
+
+
+/** Duplicate code **/
+
+duplicateCode(
+ unique int id : @duplication,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+similarCode(
+ unique int id : @similarity,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+@duplication_or_similarity = @duplication | @similarity;
+
+tokens(
+ int id : @duplication_or_similarity ref,
+ int offset : int ref,
+ int beginLine : int ref,
+ int beginColumn : int ref,
+ int endLine : int ref,
+ int endColumn : int ref);
+
+/** External data **/
+
+externalData(
+ int id : @externalDataElement,
+ varchar(900) path : string ref,
+ int column: int ref,
+ varchar(900) value : string ref
+);
+
+snapshotDate(unique date snapshotDate : date ref);
+
+sourceLocationPrefix(varchar(900) prefix : string ref);
+
+/** Overlay support **/
+
+databaseMetadata(
+ string metadataKey: string ref,
+ string value: string ref
+);
+
+overlayChangedFiles(
+ string path: string ref
+);
+
+
+/*
+ * XML Files
+ */
+
+xmlEncoding(
+ unique int id: @file ref,
+ string encoding: string ref
+);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref
+);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref
+);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref
+);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref
+);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref
+);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref
+);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref
+);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref
+);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+compilations(unique int id: @compilation, string cwd: string ref);
+
+#keyset[id, num]
+compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
+
+#keyset[id, num, kind]
+compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
+
+diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
+
+compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
+
+#keyset[id, num]
+compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
+
+diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
+ string full_error_message: string ref, int location: @location ref);
+
+locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
+ int endLine: int ref, int endColumn: int ref);
+
+numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
+
+files(unique int id: @file, string name: string ref);
+
+folders(unique int id: @folder, string name: string ref);
+
+containerparent(int parent: @container ref, unique int child: @container ref);
+
+has_location(unique int locatable: @locatable ref, int location: @location ref);
+
+#keyset[parent, idx]
+comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
+
+comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
+
+doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
+
+#keyset[parent, idx]
+exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
+
+literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
+
+constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
+
+fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
+
+typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
+
+scopes(unique int id: @scope, int kind: int ref);
+
+scopenesting(unique int inner: @scope ref, int outer: @scope ref);
+
+scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
+
+objects(unique int id: @object, int kind: int ref, string name: string ref);
+
+objectscopes(unique int object: @object ref, int scope: @scope ref);
+
+objecttypes(unique int object: @object ref, int tp: @type ref);
+
+methodreceivers(unique int method: @object ref, int receiver: @object ref);
+
+fieldstructs(unique int field: @object ref, int struct: @structtype ref);
+
+methodhosts(int method: @object ref, int host: @definedtype ref);
+
+defs(int ident: @ident ref, int object: @object ref);
+
+uses(int ident: @ident ref, int object: @object ref);
+
+types(unique int id: @type, int kind: int ref);
+
+type_of(unique int expr: @expr ref, int tp: @type ref);
+
+typename(unique int tp: @type ref, string name: string ref);
+
+key_type(unique int map: @maptype ref, int tp: @type ref);
+
+element_type(unique int container: @containertype ref, int tp: @type ref);
+
+base_type(unique int ptr: @pointertype ref, int tp: @type ref);
+
+underlying_type(unique int defined: @definedtype ref, int tp: @type ref);
+
+#keyset[parent, index]
+component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
+
+#keyset[parent, index]
+struct_tags(int parent: @structtype ref, int index: int ref, string tag: string ref);
+
+#keyset[interface, index]
+interface_private_method_ids(int interface: @interfacetype ref, int index: int ref, string id: string ref);
+
+array_length(unique int tp: @arraytype ref, string len: string ref);
+
+type_objects(unique int tp: @type ref, int object: @object ref);
+
+packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
+
+#keyset[parent, idx]
+modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
+
+#keyset[package, idx]
+errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
+ string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
+
+has_ellipsis(int id: @callorconversionexpr ref);
+
+variadic(int id: @signaturetype ref);
+
+#keyset[parent, idx, is_from_recv]
+typeparam(unique int tp: @typeparamtype ref, string name: string ref,
+ int bound: @compositetype ref, int parent: @typeparamparentobject ref, int idx: int ref, boolean is_from_recv: boolean ref);
+
+@container = @file | @folder;
+
+@locatable = @xmllocatable | @node | @localscope;
+
+@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
+ | @scopenode | @comment_group | @comment;
+
+@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
+
+@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
+
+@modexprparent = @file | @modexpr;
+
+@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
+
+@stmtparent = @funcdef | @stmt | @decl;
+
+@declparent = @file | @declstmt;
+
+@typeparamdeclparent = @funcdecl | @typespec;
+
+@funcdef = @funclit | @funcdecl;
+
+@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
+
+@location = @location_default;
+
+@sourceline = @locatable;
+
+case @comment.kind of
+ 0 = @slashslashcomment
+| 1 = @slashstarcomment;
+
+case @expr.kind of
+ 0 = @badexpr
+| 1 = @ident
+| 2 = @ellipsis
+| 3 = @intlit
+| 4 = @floatlit
+| 5 = @imaglit
+| 6 = @charlit
+| 7 = @stringlit
+| 8 = @funclit
+| 9 = @compositelit
+| 10 = @parenexpr
+| 11 = @selectorexpr
+| 12 = @indexexpr
+| 13 = @genericfunctioninstantiationexpr
+| 14 = @generictypeinstantiationexpr
+| 15 = @sliceexpr
+| 16 = @typeassertexpr
+| 17 = @callorconversionexpr
+| 18 = @starexpr
+| 19 = @keyvalueexpr
+| 20 = @arraytypeexpr
+| 21 = @structtypeexpr
+| 22 = @functypeexpr
+| 23 = @interfacetypeexpr
+| 24 = @maptypeexpr
+| 25 = @typesetliteralexpr
+| 26 = @plusexpr
+| 27 = @minusexpr
+| 28 = @notexpr
+| 29 = @complementexpr
+| 30 = @derefexpr
+| 31 = @addressexpr
+| 32 = @arrowexpr
+| 33 = @lorexpr
+| 34 = @landexpr
+| 35 = @eqlexpr
+| 36 = @neqexpr
+| 37 = @lssexpr
+| 38 = @leqexpr
+| 39 = @gtrexpr
+| 40 = @geqexpr
+| 41 = @addexpr
+| 42 = @subexpr
+| 43 = @orexpr
+| 44 = @xorexpr
+| 45 = @mulexpr
+| 46 = @quoexpr
+| 47 = @remexpr
+| 48 = @shlexpr
+| 49 = @shrexpr
+| 50 = @andexpr
+| 51 = @andnotexpr
+| 52 = @sendchantypeexpr
+| 53 = @recvchantypeexpr
+| 54 = @sendrcvchantypeexpr;
+
+@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
+
+@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
+
+@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
+
+@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
+
+@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
+
+@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
+
+@logicalunaryexpr = @notexpr;
+
+@bitwiseunaryexpr = @complementexpr;
+
+@arithmeticunaryexpr = @plusexpr | @minusexpr;
+
+@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
+
+@logicalbinaryexpr = @lorexpr | @landexpr;
+
+@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
+
+@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
+
+@shiftexpr = @shlexpr | @shrexpr;
+
+@comparison = @equalitytest | @relationalcomparison;
+
+@equalitytest = @eqlexpr | @neqexpr;
+
+@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
+
+@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
+
+case @stmt.kind of
+ 0 = @badstmt
+| 1 = @declstmt
+| 2 = @emptystmt
+| 3 = @labeledstmt
+| 4 = @exprstmt
+| 5 = @sendstmt
+| 6 = @incstmt
+| 7 = @decstmt
+| 8 = @gostmt
+| 9 = @deferstmt
+| 10 = @returnstmt
+| 11 = @breakstmt
+| 12 = @continuestmt
+| 13 = @gotostmt
+| 14 = @fallthroughstmt
+| 15 = @blockstmt
+| 16 = @ifstmt
+| 17 = @caseclause
+| 18 = @exprswitchstmt
+| 19 = @typeswitchstmt
+| 20 = @commclause
+| 21 = @selectstmt
+| 22 = @forstmt
+| 23 = @rangestmt
+| 24 = @assignstmt
+| 25 = @definestmt
+| 26 = @addassignstmt
+| 27 = @subassignstmt
+| 28 = @mulassignstmt
+| 29 = @quoassignstmt
+| 30 = @remassignstmt
+| 31 = @andassignstmt
+| 32 = @orassignstmt
+| 33 = @xorassignstmt
+| 34 = @shlassignstmt
+| 35 = @shrassignstmt
+| 36 = @andnotassignstmt;
+
+@incdecstmt = @incstmt | @decstmt;
+
+@assignment = @simpleassignstmt | @compoundassignstmt;
+
+@simpleassignstmt = @assignstmt | @definestmt;
+
+@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
+ | @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
+
+@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
+
+@switchstmt = @exprswitchstmt | @typeswitchstmt;
+
+@loopstmt = @forstmt | @rangestmt;
+
+case @decl.kind of
+ 0 = @baddecl
+| 1 = @importdecl
+| 2 = @constdecl
+| 3 = @typedecl
+| 4 = @vardecl
+| 5 = @funcdecl;
+
+@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
+
+case @spec.kind of
+ 0 = @importspec
+| 1 = @valuespec
+| 2 = @typedefspec
+| 3 = @aliasspec;
+
+@typespec = @typedefspec | @aliasspec;
+
+case @object.kind of
+ 0 = @pkgobject
+| 1 = @decltypeobject
+| 2 = @builtintypeobject
+| 3 = @declconstobject
+| 4 = @builtinconstobject
+| 5 = @declvarobject
+| 6 = @declfunctionobject
+| 7 = @builtinfunctionobject
+| 8 = @labelobject;
+
+@typeparamparentobject = @decltypeobject | @declfunctionobject;
+
+@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
+
+@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
+
+@typeobject = @decltypeobject | @builtintypeobject;
+
+@valueobject = @constobject | @varobject | @functionobject;
+
+@constobject = @declconstobject | @builtinconstobject;
+
+@varobject = @declvarobject;
+
+@functionobject = @declfunctionobject | @builtinfunctionobject;
+
+case @scope.kind of
+ 0 = @universescope
+| 1 = @packagescope
+| 2 = @localscope;
+
+case @type.kind of
+ 0 = @invalidtype
+| 1 = @boolexprtype
+| 2 = @inttype
+| 3 = @int8type
+| 4 = @int16type
+| 5 = @int32type
+| 6 = @int64type
+| 7 = @uinttype
+| 8 = @uint8type
+| 9 = @uint16type
+| 10 = @uint32type
+| 11 = @uint64type
+| 12 = @uintptrtype
+| 13 = @float32type
+| 14 = @float64type
+| 15 = @complex64type
+| 16 = @complex128type
+| 17 = @stringexprtype
+| 18 = @unsafepointertype
+| 19 = @boolliteraltype
+| 20 = @intliteraltype
+| 21 = @runeliteraltype
+| 22 = @floatliteraltype
+| 23 = @complexliteraltype
+| 24 = @stringliteraltype
+| 25 = @nilliteraltype
+| 26 = @typeparamtype
+| 27 = @arraytype
+| 28 = @slicetype
+| 29 = @structtype
+| 30 = @pointertype
+| 31 = @interfacetype
+| 32 = @tupletype
+| 33 = @signaturetype
+| 34 = @maptype
+| 35 = @sendchantype
+| 36 = @recvchantype
+| 37 = @sendrcvchantype
+| 38 = @definedtype
+| 39 = @typesetliteraltype;
+
+@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
+
+@booltype = @boolexprtype | @boolliteraltype;
+
+@numerictype = @integertype | @floattype | @complextype;
+
+@integertype = @signedintegertype | @unsignedintegertype;
+
+@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
+
+@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
+
+@floattype = @float32type | @float64type | @floatliteraltype;
+
+@complextype = @complex64type | @complex128type | @complexliteraltype;
+
+@stringtype = @stringexprtype | @stringliteraltype;
+
+@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
+ | @stringliteraltype | @nilliteraltype;
+
+@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
+ | @signaturetype | @definedtype | @typesetliteraltype;
+
+@containertype = @arraytype | @slicetype | @maptype | @chantype;
+
+@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
+
+case @modexpr.kind of
+ 0 = @modcommentblock
+| 1 = @modline
+| 2 = @modlineblock
+| 3 = @modlparen
+| 4 = @modrparen;
+
+case @error.kind of
+ 0 = @unknownerror
+| 1 = @listerror
+| 2 = @parseerror
+| 3 = @typeerror;
+
diff --git a/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/typeparam.ql b/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/typeparam.ql
new file mode 100644
index 000000000000..ad7685ac16a2
--- /dev/null
+++ b/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/typeparam.ql
@@ -0,0 +1,17 @@
+class TypeParamType extends @typeparamtype {
+ string toString() { none() }
+}
+
+class CompositeType extends @compositetype {
+ string toString() { none() }
+}
+
+class TypeParamParentObject extends @typeparamparentobject {
+ string toString() { none() }
+}
+
+from
+ TypeParamType tp, string name, CompositeType bound, TypeParamParentObject parent, int idx,
+ boolean is_from_recv
+where typeparam(tp, name, bound, parent, idx, is_from_recv)
+select tp, name, bound, parent, idx
diff --git a/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/upgrade.properties b/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/upgrade.properties
new file mode 100644
index 000000000000..d383bdf4ad30
--- /dev/null
+++ b/go/downgrades/5ff5325d274ae4f86defa195577bc7c1370b72fa/upgrade.properties
@@ -0,0 +1,3 @@
+description: Track whether a type parameter is from a receiver
+compatibility: partial
+typeparam.rel: run typeparam.qlo
diff --git a/go/extractor/dbscheme/dbscheme.go b/go/extractor/dbscheme/dbscheme.go
index 550c7920c711..45aea39b4e54 100644
--- a/go/extractor/dbscheme/dbscheme.go
+++ b/go/extractor/dbscheme/dbscheme.go
@@ -277,6 +277,11 @@ func FloatColumn(columnName string) Column {
return Column{columnName, FLOAT, false, true}
}
+// BooleanColumn constructs a column with name `columnName` holding boolean values
+func BooleanColumn(columnName string) Column {
+ return Column{columnName, BOOLEAN, false, true}
+}
+
// A Table represents a database table
type Table struct {
name string
diff --git a/go/extractor/dbscheme/tables.go b/go/extractor/dbscheme/tables.go
index 9c537fbaf89f..b72c33795182 100644
--- a/go/extractor/dbscheme/tables.go
+++ b/go/extractor/dbscheme/tables.go
@@ -1241,4 +1241,5 @@ var TypeParamTable = NewTable("typeparam",
EntityColumn(CompositeType, "bound"),
EntityColumn(TypeParamParentObjectType, "parent"),
IntColumn("idx"),
-).KeySet("parent", "idx")
+ BooleanColumn("is_from_recv"),
+).KeySet("parent", "idx", "is_from_recv")
diff --git a/go/extractor/extractor.go b/go/extractor/extractor.go
index 0e7fd199e7ce..8c2178376141 100644
--- a/go/extractor/extractor.go
+++ b/go/extractor/extractor.go
@@ -32,7 +32,13 @@ import (
)
var MaxGoRoutines int
-var typeParamParent map[*types.TypeParam]types.Object = make(map[*types.TypeParam]types.Object)
+
+type typeParamParentEntry struct {
+ parent types.Object
+ isFromReceiver bool
+}
+
+var typeParamParent map[*types.TypeParam]typeParamParentEntry = make(map[*types.TypeParam]typeParamParentEntry)
func init() {
// this sets the number of threads that the Go runtime will spawn; this is separate
@@ -530,8 +536,7 @@ func extractObjects(tw *trap.Writer, scope *types.Scope, scopeLabel trap.Label)
// do not appear as objects in any scope, so they have to be dealt
// with separately in extractMethods.
if funcObj, ok := obj.(*types.Func); ok {
- populateTypeParamParents(funcObj.Type().(*types.Signature).TypeParams(), obj)
- populateTypeParamParents(funcObj.Type().(*types.Signature).RecvTypeParams(), obj)
+ populateTypeParamParentsFromFunction(funcObj)
}
// Populate type parameter parents for defined types and alias types.
if typeNameObj, ok := obj.(*types.TypeName); ok {
@@ -542,9 +547,9 @@ func extractObjects(tw *trap.Writer, scope *types.Scope, scopeLabel trap.Label)
// careful with alias types because before Go 1.24 they would
// return the underlying type.
if tp, ok := typeNameObj.Type().(*types.Named); ok && !typeNameObj.IsAlias() {
- populateTypeParamParents(tp.TypeParams(), obj)
+ populateTypeParamParents(tp.TypeParams(), obj, false)
} else if tp, ok := typeNameObj.Type().(*types.Alias); ok {
- populateTypeParamParents(tp.TypeParams(), obj)
+ populateTypeParamParents(tp.TypeParams(), obj, false)
}
}
extractObject(tw, obj, lbl)
@@ -570,8 +575,7 @@ func extractMethod(tw *trap.Writer, meth *types.Func) trap.Label {
if !exists {
// Populate type parameter parents for methods. They do not appear as
// objects in any scope, so they have to be dealt with separately here.
- populateTypeParamParents(meth.Type().(*types.Signature).TypeParams(), meth)
- populateTypeParamParents(meth.Type().(*types.Signature).RecvTypeParams(), meth)
+ populateTypeParamParentsFromFunction(meth)
extractObject(tw, meth, methlbl)
}
@@ -1677,9 +1681,9 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
}
case *types.TypeParam:
kind = dbscheme.TypeParamType.Index()
- parentlbl := getTypeParamParentLabel(tw, tp)
+ parentlbl, isReceiverChild := getTypeParamParentLabel(tw, tp)
constraintLabel := extractType(tw, tp.Constraint())
- dbscheme.TypeParamTable.Emit(tw, lbl, tp.Obj().Name(), constraintLabel, parentlbl, tp.Index())
+ dbscheme.TypeParamTable.Emit(tw, lbl, tp.Obj().Name(), constraintLabel, parentlbl, tp.Index(), isReceiverChild)
case *types.Union:
kind = dbscheme.TypeSetLiteral.Index()
for i := 0; i < tp.Len(); i++ {
@@ -1819,9 +1823,9 @@ func getTypeLabel(tw *trap.Writer, tp types.Type) (trap.Label, bool) {
}
lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%s};definedtype", entitylbl))
case *types.TypeParam:
- parentlbl := getTypeParamParentLabel(tw, tp)
+ parentlbl, isReceiverChild := getTypeParamParentLabel(tw, tp)
idx := tp.Index()
- lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%v},%d,%s;typeparamtype", parentlbl, idx, tp.Obj().Name()))
+ lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%v},%d,%t,%s;typeparamtype", parentlbl, idx, isReceiverChild, tp.Obj().Name()))
case *types.Union:
var b strings.Builder
for i := 0; i < tp.Len(); i++ {
@@ -2005,11 +2009,18 @@ func extractTypeParamDecls(tw *trap.Writer, fields *ast.FieldList, parent trap.L
}
}
+func populateTypeParamParentsFromFunction(funcObj *types.Func) {
+ signature := funcObj.Type().(*types.Signature)
+ populateTypeParamParents(signature.RecvTypeParams(), funcObj, true)
+ populateTypeParamParents(signature.TypeParams(), funcObj, false)
+}
+
// populateTypeParamParents sets `parent` as the parent of the elements of `typeparams`
-func populateTypeParamParents(typeparams *types.TypeParamList, parent types.Object) {
+// and records whether elements are defined in a receiver.
+func populateTypeParamParents(typeparams *types.TypeParamList, parent types.Object, isFromReceiver bool) {
if typeparams != nil {
- for idx := 0; idx < typeparams.Len(); idx++ {
- setTypeParamParent(typeparams.At(idx), parent)
+ for tparam := range typeparams.TypeParams() {
+ setTypeParamParent(tparam, parent, isFromReceiver)
}
}
}
@@ -2028,24 +2039,26 @@ func getObjectBeingUsed(tw *trap.Writer, ident *ast.Ident) types.Object {
}
}
-func getTypeParamParentLabel(tw *trap.Writer, tp *types.TypeParam) trap.Label {
- parent, exists := typeParamParent[tp]
+func getTypeParamParentLabel(tw *trap.Writer, tp *types.TypeParam) (trap.Label, bool) {
+ entry, exists := typeParamParent[tp]
if !exists {
log.Fatalf("Parent of type parameter does not exist: %s %s", tp.String(), tp.Constraint().String())
}
- parentlbl, _ := tw.Labeler.ScopedObjectID(parent, func() trap.Label {
+ parentlbl, _ := tw.Labeler.ScopedObjectID(entry.parent, func() trap.Label {
log.Fatalf("getTypeLabel() called for parent of type parameter %s", tp.String())
return trap.InvalidLabel
})
- return parentlbl
+ return parentlbl, entry.isFromReceiver
}
-func setTypeParamParent(tp *types.TypeParam, newobj types.Object) {
- obj, exists := typeParamParent[tp]
+func setTypeParamParent(tp *types.TypeParam, parent types.Object, isFromReceiver bool) {
+ entry, exists := typeParamParent[tp]
+ newEntry := typeParamParentEntry{parent, isFromReceiver}
if !exists {
- typeParamParent[tp] = newobj
- } else if newobj != obj {
- log.Fatalf("Parent of type parameter '%s %s' being set to a different value: '%s' vs '%s'", tp.String(), tp.Constraint().String(), obj, newobj)
+ typeParamParent[tp] = newEntry
+ } else if entry != newEntry {
+ log.Fatalf("Parent of type parameter '%s %s' being set to a different value: {'%s', %t}' vs {'%s', %t}",
+ tp.String(), tp.Constraint().String(), entry.parent, entry.isFromReceiver, parent, isFromReceiver)
}
}
diff --git a/go/extractor/trap/trapwriter.go b/go/extractor/trap/trapwriter.go
index c565f343665b..fa7436be48bf 100644
--- a/go/extractor/trap/trapwriter.go
+++ b/go/extractor/trap/trapwriter.go
@@ -165,6 +165,8 @@ func (tw *Writer) Emit(table string, values []interface{}) error {
fmt.Fprintf(tw.wzip, "%d", value)
case float64:
fmt.Fprintf(tw.wzip, "%e", value)
+ case bool:
+ fmt.Fprintf(tw.wzip, "%t", value)
default:
return errors.New("Cannot emit value")
}
diff --git a/go/ql/lib/go.dbscheme b/go/ql/lib/go.dbscheme
index b1341734d687..5ff5325d274a 100644
--- a/go/ql/lib/go.dbscheme
+++ b/go/ql/lib/go.dbscheme
@@ -244,9 +244,9 @@ has_ellipsis(int id: @callorconversionexpr ref);
variadic(int id: @signaturetype ref);
-#keyset[parent, idx]
-typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
- int parent: @typeparamparentobject ref, int idx: int ref);
+#keyset[parent, idx, is_from_recv]
+typeparam(unique int tp: @typeparamtype ref, string name: string ref,
+ int bound: @compositetype ref, int parent: @typeparamparentobject ref, int idx: int ref, boolean is_from_recv: boolean ref);
@container = @file | @folder;
diff --git a/go/ql/lib/go.dbscheme.stats b/go/ql/lib/go.dbscheme.stats
index 126bbff00f7f..dd9440b09982 100644
--- a/go/ql/lib/go.dbscheme.stats
+++ b/go/ql/lib/go.dbscheme.stats
@@ -17791,6 +17791,10 @@
idx
3126
+
+ is_from_recv
+ 0
+
diff --git a/go/ql/lib/semmle/go/Types.qll b/go/ql/lib/semmle/go/Types.qll
index 574d75685439..1ea5b5c65c1d 100644
--- a/go/ql/lib/semmle/go/Types.qll
+++ b/go/ql/lib/semmle/go/Types.qll
@@ -382,18 +382,21 @@ class CompositeType extends @compositetype, Type { }
/** A type that comes from a type parameter. */
class TypeParamType extends @typeparamtype, CompositeType {
/** Gets the name of this type parameter type. */
- string getParamName() { typeparam(this, result, _, _, _) }
+ string getParamName() { typeparam(this, result, _, _, _, _) }
/** Gets the constraint of this type parameter type. */
- Type getConstraint() { typeparam(this, _, result, _, _) }
+ Type getConstraint() { typeparam(this, _, result, _, _, _) }
override InterfaceType getUnderlyingType() { result = this.getConstraint().getUnderlyingType() }
/** Gets the parent object of this type parameter type. */
- TypeParamParentEntity getParent() { typeparam(this, _, _, result, _) }
+ TypeParamParentEntity getParent() { typeparam(this, _, _, result, _, _) }
/** Gets the index of this type parameter type. */
- int getIndex() { typeparam(this, _, _, _, result) }
+ int getIndex() { typeparam(this, _, _, _, result, _) }
+
+ /** Holds if this type parameter type is declared as part of a receiver */
+ predicate isFromReceiver() { typeparam(this, _, _, _, _, true) }
override string pp() { result = this.getParamName() }
diff --git a/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/go.dbscheme b/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/go.dbscheme
new file mode 100644
index 000000000000..5ff5325d274a
--- /dev/null
+++ b/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/go.dbscheme
@@ -0,0 +1,563 @@
+/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */
+
+
+/** Duplicate code **/
+
+duplicateCode(
+ unique int id : @duplication,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+similarCode(
+ unique int id : @similarity,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+@duplication_or_similarity = @duplication | @similarity;
+
+tokens(
+ int id : @duplication_or_similarity ref,
+ int offset : int ref,
+ int beginLine : int ref,
+ int beginColumn : int ref,
+ int endLine : int ref,
+ int endColumn : int ref);
+
+/** External data **/
+
+externalData(
+ int id : @externalDataElement,
+ varchar(900) path : string ref,
+ int column: int ref,
+ varchar(900) value : string ref
+);
+
+snapshotDate(unique date snapshotDate : date ref);
+
+sourceLocationPrefix(varchar(900) prefix : string ref);
+
+/** Overlay support **/
+
+databaseMetadata(
+ string metadataKey: string ref,
+ string value: string ref
+);
+
+overlayChangedFiles(
+ string path: string ref
+);
+
+
+/*
+ * XML Files
+ */
+
+xmlEncoding(
+ unique int id: @file ref,
+ string encoding: string ref
+);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref
+);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref
+);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref
+);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref
+);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref
+);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref
+);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref
+);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref
+);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+compilations(unique int id: @compilation, string cwd: string ref);
+
+#keyset[id, num]
+compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
+
+#keyset[id, num, kind]
+compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
+
+diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
+
+compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
+
+#keyset[id, num]
+compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
+
+diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
+ string full_error_message: string ref, int location: @location ref);
+
+locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
+ int endLine: int ref, int endColumn: int ref);
+
+numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
+
+files(unique int id: @file, string name: string ref);
+
+folders(unique int id: @folder, string name: string ref);
+
+containerparent(int parent: @container ref, unique int child: @container ref);
+
+has_location(unique int locatable: @locatable ref, int location: @location ref);
+
+#keyset[parent, idx]
+comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
+
+comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
+
+doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
+
+#keyset[parent, idx]
+exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
+
+literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
+
+constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
+
+fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
+
+typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
+
+scopes(unique int id: @scope, int kind: int ref);
+
+scopenesting(unique int inner: @scope ref, int outer: @scope ref);
+
+scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
+
+objects(unique int id: @object, int kind: int ref, string name: string ref);
+
+objectscopes(unique int object: @object ref, int scope: @scope ref);
+
+objecttypes(unique int object: @object ref, int tp: @type ref);
+
+methodreceivers(unique int method: @object ref, int receiver: @object ref);
+
+fieldstructs(unique int field: @object ref, int struct: @structtype ref);
+
+methodhosts(int method: @object ref, int host: @definedtype ref);
+
+defs(int ident: @ident ref, int object: @object ref);
+
+uses(int ident: @ident ref, int object: @object ref);
+
+types(unique int id: @type, int kind: int ref);
+
+type_of(unique int expr: @expr ref, int tp: @type ref);
+
+typename(unique int tp: @type ref, string name: string ref);
+
+key_type(unique int map: @maptype ref, int tp: @type ref);
+
+element_type(unique int container: @containertype ref, int tp: @type ref);
+
+base_type(unique int ptr: @pointertype ref, int tp: @type ref);
+
+underlying_type(unique int defined: @definedtype ref, int tp: @type ref);
+
+#keyset[parent, index]
+component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
+
+#keyset[parent, index]
+struct_tags(int parent: @structtype ref, int index: int ref, string tag: string ref);
+
+#keyset[interface, index]
+interface_private_method_ids(int interface: @interfacetype ref, int index: int ref, string id: string ref);
+
+array_length(unique int tp: @arraytype ref, string len: string ref);
+
+type_objects(unique int tp: @type ref, int object: @object ref);
+
+packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
+
+#keyset[parent, idx]
+modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
+
+#keyset[package, idx]
+errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
+ string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
+
+has_ellipsis(int id: @callorconversionexpr ref);
+
+variadic(int id: @signaturetype ref);
+
+#keyset[parent, idx, is_from_recv]
+typeparam(unique int tp: @typeparamtype ref, string name: string ref,
+ int bound: @compositetype ref, int parent: @typeparamparentobject ref, int idx: int ref, boolean is_from_recv: boolean ref);
+
+@container = @file | @folder;
+
+@locatable = @xmllocatable | @node | @localscope;
+
+@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
+ | @scopenode | @comment_group | @comment;
+
+@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
+
+@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
+
+@modexprparent = @file | @modexpr;
+
+@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
+
+@stmtparent = @funcdef | @stmt | @decl;
+
+@declparent = @file | @declstmt;
+
+@typeparamdeclparent = @funcdecl | @typespec;
+
+@funcdef = @funclit | @funcdecl;
+
+@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
+
+@location = @location_default;
+
+@sourceline = @locatable;
+
+case @comment.kind of
+ 0 = @slashslashcomment
+| 1 = @slashstarcomment;
+
+case @expr.kind of
+ 0 = @badexpr
+| 1 = @ident
+| 2 = @ellipsis
+| 3 = @intlit
+| 4 = @floatlit
+| 5 = @imaglit
+| 6 = @charlit
+| 7 = @stringlit
+| 8 = @funclit
+| 9 = @compositelit
+| 10 = @parenexpr
+| 11 = @selectorexpr
+| 12 = @indexexpr
+| 13 = @genericfunctioninstantiationexpr
+| 14 = @generictypeinstantiationexpr
+| 15 = @sliceexpr
+| 16 = @typeassertexpr
+| 17 = @callorconversionexpr
+| 18 = @starexpr
+| 19 = @keyvalueexpr
+| 20 = @arraytypeexpr
+| 21 = @structtypeexpr
+| 22 = @functypeexpr
+| 23 = @interfacetypeexpr
+| 24 = @maptypeexpr
+| 25 = @typesetliteralexpr
+| 26 = @plusexpr
+| 27 = @minusexpr
+| 28 = @notexpr
+| 29 = @complementexpr
+| 30 = @derefexpr
+| 31 = @addressexpr
+| 32 = @arrowexpr
+| 33 = @lorexpr
+| 34 = @landexpr
+| 35 = @eqlexpr
+| 36 = @neqexpr
+| 37 = @lssexpr
+| 38 = @leqexpr
+| 39 = @gtrexpr
+| 40 = @geqexpr
+| 41 = @addexpr
+| 42 = @subexpr
+| 43 = @orexpr
+| 44 = @xorexpr
+| 45 = @mulexpr
+| 46 = @quoexpr
+| 47 = @remexpr
+| 48 = @shlexpr
+| 49 = @shrexpr
+| 50 = @andexpr
+| 51 = @andnotexpr
+| 52 = @sendchantypeexpr
+| 53 = @recvchantypeexpr
+| 54 = @sendrcvchantypeexpr;
+
+@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
+
+@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
+
+@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
+
+@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
+
+@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
+
+@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
+
+@logicalunaryexpr = @notexpr;
+
+@bitwiseunaryexpr = @complementexpr;
+
+@arithmeticunaryexpr = @plusexpr | @minusexpr;
+
+@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
+
+@logicalbinaryexpr = @lorexpr | @landexpr;
+
+@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
+
+@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
+
+@shiftexpr = @shlexpr | @shrexpr;
+
+@comparison = @equalitytest | @relationalcomparison;
+
+@equalitytest = @eqlexpr | @neqexpr;
+
+@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
+
+@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
+
+case @stmt.kind of
+ 0 = @badstmt
+| 1 = @declstmt
+| 2 = @emptystmt
+| 3 = @labeledstmt
+| 4 = @exprstmt
+| 5 = @sendstmt
+| 6 = @incstmt
+| 7 = @decstmt
+| 8 = @gostmt
+| 9 = @deferstmt
+| 10 = @returnstmt
+| 11 = @breakstmt
+| 12 = @continuestmt
+| 13 = @gotostmt
+| 14 = @fallthroughstmt
+| 15 = @blockstmt
+| 16 = @ifstmt
+| 17 = @caseclause
+| 18 = @exprswitchstmt
+| 19 = @typeswitchstmt
+| 20 = @commclause
+| 21 = @selectstmt
+| 22 = @forstmt
+| 23 = @rangestmt
+| 24 = @assignstmt
+| 25 = @definestmt
+| 26 = @addassignstmt
+| 27 = @subassignstmt
+| 28 = @mulassignstmt
+| 29 = @quoassignstmt
+| 30 = @remassignstmt
+| 31 = @andassignstmt
+| 32 = @orassignstmt
+| 33 = @xorassignstmt
+| 34 = @shlassignstmt
+| 35 = @shrassignstmt
+| 36 = @andnotassignstmt;
+
+@incdecstmt = @incstmt | @decstmt;
+
+@assignment = @simpleassignstmt | @compoundassignstmt;
+
+@simpleassignstmt = @assignstmt | @definestmt;
+
+@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
+ | @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
+
+@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
+
+@switchstmt = @exprswitchstmt | @typeswitchstmt;
+
+@loopstmt = @forstmt | @rangestmt;
+
+case @decl.kind of
+ 0 = @baddecl
+| 1 = @importdecl
+| 2 = @constdecl
+| 3 = @typedecl
+| 4 = @vardecl
+| 5 = @funcdecl;
+
+@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
+
+case @spec.kind of
+ 0 = @importspec
+| 1 = @valuespec
+| 2 = @typedefspec
+| 3 = @aliasspec;
+
+@typespec = @typedefspec | @aliasspec;
+
+case @object.kind of
+ 0 = @pkgobject
+| 1 = @decltypeobject
+| 2 = @builtintypeobject
+| 3 = @declconstobject
+| 4 = @builtinconstobject
+| 5 = @declvarobject
+| 6 = @declfunctionobject
+| 7 = @builtinfunctionobject
+| 8 = @labelobject;
+
+@typeparamparentobject = @decltypeobject | @declfunctionobject;
+
+@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
+
+@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
+
+@typeobject = @decltypeobject | @builtintypeobject;
+
+@valueobject = @constobject | @varobject | @functionobject;
+
+@constobject = @declconstobject | @builtinconstobject;
+
+@varobject = @declvarobject;
+
+@functionobject = @declfunctionobject | @builtinfunctionobject;
+
+case @scope.kind of
+ 0 = @universescope
+| 1 = @packagescope
+| 2 = @localscope;
+
+case @type.kind of
+ 0 = @invalidtype
+| 1 = @boolexprtype
+| 2 = @inttype
+| 3 = @int8type
+| 4 = @int16type
+| 5 = @int32type
+| 6 = @int64type
+| 7 = @uinttype
+| 8 = @uint8type
+| 9 = @uint16type
+| 10 = @uint32type
+| 11 = @uint64type
+| 12 = @uintptrtype
+| 13 = @float32type
+| 14 = @float64type
+| 15 = @complex64type
+| 16 = @complex128type
+| 17 = @stringexprtype
+| 18 = @unsafepointertype
+| 19 = @boolliteraltype
+| 20 = @intliteraltype
+| 21 = @runeliteraltype
+| 22 = @floatliteraltype
+| 23 = @complexliteraltype
+| 24 = @stringliteraltype
+| 25 = @nilliteraltype
+| 26 = @typeparamtype
+| 27 = @arraytype
+| 28 = @slicetype
+| 29 = @structtype
+| 30 = @pointertype
+| 31 = @interfacetype
+| 32 = @tupletype
+| 33 = @signaturetype
+| 34 = @maptype
+| 35 = @sendchantype
+| 36 = @recvchantype
+| 37 = @sendrcvchantype
+| 38 = @definedtype
+| 39 = @typesetliteraltype;
+
+@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
+
+@booltype = @boolexprtype | @boolliteraltype;
+
+@numerictype = @integertype | @floattype | @complextype;
+
+@integertype = @signedintegertype | @unsignedintegertype;
+
+@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
+
+@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
+
+@floattype = @float32type | @float64type | @floatliteraltype;
+
+@complextype = @complex64type | @complex128type | @complexliteraltype;
+
+@stringtype = @stringexprtype | @stringliteraltype;
+
+@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
+ | @stringliteraltype | @nilliteraltype;
+
+@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
+ | @signaturetype | @definedtype | @typesetliteraltype;
+
+@containertype = @arraytype | @slicetype | @maptype | @chantype;
+
+@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
+
+case @modexpr.kind of
+ 0 = @modcommentblock
+| 1 = @modline
+| 2 = @modlineblock
+| 3 = @modlparen
+| 4 = @modrparen;
+
+case @error.kind of
+ 0 = @unknownerror
+| 1 = @listerror
+| 2 = @parseerror
+| 3 = @typeerror;
+
diff --git a/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/old.dbscheme b/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/old.dbscheme
new file mode 100644
index 000000000000..b1341734d687
--- /dev/null
+++ b/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/old.dbscheme
@@ -0,0 +1,563 @@
+/** Auto-generated dbscheme; do not edit. Run `make gen` in directory `go/` to regenerate. */
+
+
+/** Duplicate code **/
+
+duplicateCode(
+ unique int id : @duplication,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+similarCode(
+ unique int id : @similarity,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+@duplication_or_similarity = @duplication | @similarity;
+
+tokens(
+ int id : @duplication_or_similarity ref,
+ int offset : int ref,
+ int beginLine : int ref,
+ int beginColumn : int ref,
+ int endLine : int ref,
+ int endColumn : int ref);
+
+/** External data **/
+
+externalData(
+ int id : @externalDataElement,
+ varchar(900) path : string ref,
+ int column: int ref,
+ varchar(900) value : string ref
+);
+
+snapshotDate(unique date snapshotDate : date ref);
+
+sourceLocationPrefix(varchar(900) prefix : string ref);
+
+/** Overlay support **/
+
+databaseMetadata(
+ string metadataKey: string ref,
+ string value: string ref
+);
+
+overlayChangedFiles(
+ string path: string ref
+);
+
+
+/*
+ * XML Files
+ */
+
+xmlEncoding(
+ unique int id: @file ref,
+ string encoding: string ref
+);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref
+);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref
+);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref
+);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref
+);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref
+);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref
+);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref
+);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref
+);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+compilations(unique int id: @compilation, string cwd: string ref);
+
+#keyset[id, num]
+compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
+
+#keyset[id, num, kind]
+compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
+
+diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
+
+compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
+
+#keyset[id, num]
+compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file ref);
+
+diagnostics(unique int id: @diagnostic, int severity: int ref, string error_tag: string ref, string error_message: string ref,
+ string full_error_message: string ref, int location: @location ref);
+
+locations_default(unique int id: @location_default, int file: @file ref, int beginLine: int ref, int beginColumn: int ref,
+ int endLine: int ref, int endColumn: int ref);
+
+numlines(int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref);
+
+files(unique int id: @file, string name: string ref);
+
+folders(unique int id: @folder, string name: string ref);
+
+containerparent(int parent: @container ref, unique int child: @container ref);
+
+has_location(unique int locatable: @locatable ref, int location: @location ref);
+
+#keyset[parent, idx]
+comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
+
+comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
+
+doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
+
+#keyset[parent, idx]
+exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
+
+literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
+
+constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
+
+fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
+
+typeparamdecls(unique int id: @typeparamdecl, int parent: @typeparamdeclparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
+
+scopes(unique int id: @scope, int kind: int ref);
+
+scopenesting(unique int inner: @scope ref, int outer: @scope ref);
+
+scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
+
+objects(unique int id: @object, int kind: int ref, string name: string ref);
+
+objectscopes(unique int object: @object ref, int scope: @scope ref);
+
+objecttypes(unique int object: @object ref, int tp: @type ref);
+
+methodreceivers(unique int method: @object ref, int receiver: @object ref);
+
+fieldstructs(unique int field: @object ref, int struct: @structtype ref);
+
+methodhosts(int method: @object ref, int host: @definedtype ref);
+
+defs(int ident: @ident ref, int object: @object ref);
+
+uses(int ident: @ident ref, int object: @object ref);
+
+types(unique int id: @type, int kind: int ref);
+
+type_of(unique int expr: @expr ref, int tp: @type ref);
+
+typename(unique int tp: @type ref, string name: string ref);
+
+key_type(unique int map: @maptype ref, int tp: @type ref);
+
+element_type(unique int container: @containertype ref, int tp: @type ref);
+
+base_type(unique int ptr: @pointertype ref, int tp: @type ref);
+
+underlying_type(unique int defined: @definedtype ref, int tp: @type ref);
+
+#keyset[parent, index]
+component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
+
+#keyset[parent, index]
+struct_tags(int parent: @structtype ref, int index: int ref, string tag: string ref);
+
+#keyset[interface, index]
+interface_private_method_ids(int interface: @interfacetype ref, int index: int ref, string id: string ref);
+
+array_length(unique int tp: @arraytype ref, string len: string ref);
+
+type_objects(unique int tp: @type ref, int object: @object ref);
+
+packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
+
+#keyset[parent, idx]
+modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
+
+#keyset[package, idx]
+errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
+ string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
+
+has_ellipsis(int id: @callorconversionexpr ref);
+
+variadic(int id: @signaturetype ref);
+
+#keyset[parent, idx]
+typeparam(unique int tp: @typeparamtype ref, string name: string ref, int bound: @compositetype ref,
+ int parent: @typeparamparentobject ref, int idx: int ref);
+
+@container = @file | @folder;
+
+@locatable = @xmllocatable | @node | @localscope;
+
+@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @typeparamdeclparent
+ | @scopenode | @comment_group | @comment;
+
+@documentable = @file | @field | @typeparamdecl | @spec | @gendecl | @funcdecl | @modexpr;
+
+@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @typeparamdecl | @spec;
+
+@modexprparent = @file | @modexpr;
+
+@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
+
+@stmtparent = @funcdef | @stmt | @decl;
+
+@declparent = @file | @declstmt;
+
+@typeparamdeclparent = @funcdecl | @typespec;
+
+@funcdef = @funclit | @funcdecl;
+
+@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
+
+@location = @location_default;
+
+@sourceline = @locatable;
+
+case @comment.kind of
+ 0 = @slashslashcomment
+| 1 = @slashstarcomment;
+
+case @expr.kind of
+ 0 = @badexpr
+| 1 = @ident
+| 2 = @ellipsis
+| 3 = @intlit
+| 4 = @floatlit
+| 5 = @imaglit
+| 6 = @charlit
+| 7 = @stringlit
+| 8 = @funclit
+| 9 = @compositelit
+| 10 = @parenexpr
+| 11 = @selectorexpr
+| 12 = @indexexpr
+| 13 = @genericfunctioninstantiationexpr
+| 14 = @generictypeinstantiationexpr
+| 15 = @sliceexpr
+| 16 = @typeassertexpr
+| 17 = @callorconversionexpr
+| 18 = @starexpr
+| 19 = @keyvalueexpr
+| 20 = @arraytypeexpr
+| 21 = @structtypeexpr
+| 22 = @functypeexpr
+| 23 = @interfacetypeexpr
+| 24 = @maptypeexpr
+| 25 = @typesetliteralexpr
+| 26 = @plusexpr
+| 27 = @minusexpr
+| 28 = @notexpr
+| 29 = @complementexpr
+| 30 = @derefexpr
+| 31 = @addressexpr
+| 32 = @arrowexpr
+| 33 = @lorexpr
+| 34 = @landexpr
+| 35 = @eqlexpr
+| 36 = @neqexpr
+| 37 = @lssexpr
+| 38 = @leqexpr
+| 39 = @gtrexpr
+| 40 = @geqexpr
+| 41 = @addexpr
+| 42 = @subexpr
+| 43 = @orexpr
+| 44 = @xorexpr
+| 45 = @mulexpr
+| 46 = @quoexpr
+| 47 = @remexpr
+| 48 = @shlexpr
+| 49 = @shrexpr
+| 50 = @andexpr
+| 51 = @andnotexpr
+| 52 = @sendchantypeexpr
+| 53 = @recvchantypeexpr
+| 54 = @sendrcvchantypeexpr;
+
+@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
+
+@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
+
+@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
+
+@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
+
+@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
+
+@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
+
+@logicalunaryexpr = @notexpr;
+
+@bitwiseunaryexpr = @complementexpr;
+
+@arithmeticunaryexpr = @plusexpr | @minusexpr;
+
+@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
+
+@logicalbinaryexpr = @lorexpr | @landexpr;
+
+@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
+
+@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
+
+@shiftexpr = @shlexpr | @shrexpr;
+
+@comparison = @equalitytest | @relationalcomparison;
+
+@equalitytest = @eqlexpr | @neqexpr;
+
+@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
+
+@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
+
+case @stmt.kind of
+ 0 = @badstmt
+| 1 = @declstmt
+| 2 = @emptystmt
+| 3 = @labeledstmt
+| 4 = @exprstmt
+| 5 = @sendstmt
+| 6 = @incstmt
+| 7 = @decstmt
+| 8 = @gostmt
+| 9 = @deferstmt
+| 10 = @returnstmt
+| 11 = @breakstmt
+| 12 = @continuestmt
+| 13 = @gotostmt
+| 14 = @fallthroughstmt
+| 15 = @blockstmt
+| 16 = @ifstmt
+| 17 = @caseclause
+| 18 = @exprswitchstmt
+| 19 = @typeswitchstmt
+| 20 = @commclause
+| 21 = @selectstmt
+| 22 = @forstmt
+| 23 = @rangestmt
+| 24 = @assignstmt
+| 25 = @definestmt
+| 26 = @addassignstmt
+| 27 = @subassignstmt
+| 28 = @mulassignstmt
+| 29 = @quoassignstmt
+| 30 = @remassignstmt
+| 31 = @andassignstmt
+| 32 = @orassignstmt
+| 33 = @xorassignstmt
+| 34 = @shlassignstmt
+| 35 = @shrassignstmt
+| 36 = @andnotassignstmt;
+
+@incdecstmt = @incstmt | @decstmt;
+
+@assignment = @simpleassignstmt | @compoundassignstmt;
+
+@simpleassignstmt = @assignstmt | @definestmt;
+
+@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
+ | @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
+
+@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
+
+@switchstmt = @exprswitchstmt | @typeswitchstmt;
+
+@loopstmt = @forstmt | @rangestmt;
+
+case @decl.kind of
+ 0 = @baddecl
+| 1 = @importdecl
+| 2 = @constdecl
+| 3 = @typedecl
+| 4 = @vardecl
+| 5 = @funcdecl;
+
+@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
+
+case @spec.kind of
+ 0 = @importspec
+| 1 = @valuespec
+| 2 = @typedefspec
+| 3 = @aliasspec;
+
+@typespec = @typedefspec | @aliasspec;
+
+case @object.kind of
+ 0 = @pkgobject
+| 1 = @decltypeobject
+| 2 = @builtintypeobject
+| 3 = @declconstobject
+| 4 = @builtinconstobject
+| 5 = @declvarobject
+| 6 = @declfunctionobject
+| 7 = @builtinfunctionobject
+| 8 = @labelobject;
+
+@typeparamparentobject = @decltypeobject | @declfunctionobject;
+
+@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
+
+@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
+
+@typeobject = @decltypeobject | @builtintypeobject;
+
+@valueobject = @constobject | @varobject | @functionobject;
+
+@constobject = @declconstobject | @builtinconstobject;
+
+@varobject = @declvarobject;
+
+@functionobject = @declfunctionobject | @builtinfunctionobject;
+
+case @scope.kind of
+ 0 = @universescope
+| 1 = @packagescope
+| 2 = @localscope;
+
+case @type.kind of
+ 0 = @invalidtype
+| 1 = @boolexprtype
+| 2 = @inttype
+| 3 = @int8type
+| 4 = @int16type
+| 5 = @int32type
+| 6 = @int64type
+| 7 = @uinttype
+| 8 = @uint8type
+| 9 = @uint16type
+| 10 = @uint32type
+| 11 = @uint64type
+| 12 = @uintptrtype
+| 13 = @float32type
+| 14 = @float64type
+| 15 = @complex64type
+| 16 = @complex128type
+| 17 = @stringexprtype
+| 18 = @unsafepointertype
+| 19 = @boolliteraltype
+| 20 = @intliteraltype
+| 21 = @runeliteraltype
+| 22 = @floatliteraltype
+| 23 = @complexliteraltype
+| 24 = @stringliteraltype
+| 25 = @nilliteraltype
+| 26 = @typeparamtype
+| 27 = @arraytype
+| 28 = @slicetype
+| 29 = @structtype
+| 30 = @pointertype
+| 31 = @interfacetype
+| 32 = @tupletype
+| 33 = @signaturetype
+| 34 = @maptype
+| 35 = @sendchantype
+| 36 = @recvchantype
+| 37 = @sendrcvchantype
+| 38 = @definedtype
+| 39 = @typesetliteraltype;
+
+@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
+
+@booltype = @boolexprtype | @boolliteraltype;
+
+@numerictype = @integertype | @floattype | @complextype;
+
+@integertype = @signedintegertype | @unsignedintegertype;
+
+@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
+
+@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
+
+@floattype = @float32type | @float64type | @floatliteraltype;
+
+@complextype = @complex64type | @complex128type | @complexliteraltype;
+
+@stringtype = @stringexprtype | @stringliteraltype;
+
+@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
+ | @stringliteraltype | @nilliteraltype;
+
+@compositetype = @typeparamtype | @containertype | @structtype | @pointertype | @interfacetype | @tupletype
+ | @signaturetype | @definedtype | @typesetliteraltype;
+
+@containertype = @arraytype | @slicetype | @maptype | @chantype;
+
+@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
+
+case @modexpr.kind of
+ 0 = @modcommentblock
+| 1 = @modline
+| 2 = @modlineblock
+| 3 = @modlparen
+| 4 = @modrparen;
+
+case @error.kind of
+ 0 = @unknownerror
+| 1 = @listerror
+| 2 = @parseerror
+| 3 = @typeerror;
+
diff --git a/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/typeparam.ql b/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/typeparam.ql
new file mode 100644
index 000000000000..05ceab703446
--- /dev/null
+++ b/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/typeparam.ql
@@ -0,0 +1,21 @@
+class TypeParamType extends @typeparamtype {
+ string toString() { none() }
+}
+
+class CompositeType extends @compositetype {
+ string toString() { none() }
+}
+
+class TypeParamParentObject extends @typeparamparentobject {
+ string toString() { none() }
+}
+
+// In Go 1.26 and below, a type parameter is from a receiver exactly when its
+// parent is a method.
+boolean isFromReceiver(TypeParamParentObject parent) {
+ if methodreceivers(parent, _) then result = true else result = false
+}
+
+from TypeParamType tp, string name, CompositeType bound, TypeParamParentObject parent, int idx
+where typeparam(tp, name, bound, parent, idx)
+select tp, name, bound, parent, idx, isFromReceiver(parent)
diff --git a/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/upgrade.properties b/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/upgrade.properties
new file mode 100644
index 000000000000..d383bdf4ad30
--- /dev/null
+++ b/go/ql/lib/upgrades/b1341734d6870b105e5c9d168ce7dec25d7f72d0/upgrade.properties
@@ -0,0 +1,3 @@
+description: Track whether a type parameter is from a receiver
+compatibility: partial
+typeparam.rel: run typeparam.qlo
diff --git a/go/ql/test/library-tests/semmle/go/Function/TypeParamType.expected b/go/ql/test/library-tests/semmle/go/Function/TypeParamType.expected
index bda7c1517975..4addfa50f349 100644
--- a/go/ql/test/library-tests/semmle/go/Function/TypeParamType.expected
+++ b/go/ql/test/library-tests/semmle/go/Function/TypeParamType.expected
@@ -20,36 +20,36 @@ numberOfTypeParameters
| genericFunctions.go:152:6:152:36 | multipleAnonymousTypeParamsType | 3 |
| genericFunctions.go:154:51:154:51 | f | 3 |
#select
-| codeql-go-tests/function.EdgeConstraint | 0 | Node | interface { } |
-| codeql-go-tests/function.Element | 0 | S | interface { } |
-| codeql-go-tests/function.GenericFunctionInAnotherFile | 0 | T | interface { } |
-| codeql-go-tests/function.GenericFunctionOneTypeParam | 0 | T | interface { } |
-| codeql-go-tests/function.GenericFunctionTwoTypeParams | 0 | K | comparable |
-| codeql-go-tests/function.GenericFunctionTwoTypeParams | 1 | V | interface { int64 \| float64 } |
-| codeql-go-tests/function.GenericStruct1 | 0 | T | interface { } |
-| codeql-go-tests/function.GenericStruct1.f1 | 0 | TF1 | interface { } |
-| codeql-go-tests/function.GenericStruct1.g1 | 0 | TG1 | interface { } |
-| codeql-go-tests/function.GenericStruct2 | 0 | S | interface { } |
-| codeql-go-tests/function.GenericStruct2 | 1 | T | interface { } |
-| codeql-go-tests/function.GenericStruct2.f2 | 0 | SF2 | interface { } |
-| codeql-go-tests/function.GenericStruct2.f2 | 1 | TF2 | interface { } |
-| codeql-go-tests/function.GenericStruct2.g2 | 0 | SG2 | interface { } |
-| codeql-go-tests/function.GenericStruct2.g2 | 1 | TG2 | interface { } |
-| codeql-go-tests/function.Graph | 0 | Node | NodeConstraint |
-| codeql-go-tests/function.Graph | 1 | Edge | EdgeConstraint |
-| codeql-go-tests/function.Graph.ShortestPath | 0 | Node | NodeConstraint |
-| codeql-go-tests/function.Graph.ShortestPath | 1 | Edge | EdgeConstraint |
-| codeql-go-tests/function.List | 0 | T | interface { } |
-| codeql-go-tests/function.List.MyLen | 0 | U | interface { } |
-| codeql-go-tests/function.New | 0 | Node | NodeConstraint |
-| codeql-go-tests/function.New | 1 | Edge | EdgeConstraint |
-| codeql-go-tests/function.NodeConstraint | 0 | Edge | interface { } |
-| codeql-go-tests/function.multipleAnonymousTypeParamsFunc | 0 | _ | interface { } |
-| codeql-go-tests/function.multipleAnonymousTypeParamsFunc | 1 | _ | interface { string } |
-| codeql-go-tests/function.multipleAnonymousTypeParamsFunc | 2 | _ | interface { } |
-| codeql-go-tests/function.multipleAnonymousTypeParamsType | 0 | _ | interface { } |
-| codeql-go-tests/function.multipleAnonymousTypeParamsType | 1 | _ | interface { string } |
-| codeql-go-tests/function.multipleAnonymousTypeParamsType | 2 | _ | interface { } |
-| codeql-go-tests/function.multipleAnonymousTypeParamsType.f | 0 | _ | interface { } |
-| codeql-go-tests/function.multipleAnonymousTypeParamsType.f | 1 | _ | interface { string } |
-| codeql-go-tests/function.multipleAnonymousTypeParamsType.f | 2 | _ | interface { } |
+| codeql-go-tests/function.EdgeConstraint | 0 | | Node | interface { } |
+| codeql-go-tests/function.Element | 0 | | S | interface { } |
+| codeql-go-tests/function.GenericFunctionInAnotherFile | 0 | | T | interface { } |
+| codeql-go-tests/function.GenericFunctionOneTypeParam | 0 | | T | interface { } |
+| codeql-go-tests/function.GenericFunctionTwoTypeParams | 0 | | K | comparable |
+| codeql-go-tests/function.GenericFunctionTwoTypeParams | 1 | | V | interface { int64 \| float64 } |
+| codeql-go-tests/function.GenericStruct1 | 0 | | T | interface { } |
+| codeql-go-tests/function.GenericStruct1.f1 | 0 | from receiver | TF1 | interface { } |
+| codeql-go-tests/function.GenericStruct1.g1 | 0 | from receiver | TG1 | interface { } |
+| codeql-go-tests/function.GenericStruct2 | 0 | | S | interface { } |
+| codeql-go-tests/function.GenericStruct2 | 1 | | T | interface { } |
+| codeql-go-tests/function.GenericStruct2.f2 | 0 | from receiver | SF2 | interface { } |
+| codeql-go-tests/function.GenericStruct2.f2 | 1 | from receiver | TF2 | interface { } |
+| codeql-go-tests/function.GenericStruct2.g2 | 0 | from receiver | SG2 | interface { } |
+| codeql-go-tests/function.GenericStruct2.g2 | 1 | from receiver | TG2 | interface { } |
+| codeql-go-tests/function.Graph | 0 | | Node | NodeConstraint |
+| codeql-go-tests/function.Graph | 1 | | Edge | EdgeConstraint |
+| codeql-go-tests/function.Graph.ShortestPath | 0 | from receiver | Node | NodeConstraint |
+| codeql-go-tests/function.Graph.ShortestPath | 1 | from receiver | Edge | EdgeConstraint |
+| codeql-go-tests/function.List | 0 | | T | interface { } |
+| codeql-go-tests/function.List.MyLen | 0 | from receiver | U | interface { } |
+| codeql-go-tests/function.New | 0 | | Node | NodeConstraint |
+| codeql-go-tests/function.New | 1 | | Edge | EdgeConstraint |
+| codeql-go-tests/function.NodeConstraint | 0 | | Edge | interface { } |
+| codeql-go-tests/function.multipleAnonymousTypeParamsFunc | 0 | | _ | interface { } |
+| codeql-go-tests/function.multipleAnonymousTypeParamsFunc | 1 | | _ | interface { string } |
+| codeql-go-tests/function.multipleAnonymousTypeParamsFunc | 2 | | _ | interface { } |
+| codeql-go-tests/function.multipleAnonymousTypeParamsType | 0 | | _ | interface { } |
+| codeql-go-tests/function.multipleAnonymousTypeParamsType | 1 | | _ | interface { string } |
+| codeql-go-tests/function.multipleAnonymousTypeParamsType | 2 | | _ | interface { } |
+| codeql-go-tests/function.multipleAnonymousTypeParamsType.f | 0 | from receiver | _ | interface { } |
+| codeql-go-tests/function.multipleAnonymousTypeParamsType.f | 1 | from receiver | _ | interface { string } |
+| codeql-go-tests/function.multipleAnonymousTypeParamsType.f | 2 | from receiver | _ | interface { } |
diff --git a/go/ql/test/library-tests/semmle/go/Function/TypeParamType.ql b/go/ql/test/library-tests/semmle/go/Function/TypeParamType.ql
index 02dec23d2a86..323defa04934 100644
--- a/go/ql/test/library-tests/semmle/go/Function/TypeParamType.ql
+++ b/go/ql/test/library-tests/semmle/go/Function/TypeParamType.ql
@@ -5,10 +5,11 @@ query predicate numberOfTypeParameters(TypeParamParentEntity parent, int n) {
n = strictcount(TypeParamType tpt | tpt.getParent() = parent)
}
-from TypeParamType tpt, TypeParamParentEntity ty
+from TypeParamType tpt, TypeParamParentEntity ty, string fr
where
ty = tpt.getParent() and
// Note that we cannot use the location of `tpt` itself as we currently fail
// to extract an object for type parameters for methods on generic structs.
- exists(ty.getLocation())
-select ty.getQualifiedName(), tpt.getIndex(), tpt.getParamName(), tpt.getConstraint().pp()
+ exists(ty.getLocation()) and
+ if tpt.isFromReceiver() then fr = "from receiver" else fr = ""
+select ty.getQualifiedName(), tpt.getIndex(), fr, tpt.getParamName(), tpt.getConstraint().pp()