Skip to content

Commit

Permalink
Merge pull request #17378 from github/mbg/go/improve-typeparamtype
Browse files Browse the repository at this point in the history
Go: Add `getParent` and `getIndex` for `TypeParamType`
  • Loading branch information
mbg authored Sep 4, 2024
2 parents 8508056 + db72bd4 commit cd8a5d7
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 34 deletions.
7 changes: 5 additions & 2 deletions go/ql/lib/semmle/go/Scopes.qll
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,11 @@ class PackageEntity extends Entity, @pkgobject { }
/** A built-in or declared named type. */
class TypeEntity extends Entity, @typeobject { }

/** The parent of a type parameter type, either a declared type or a declared function. */
class TypeParamParentEntity extends Entity, @typeparamparentobject { }

/** A declared named type. */
class DeclaredType extends TypeEntity, DeclaredEntity, @decltypeobject {
class DeclaredType extends TypeEntity, DeclaredEntity, TypeParamParentEntity, @decltypeobject {
/** Gets the declaration specifier declaring this type. */
TypeSpec getSpec() { result.getNameExpr() = this.getDeclaration() }
}
Expand Down Expand Up @@ -598,7 +601,7 @@ class PromotedMethod extends Method {
}

/** A declared function. */
class DeclaredFunction extends Function, DeclaredEntity, @declfunctionobject {
class DeclaredFunction extends Function, DeclaredEntity, TypeParamParentEntity, @declfunctionobject {
override FuncDecl getFuncDecl() { result.getNameExpr() = this.getDeclaration() }

override predicate mayHaveSideEffects() {
Expand Down
6 changes: 6 additions & 0 deletions go/ql/lib/semmle/go/Types.qll
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,12 @@ class TypeParamType extends @typeparamtype, CompositeType {

override InterfaceType getUnderlyingType() { result = this.getConstraint().getUnderlyingType() }

/** Gets the parent object of this type parameter type. */
TypeParamParentEntity getParent() { typeparam(this, _, _, result, _) }

/** Gets the index of this type parameter type. */
int getIndex() { typeparam(this, _, _, _, result) }

override string pp() { result = this.getParamName() }

/**
Expand Down
191 changes: 161 additions & 30 deletions go/ql/test/library-tests/semmle/go/Function/TypeParamType.expected
Original file line number Diff line number Diff line change
@@ -1,30 +1,161 @@
| E | Ordered |
| E | comparable |
| E | interface { } |
| E1 | interface { } |
| E2 | interface { } |
| Edge | EdgeConstraint |
| Edge | interface { } |
| F | floaty |
| K | comparable |
| Node | NodeConstraint |
| Node | interface { } |
| S | interface { } |
| S | interface { ~[]E } |
| S1 | interface { ~[]E1 } |
| S2 | interface { ~[]E2 } |
| SF2 | interface { } |
| SG2 | interface { } |
| T | Ordered |
| T | comparable |
| T | interface { string \| []uint8 } |
| T | interface { } |
| T1 | interface { } |
| T2 | interface { } |
| TF1 | interface { } |
| TF2 | interface { } |
| TG1 | interface { } |
| TG2 | interface { } |
| U | interface { } |
| V | interface { int64 \| float64 } |
| bytes | interface { []uint8 \| string } |
| cmp.Compare | 0 | T | Ordered |
| cmp.Less | 0 | T | Ordered |
| cmp.Or | 0 | T | comparable |
| cmp.isNaN | 0 | T | Ordered |
| 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 { } |
| github.com/anotherpkg.GenericFunctionInAnotherPackage | 0 | T | interface { } |
| internal/bytealg.HashStr | 0 | T | interface { string \| []uint8 } |
| internal/bytealg.HashStrRev | 0 | T | interface { string \| []uint8 } |
| internal/bytealg.IndexRabinKarp | 0 | T | interface { string \| []uint8 } |
| internal/bytealg.LastIndexRabinKarp | 0 | T | interface { string \| []uint8 } |
| runtime.fandbits | 0 | F | floaty |
| runtime.fmax | 0 | F | floaty |
| runtime.fmin | 0 | F | floaty |
| runtime.forbits | 0 | F | floaty |
| runtime.noEscapePtr | 0 | T | interface { } |
| runtime/internal/atomic.Pointer.CompareAndSwap | 0 | T | interface { } |
| runtime/internal/atomic.Pointer.CompareAndSwapNoWB | 0 | T | interface { } |
| runtime/internal/atomic.Pointer.Load | 0 | T | interface { } |
| runtime/internal/atomic.Pointer.Store | 0 | T | interface { } |
| runtime/internal/atomic.Pointer.StoreNoWB | 0 | T | interface { } |
| slices.BinarySearch | 0 | S | interface { ~[]E } |
| slices.BinarySearch | 1 | E | Ordered |
| slices.BinarySearchFunc | 0 | S | interface { ~[]E } |
| slices.BinarySearchFunc | 1 | E | interface { } |
| slices.BinarySearchFunc | 2 | T | interface { } |
| slices.Clip | 0 | S | interface { ~[]E } |
| slices.Clip | 1 | E | interface { } |
| slices.Clone | 0 | S | interface { ~[]E } |
| slices.Clone | 1 | E | interface { } |
| slices.Compact | 0 | S | interface { ~[]E } |
| slices.Compact | 1 | E | comparable |
| slices.CompactFunc | 0 | S | interface { ~[]E } |
| slices.CompactFunc | 1 | E | interface { } |
| slices.Compare | 0 | S | interface { ~[]E } |
| slices.Compare | 1 | E | Ordered |
| slices.CompareFunc | 0 | S1 | interface { ~[]E1 } |
| slices.CompareFunc | 1 | S2 | interface { ~[]E2 } |
| slices.CompareFunc | 2 | E1 | interface { } |
| slices.CompareFunc | 3 | E2 | interface { } |
| slices.Concat | 0 | S | interface { ~[]E } |
| slices.Concat | 1 | E | interface { } |
| slices.Contains | 0 | S | interface { ~[]E } |
| slices.Contains | 1 | E | comparable |
| slices.ContainsFunc | 0 | S | interface { ~[]E } |
| slices.ContainsFunc | 1 | E | interface { } |
| slices.Delete | 0 | S | interface { ~[]E } |
| slices.Delete | 1 | E | interface { } |
| slices.DeleteFunc | 0 | S | interface { ~[]E } |
| slices.DeleteFunc | 1 | E | interface { } |
| slices.Equal | 0 | S | interface { ~[]E } |
| slices.Equal | 1 | E | comparable |
| slices.EqualFunc | 0 | S1 | interface { ~[]E1 } |
| slices.EqualFunc | 1 | S2 | interface { ~[]E2 } |
| slices.EqualFunc | 2 | E1 | interface { } |
| slices.EqualFunc | 3 | E2 | interface { } |
| slices.Grow | 0 | S | interface { ~[]E } |
| slices.Grow | 1 | E | interface { } |
| slices.Index | 0 | S | interface { ~[]E } |
| slices.Index | 1 | E | comparable |
| slices.IndexFunc | 0 | S | interface { ~[]E } |
| slices.IndexFunc | 1 | E | interface { } |
| slices.Insert | 0 | S | interface { ~[]E } |
| slices.Insert | 1 | E | interface { } |
| slices.IsSorted | 0 | S | interface { ~[]E } |
| slices.IsSorted | 1 | E | Ordered |
| slices.IsSortedFunc | 0 | S | interface { ~[]E } |
| slices.IsSortedFunc | 1 | E | interface { } |
| slices.Max | 0 | S | interface { ~[]E } |
| slices.Max | 1 | E | Ordered |
| slices.MaxFunc | 0 | S | interface { ~[]E } |
| slices.MaxFunc | 1 | E | interface { } |
| slices.Min | 0 | S | interface { ~[]E } |
| slices.Min | 1 | E | Ordered |
| slices.MinFunc | 0 | S | interface { ~[]E } |
| slices.MinFunc | 1 | E | interface { } |
| slices.Replace | 0 | S | interface { ~[]E } |
| slices.Replace | 1 | E | interface { } |
| slices.Reverse | 0 | S | interface { ~[]E } |
| slices.Reverse | 1 | E | interface { } |
| slices.Sort | 0 | S | interface { ~[]E } |
| slices.Sort | 1 | E | Ordered |
| slices.SortFunc | 0 | S | interface { ~[]E } |
| slices.SortFunc | 1 | E | interface { } |
| slices.SortStableFunc | 0 | S | interface { ~[]E } |
| slices.SortStableFunc | 1 | E | interface { } |
| slices.breakPatternsCmpFunc | 0 | E | interface { } |
| slices.breakPatternsOrdered | 0 | E | Ordered |
| slices.choosePivotCmpFunc | 0 | E | interface { } |
| slices.choosePivotOrdered | 0 | E | Ordered |
| slices.heapSortCmpFunc | 0 | E | interface { } |
| slices.heapSortOrdered | 0 | E | Ordered |
| slices.insertionSortCmpFunc | 0 | E | interface { } |
| slices.insertionSortOrdered | 0 | E | Ordered |
| slices.isNaN | 0 | T | Ordered |
| slices.medianAdjacentCmpFunc | 0 | E | interface { } |
| slices.medianAdjacentOrdered | 0 | E | Ordered |
| slices.medianCmpFunc | 0 | E | interface { } |
| slices.medianOrdered | 0 | E | Ordered |
| slices.order2CmpFunc | 0 | E | interface { } |
| slices.order2Ordered | 0 | E | Ordered |
| slices.overlaps | 0 | E | interface { } |
| slices.partialInsertionSortCmpFunc | 0 | E | interface { } |
| slices.partialInsertionSortOrdered | 0 | E | Ordered |
| slices.partitionCmpFunc | 0 | E | interface { } |
| slices.partitionEqualCmpFunc | 0 | E | interface { } |
| slices.partitionEqualOrdered | 0 | E | Ordered |
| slices.partitionOrdered | 0 | E | Ordered |
| slices.pdqsortCmpFunc | 0 | E | interface { } |
| slices.pdqsortOrdered | 0 | E | Ordered |
| slices.reverseRangeCmpFunc | 0 | E | interface { } |
| slices.reverseRangeOrdered | 0 | E | Ordered |
| slices.rotateCmpFunc | 0 | E | interface { } |
| slices.rotateLeft | 0 | E | interface { } |
| slices.rotateOrdered | 0 | E | Ordered |
| slices.rotateRight | 0 | E | interface { } |
| slices.siftDownCmpFunc | 0 | E | interface { } |
| slices.siftDownOrdered | 0 | E | Ordered |
| slices.stableCmpFunc | 0 | E | interface { } |
| slices.stableOrdered | 0 | E | Ordered |
| slices.startIdx | 0 | E | interface { } |
| slices.swap | 0 | E | interface { } |
| slices.swapRangeCmpFunc | 0 | E | interface { } |
| slices.swapRangeOrdered | 0 | E | Ordered |
| slices.symMergeCmpFunc | 0 | E | interface { } |
| slices.symMergeOrdered | 0 | E | Ordered |
| sync.OnceValue | 0 | T | interface { } |
| sync.OnceValues | 0 | T1 | interface { } |
| sync.OnceValues | 1 | T2 | interface { } |
| sync/atomic.Pointer | 0 | T | interface { } |
| sync/atomic.Pointer.CompareAndSwap | 0 | T | interface { } |
| sync/atomic.Pointer.Load | 0 | T | interface { } |
| sync/atomic.Pointer.Store | 0 | T | interface { } |
| sync/atomic.Pointer.Swap | 0 | T | interface { } |
| time.atoi | 0 | bytes | interface { []uint8 \| string } |
| time.isDigit | 0 | bytes | interface { []uint8 \| string } |
| time.leadingInt | 0 | bytes | interface { []uint8 \| string } |
| time.parseNanoseconds | 0 | bytes | interface { []uint8 \| string } |
| time.parseRFC3339 | 0 | bytes | interface { []uint8 \| string } |
5 changes: 3 additions & 2 deletions go/ql/test/library-tests/semmle/go/Function/TypeParamType.ql
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import go

from TypeParamType tpt
select tpt.getParamName(), tpt.getConstraint().pp()
from TypeParamType tpt, TypeParamParentEntity ty
where ty = tpt.getParent()
select ty.getQualifiedName(), tpt.getIndex(), tpt.getParamName(), tpt.getConstraint().pp()

0 comments on commit cd8a5d7

Please sign in to comment.