From 67ec59003a9392052b70d2b36f23c4108d2e4b5c Mon Sep 17 00:00:00 2001 From: Grant Nelson Date: Wed, 2 Oct 2024 16:23:24 -0600 Subject: [PATCH] Adding more tests around IndexExpr case --- compiler/internal/analysis/info.go | 5 +++ compiler/internal/analysis/info_test.go | 44 ++++++++++++++++++++++++- internal/srctesting/srctesting.go | 2 +- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/compiler/internal/analysis/info.go b/compiler/internal/analysis/info.go index 4a2e50078..4d83a6c04 100644 --- a/compiler/internal/analysis/info.go +++ b/compiler/internal/analysis/info.go @@ -356,6 +356,11 @@ func (fi *FuncInfo) visitCallExpr(n *ast.CallExpr) ast.Visitor { // Register literal function call site in case it is identified as blocking. fi.literalFuncCallees[f] = append(fi.literalFuncCallees[f], fi.visitorStack.copy()) return nil // No need to walk under this CallExpr, we already did it manually. + case *ast.IndexExpr: + // Collect info about the instantiated type or function. + + fmt.Printf(">> %[1]T %#[1]v\n", n) // TODO(gn): Finish implementing! + default: if astutil.IsTypeExpr(f, fi.pkgInfo.Info) { // This is a type conversion, not a call. Type assertion itself is not diff --git a/compiler/internal/analysis/info_test.go b/compiler/internal/analysis/info_test.go index 7573fcb4c..cb567bf0a 100644 --- a/compiler/internal/analysis/info_test.go +++ b/compiler/internal/analysis/info_test.go @@ -55,7 +55,7 @@ func TestInstanceBlocking(t *testing.T) { notBlocking []string }{ { - name: "blocking instance", + name: `blocking instance`, src: `package test func blocking[T any]() { c := make(chan T) @@ -73,6 +73,48 @@ func TestInstanceBlocking(t *testing.T) { blocking: []string{`blocking`, `bInt`}, notBlocking: []string{`notBlocking`, `nbUint`}, }, + { + name: `differentiate indexing`, + // Below calls notBlocking but since the function pointers + // are in the slice they will both be considered as blocking. + // This is just checking that the analysis can tell between + // indexing and instantiation of a generic. + src: `package test + func blocking() { + c := make(chan int) + <-c + } + func notBlocking() { + println() + } + var funcs = []func() { blocking, notBlocking } + func indexer() { + funcs[1]() + }`, + blocking: []string{`blocking`, `indexer`}, + notBlocking: []string{`notBlocking`}, + }, + { + name: `differentiate casting`, + // Below checks that casting to an instance type is treated as a + // cast an not accidentally treated as a function call. + src: `package test + type Foo[T any] interface { + Baz() T + } + type Bar struct { + name string + } + func (b Bar) Baz() string { + return b.name + } + func caster() { + a := Bar{"foo"} + b := Foo[string](a) + println(b.Baz()) + }`, + notBlocking: []string{`caster`}, + }, } for _, test := range tests { diff --git a/internal/srctesting/srctesting.go b/internal/srctesting/srctesting.go index a74d31958..6bba9fced 100644 --- a/internal/srctesting/srctesting.go +++ b/internal/srctesting/srctesting.go @@ -71,7 +71,7 @@ func (f *Fixture) Check(importPath string, files ...*ast.File) (*types.Info, *ty } pkg, err := config.Check(importPath, f.FileSet, files, info) if err != nil { - f.T.Fatalf("Filed to type check test source: %s", err) + f.T.Fatalf("Failed to type check test source: %s", err) } f.Packages[importPath] = pkg return info, pkg