Skip to content
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

Go: Support 1.23 (Transparent aliases) #17358

Merged
merged 12 commits into from
Sep 6, 2024
2 changes: 1 addition & 1 deletion MODULE.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ use_repo(
)

go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(version = "1.22.2")
go_sdk.download(version = "1.23.1")

go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//go/extractor:go.mod")
Expand Down
2 changes: 1 addition & 1 deletion go/actions/test/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ inputs:
go-test-version:
description: Which Go version to use for running the tests
required: false
default: ~1.22.0
default: "~1.23.1"
run-code-checks:
description: Whether to run formatting, code and qhelp generation checks
required: false
Expand Down
2 changes: 1 addition & 1 deletion go/extractor/autobuilder/build-environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
)

var minGoVersion = util.NewSemVer("1.11")
var maxGoVersion = util.NewSemVer("1.22")
var maxGoVersion = util.NewSemVer("1.23")

type versionInfo struct {
goModVersion util.SemVer // The version of Go found in the go directive in the `go.mod` file.
Expand Down
16 changes: 16 additions & 0 deletions go/extractor/extractor.go
Original file line number Diff line number Diff line change
Expand Up @@ -1507,9 +1507,24 @@ func extractSpec(tw *trap.Writer, spec ast.Spec, parent trap.Label, idx int) {
extractNodeLocation(tw, spec, lbl)
}

// Determines whether the given type is an alias.
func isAlias(tp types.Type) bool {
_, ok := tp.(*types.Alias)
return ok
}

// If the given type is a type alias, this function resolves it to its underlying type.
func resolveTypeAlias(tp types.Type) types.Type {
if isAlias(tp) {
return types.Unalias(tp) // tp.Underlying()
}
return tp
}

Comment on lines +1510 to +1523
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is all redundant and we can just use types.Unalias. But this can be done in a follow-up PR.

Suggested change
// Determines whether the given type is an alias.
func isAlias(tp types.Type) bool {
_, ok := tp.(*types.Alias)
return ok
}
// If the given type is a type alias, this function resolves it to its underlying type.
func resolveTypeAlias(tp types.Type) types.Type {
if isAlias(tp) {
return types.Unalias(tp) // tp.Underlying()
}
return tp
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well spotted. Yes, none of this is necessary anymore with the current version of this PR since Unalias implements the same logic. Agree that we can remove it later since it doesn't impact the behaviour.

// extractType extracts type information for `tp` and returns its associated label;
// types are only extracted once, so the second time `extractType` is invoked it simply returns the label
func extractType(tw *trap.Writer, tp types.Type) trap.Label {
tp = resolveTypeAlias(tp)
lbl, exists := getTypeLabel(tw, tp)
if !exists {
var kind int
Expand Down Expand Up @@ -1666,6 +1681,7 @@ func extractType(tw *trap.Writer, tp types.Type) trap.Label {
// is constructed from their globally unique ID. This prevents cyclic type keys
// since type recursion in Go always goes through named types.
func getTypeLabel(tw *trap.Writer, tp types.Type) (trap.Label, bool) {
tp = resolveTypeAlias(tp)
lbl, exists := tw.Labeler.TypeLabels[tp]
if !exists {
switch tp := tp.(type) {
Expand Down
4 changes: 3 additions & 1 deletion go/extractor/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
module github.com/github/codeql-go/extractor

go 1.22.0
go 1.23

toolchain go1.23.1

// when updating this, run
// bazel run @rules_go//go -- mod tidy
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
| -:0:0:0:0 | package ; expected main |
| -:0:0:0:0 | package ; expected package main |
| broken2/test1.go:4:2:4:2 | undefined: fmt |
| broken2/test1.go:5:2:5:2 | undefined: fmt |
| broken2/test1.go:5:14:5:14 | undefined: a |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
| -:0:0:0:0 | package ; expected nonexistent |
| -:0:0:0:0 | package ; expected package nonexistent |
| vendor/github.com/github/nonexistent/bad.go:1:57:1:57 | expected ';', found 'EOF' |
| vendor/github.com/github/nonexistent/bad.go:1:57:1:57 | expected 'IDENT', found 'EOF' |
| vendor/github.com/github/nonexistent/bad.go:1:57:1:57 | expected 'package', found 'EOF' |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
| E | Ordered |
| E | comparable |
| E | interface { } |
| E | interface { ~uint16 \| ~uint32 } |
| E1 | interface { } |
| E2 | interface { } |
| Edge | EdgeConstraint |
| Edge | interface { } |
| F | floaty |
| K | comparable |
| K | interface { } |
| N | interface { int64 \| uint64 } |
| Node | NodeConstraint |
| Node | interface { } |
| S | interface { } |
Expand All @@ -15,6 +18,7 @@
| S2 | interface { ~[]E2 } |
| SF2 | interface { } |
| SG2 | interface { } |
| Slice | interface { ~[]E } |
| T | Ordered |
| T | comparable |
| T | interface { string \| []uint8 } |
Expand All @@ -27,4 +31,5 @@
| TG2 | interface { } |
| U | interface { } |
| V | interface { int64 \| float64 } |
| V | interface { } |
| bytes | interface { []uint8 \| string } |
20 changes: 20 additions & 0 deletions go/ql/test/library-tests/semmle/go/Types/Aliases.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
entities
| aliases.go | aliases.go:3:6:3:13 | aliasesX | 1 | file://:0:0:0:0 | int |
| aliases.go | aliases.go:4:6:4:13 | aliasesY | 1 | file://:0:0:0:0 | int |
| aliases.go | aliases.go:6:6:6:14 | aliasesS1 | 1 | file://:0:0:0:0 | struct type |
| aliases.go | aliases.go:6:26:6:26 | x | 3 | file://:0:0:0:0 | int |
| aliases.go | aliases.go:8:6:8:14 | aliasesS2 | 1 | file://:0:0:0:0 | struct type |
| aliases.go | aliases.go:8:26:8:26 | x | 3 | file://:0:0:0:0 | int |
| aliases.go | aliases.go:10:6:10:6 | F | 1 | file://:0:0:0:0 | signature type |
| aliases.go | aliases.go:10:8:10:11 | Afs1 | 1 | file://:0:0:0:0 | struct type |
| aliases.go | aliases.go:14:6:14:6 | G | 1 | file://:0:0:0:0 | signature type |
| aliases.go | aliases.go:14:8:14:11 | Afs2 | 1 | file://:0:0:0:0 | struct type |
| aliases.go | aliases.go:19:6:19:7 | S3 | 1 | aliases.go:19:6:19:7 | S3 |
| aliases.go | aliases.go:19:17:19:17 | x | 3 | file://:0:0:0:0 | int |
| aliases.go | aliases.go:22:6:22:6 | T | 1 | aliases.go:19:6:19:7 | S3 |
| aliases.go | aliases.go:25:6:25:6 | H | 1 | file://:0:0:0:0 | signature type |
| aliases.go | aliases.go:25:8:25:11 | Afs3 | 1 | aliases.go:19:6:19:7 | S3 |
#select
| F | func(struct { x int }) int |
| G | func(struct { x int }) int |
| H | func(S3) int |
21 changes: 21 additions & 0 deletions go/ql/test/library-tests/semmle/go/Types/Aliases.ql
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import go

int countDecls(Entity e) { result = count(Ident decl | decl = e.getDeclaration()) }

query predicate entities(string fp, Entity e, int c, Type ty) {
c = countDecls(e) and
ty = e.getType() and
exists(DbLocation loc |
loc = e.getDeclaration().getLocation() and
fp = loc.getFile().getBaseName() and
fp = "aliases.go"
)
}

from string fp, FuncDecl decl, SignatureType sig
where
decl.hasLocationInfo(fp, _, _, _, _) and
decl.getName() = ["F", "G", "H"] and
sig = decl.getType() and
fp.matches("%aliases.go%")
select decl.getName(), sig.pp()
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
| aliases.go:6:26:6:26 | x | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| aliases.go:8:26:8:26 | x | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| aliases.go:19:17:19:17 | x | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| cyclic.go:4:3:4:3 | s | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| cyclic.go:8:3:8:3 | u | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
| cyclic.go:9:2:9:2 | f | package github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
| aliases.go:6:26:6:26 | x | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S3 | x |
| aliases.go:8:26:8:26 | x | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S3 | x |
| aliases.go:19:17:19:17 | x | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S3 | x |
| cyclic.go:4:3:4:3 | s | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.s | s |
| cyclic.go:8:3:8:3 | u | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.t | u |
| cyclic.go:8:3:8:3 | u | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.u | u |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
| aliases.go:6:26:6:26 | x | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | S3 | x |
| aliases.go:8:26:8:26 | x | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | S3 | x |
| aliases.go:19:17:19:17 | x | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | S3 | x |
| cyclic.go:4:3:4:3 | s | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | s | s |
| cyclic.go:8:3:8:3 | u | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | t | u |
| cyclic.go:8:3:8:3 | u | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types | u | u |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
| aliases.go:19:6:19:7 | S3 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.S3 |
| cyclic.go:3:6:3:6 | s | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.s |
| cyclic.go:7:6:7:6 | t | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.t |
| cyclic.go:12:6:12:6 | u | github.com/github/codeql-go/ql/test/library-tests/semmle/go/Types.u |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
| aliases.go:10:1:12:1 | function declaration | 1 |
| aliases.go:14:1:16:1 | function declaration | 1 |
| aliases.go:25:1:27:1 | function declaration | 1 |
| depth.go:22:1:25:1 | function declaration | 0 |
| generic.go:70:1:72:1 | function declaration | 1 |
| generic.go:74:1:80:1 | function declaration | 1 |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
| aliases.go:10:1:12:1 | function declaration | 1 |
| aliases.go:14:1:16:1 | function declaration | 1 |
| aliases.go:25:1:27:1 | function declaration | 1 |
| depth.go:22:1:25:1 | function declaration | 0 |
| generic.go:70:1:72:1 | function declaration | 1 |
| generic.go:74:1:80:1 | function declaration | 0 |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
| aliases.go:19:6:19:7 | S3 | aliases.go:6:18:6:37 | struct type | x | int |
| aliases.go:19:6:19:7 | S3 | aliases.go:8:18:8:37 | struct type | x | int |
| aliases.go:19:6:19:7 | S3 | aliases.go:19:9:19:23 | struct type | x | int |
| cyclic.go:3:6:3:6 | s | cyclic.go:3:8:5:1 | struct type | s | * s |
| cyclic.go:7:6:7:6 | t | cyclic.go:7:8:10:1 | struct type | f | int |
| cyclic.go:7:6:7:6 | t | cyclic.go:7:8:10:1 | struct type | t | t |
Expand Down
1 change: 1 addition & 0 deletions go/ql/test/library-tests/semmle/go/Types/Types.expected
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
| aliases.go:19:6:19:7 | S3 | S3 |
| cyclic.go:3:6:3:6 | s | s |
| cyclic.go:7:6:7:6 | t | t |
| cyclic.go:12:6:12:6 | u | u |
Expand Down
27 changes: 27 additions & 0 deletions go/ql/test/library-tests/semmle/go/Types/aliases.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package main

type aliasesX = int
type aliasesY = int

type aliasesS1 = struct{ x aliasesX }

type aliasesS2 = struct{ x aliasesY }

func F(Afs1 aliasesS1) int {
return G(Afs1) + Afs1.x
}

func G(Afs2 aliasesS2) int {
return Afs2.x
}

// This is a named type, not an alias
type S3 struct{ x int }

// This is a type alias
type T = S3

// We expect `Afs3` to be of type `S3` here, not `struct{ x int }`
func H(Afs3 T) int {
return Afs3.x
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
| -:0:0:0:0 | malformed import path "github.com/github/codeql-go/ql/test/query-tests/Diagnostics/invalid{": invalid char '{' |
| -:0:0:0:0 | package ; expected main |
| -:0:0:0:0 | package ; expected package main |
| bad.go:3:1:3:1 | expected 'package', found avvu |
| bad.go:3:1:3:1 | expected 'package', found avvu |
| bad.go:3:5:3:5 | expected 'IDENT', found newline |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@
| Extraction failed with error expected 'IDENT', found newline | 2 |
| Extraction failed with error expected 'package', found avvu | 2 |
| Extraction failed with error malformed import path "github.com/github/codeql-go/ql/test/query-tests/Diagnostics/invalid{": invalid char '{' | 2 |
| Extraction failed with error package ; expected main | 2 |
| Extraction failed with error package ; expected package main | 2 |
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
| -:0:0:0:0 | package ; expected main |
| -:0:0:0:0 | package ; expected package main |
| empty-file.go:1:1:1:1 | expected ';', found 'EOF' |
| empty-file.go:1:1:1:1 | expected 'IDENT', found 'EOF' |
| empty-file.go:1:1:1:1 | expected 'package', found 'EOF' |
Expand Down
Loading