-
Notifications
You must be signed in to change notification settings - Fork 2k
Go: Update to 1.27 #22042
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Go: Update to 1.27 #22042
Changes from all commits
d3b5129
6ce74da
ce2eef6
e78e910
5e84585
e51a7c2
cc73d6c
7213ee7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
| index int | ||
| } | ||
|
|
||
| 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,10 @@ 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) | ||
| typeParams := funcObj.Type().(*types.Signature).TypeParams() | ||
| populateTypeParamParents(typeParams, obj, 0) | ||
| recvTypeParams := funcObj.Type().(*types.Signature).RecvTypeParams() | ||
| populateTypeParamParents(recvTypeParams, obj, typeParams.Len()) | ||
| } | ||
| // Populate type parameter parents for defined types and alias types. | ||
| if typeNameObj, ok := obj.(*types.TypeName); ok { | ||
|
|
@@ -542,9 +550,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, 0) | ||
| } else if tp, ok := typeNameObj.Type().(*types.Alias); ok { | ||
| populateTypeParamParents(tp.TypeParams(), obj) | ||
| populateTypeParamParents(tp.TypeParams(), obj, 0) | ||
| } | ||
| } | ||
| extractObject(tw, obj, lbl) | ||
|
|
@@ -570,8 +578,10 @@ 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) | ||
| typeParams := meth.Type().(*types.Signature).TypeParams() | ||
| populateTypeParamParents(typeParams, meth, 0) | ||
| recvTypeParams := meth.Type().(*types.Signature).RecvTypeParams() | ||
| populateTypeParamParents(recvTypeParams, meth, typeParams.Len()) | ||
| extractObject(tw, meth, methlbl) | ||
| } | ||
|
|
||
|
|
@@ -1660,7 +1670,8 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label { | |
| // parent scope, so they are not dealt with by `extractScopes` | ||
| for i := 0; i < origintp.NumMethods(); i++ { | ||
| meth := origintp.Method(i).Origin() | ||
|
|
||
| typeParams := tp.Method(i).Type().(*types.Signature).TypeParams() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are you sure that this line wants to use the instantiated receiver type ( Perhaps we should put a short comment here, as it will no doubt be confusing to future readers as well.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As far as I can tell, it needs to be
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just to provide some context first. The problem is coming from the select expression in s2.GenericMethod2[string]("hello")That is I think this means there are two solutions here:
(2) we can do by constructing a separate map from type parameters to type parameters near the call sides of
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does ☝️ make sense? |
||
| populateTypeParamParents(typeParams, meth, 0) | ||
| extractMethod(tw, meth) | ||
| } | ||
|
|
||
|
|
@@ -1684,9 +1695,9 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label { | |
| } | ||
| case *types.TypeParam: | ||
| kind = dbscheme.TypeParamType.Index() | ||
| parentlbl := getTypeParamParentLabel(tw, tp) | ||
| parentlbl, idx := 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, idx) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should update the QLDoc for
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm happy to switch the order. I just kept things in the order in which the code appears for now.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'd say left-to-right order, so receiver type parameters first and then method type parameters, is slightly more intuitive.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The alternative would be to add a column to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or split the receiver type parameters off in a completely separate table.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I think this might be the best solution actually. Have an extra column
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done here: #22178 |
||
| case *types.Union: | ||
| kind = dbscheme.TypeSetLiteral.Index() | ||
| for i := 0; i < tp.Len(); i++ { | ||
|
|
@@ -1826,8 +1837,7 @@ 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) | ||
| idx := tp.Index() | ||
| parentlbl, idx := getTypeParamParentLabel(tw, tp) | ||
| lbl = tw.Labeler.GlobalID(fmt.Sprintf("{%v},%d,%s;typeparamtype", parentlbl, idx, tp.Obj().Name())) | ||
| case *types.Union: | ||
| var b strings.Builder | ||
|
|
@@ -2013,10 +2023,10 @@ func extractTypeParamDecls(tw *trap.Writer, fields *ast.FieldList, parent trap.L | |
| } | ||
|
|
||
| // populateTypeParamParents sets `parent` as the parent of the elements of `typeparams` | ||
| func populateTypeParamParents(typeparams *types.TypeParamList, parent types.Object) { | ||
| func populateTypeParamParents(typeparams *types.TypeParamList, parent types.Object, offset int) { | ||
| if typeparams != nil { | ||
| for idx := 0; idx < typeparams.Len(); idx++ { | ||
| setTypeParamParent(typeparams.At(idx), parent) | ||
| setTypeParamParent(typeparams.At(idx), parent, idx+offset) | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -2065,24 +2075,24 @@ func trackInstantiatedStructFields(tw *trap.Writer, tp, origintp *types.Named) { | |
| } | ||
| } | ||
|
|
||
| func getTypeParamParentLabel(tw *trap.Writer, tp *types.TypeParam) trap.Label { | ||
| parent, exists := typeParamParent[tp] | ||
| func getTypeParamParentLabel(tw *trap.Writer, tp *types.TypeParam) (trap.Label, int) { | ||
| 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.index | ||
| } | ||
|
|
||
| func setTypeParamParent(tp *types.TypeParam, newobj types.Object) { | ||
| obj, exists := typeParamParent[tp] | ||
| func setTypeParamParent(tp *types.TypeParam, newobj types.Object, idx int) { | ||
| entry, exists := typeParamParent[tp] | ||
| 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] = typeParamParentEntry{newobj, idx} | ||
| } else if entry.parent != newobj || entry.index != idx { | ||
| log.Fatalf("Parent of type parameter '%s %s' being set to a different value: '%s' vs '%s'", tp.String(), tp.Constraint().String(), entry.parent, newobj) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This error message is slightly inaccurate, as it only prints the objects but it could be printed if the objects are the same but the indexes are different. It's not a big thing, but consider printing the indexes as well (or the |
||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| --- | ||
| category: majorAnalysis | ||
| --- | ||
| * Go 1.27 is now supported. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package main | ||
|
|
||
| type StructForGenericMethod1 struct{} | ||
|
|
||
| func (*StructForGenericMethod1) GenericMethod1[P1 any](x P1) {} | ||
|
|
||
| type StructForGenericMethod2[P2 any] struct{} | ||
|
|
||
| func (*StructForGenericMethod2[P3]) GenericMethod2[P4 any](x P4) {} | ||
|
|
||
| func generic_methods(s1 StructForGenericMethod1, s2 StructForGenericMethod2[int]) { | ||
| // Call the generic method specifying the type | ||
| s1.GenericMethod1[int](1) | ||
| s2.GenericMethod2[string]("hello") | ||
|
|
||
| // Call the generic method without specifying the type | ||
| s1.GenericMethod1("hello") | ||
| s2.GenericMethod2(42) | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,8 @@ | ||
| module codeql-go-tests/function | ||
|
|
||
| go 1.18 | ||
| go 1.27 | ||
|
|
||
| toolchain go1.27rc1 | ||
|
|
||
| require github.com/anotherpkg v0.0.0-20200203000000-0000000000000 | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In theory these lines shouldn't be needed here, because the comment above says that methods do not appear as objects in any scope, so we should only be dealing with top-level functions. However, rather than deleting it, I think it would be better to create a separate function for these four lines, as they are duplicated lower down. Maybe
populateTypeParamParentsFromFunction(funcObj *types.Func). (Can you tell I like long method names? 😆 )There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Happy to refactor. The only thing I changed here was the addition of the offset. I simply assumed that this code was necessary (because it was already there 😄 ).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point 😆
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This only applies to
RecvTypeParams, right? TheTypeParamsare needed for generic functions.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's also not clear to me how
RecvTypeParamscan ever be non-empty here. And somewhat similar: howTypeParamscould ever have been non-empty for methods before Go 1.27.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
factored out in #22178