all: merge master (43b469a) into gopls-release-branch.0.7 Merge List: + 2021-11-17 43b469a3 go/analysis/passes/printf: update logic now that type parameters are interfaces + 2021-11-17 771dabf4 gopls/internal/regtest/misc: skip TestInconsistentVendoring on Windows + 2021-11-17 7d6c71f2 internal/lsp/source/completion: avoid invalid AST in enclosingSignature Change-Id: I7926670ad4f2897ac4951f08ad37df9b39222847
diff --git a/go/analysis/passes/printf/printf.go b/go/analysis/passes/printf/printf.go index 0206073..dee37d7 100644 --- a/go/analysis/passes/printf/printf.go +++ b/go/analysis/passes/printf/printf.go
@@ -25,6 +25,7 @@ "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/go/types/typeutil" + "golang.org/x/tools/internal/typeparams" ) func init() { @@ -520,7 +521,12 @@ func isFormatter(typ types.Type) bool { // If the type is an interface, the value it holds might satisfy fmt.Formatter. if _, ok := typ.Underlying().(*types.Interface); ok { - return true + // Don't assume type parameters could be formatters. With the greater + // expressiveness of constraint interface syntax we expect more type safety + // when using type parameters. + if !typeparams.IsTypeParam(typ) { + return true + } } obj, _, _ := types.LookupFieldOrMethod(typ, false, nil, "Format") fn, ok := obj.(*types.Func)
diff --git a/go/analysis/passes/printf/types.go b/go/analysis/passes/printf/types.go index 81bf36e..270e917 100644 --- a/go/analysis/passes/printf/types.go +++ b/go/analysis/passes/printf/types.go
@@ -178,10 +178,12 @@ return true } + if typeparams.IsTypeParam(typ.Elem()) { + return true // We don't know whether the logic below applies. Give up. + } + under := typ.Elem().Underlying() switch under.(type) { - case *typeparams.TypeParam: - return true // We don't know whether the logic below applies. Give up. case *types.Struct: // see below case *types.Array: // see below case *types.Slice: // see below
diff --git a/gopls/internal/regtest/misc/vendor_test.go b/gopls/internal/regtest/misc/vendor_test.go index 4e02799..0e615f2 100644 --- a/gopls/internal/regtest/misc/vendor_test.go +++ b/gopls/internal/regtest/misc/vendor_test.go
@@ -5,6 +5,7 @@ package misc import ( + "runtime" "testing" . "golang.org/x/tools/internal/lsp/regtest" @@ -26,6 +27,9 @@ func TestInconsistentVendoring(t *testing.T) { testenv.NeedsGo1Point(t, 14) + if runtime.GOOS == "windows" { + t.Skipf("skipping test due to flakiness on Windows: https://golang.org/issue/49646") + } const pkgThatUsesVendoring = ` -- go.mod --
diff --git a/internal/lsp/source/completion/completion.go b/internal/lsp/source/completion/completion.go index dbc380c..94389c7 100644 --- a/internal/lsp/source/completion/completion.go +++ b/internal/lsp/source/completion/completion.go
@@ -1694,6 +1694,12 @@ } case *ast.FuncLit: if typ, ok := info.Types[t]; ok { + if sig, _ := typ.Type.(*types.Signature); sig == nil { + // golang/go#49397: it should not be possible, but we somehow arrived + // here with a non-signature type, most likely due to AST mangling + // such that node.Type is not a FuncType. + return nil + } return &funcInfo{ sig: typ.Type.(*types.Signature), body: t.Body,
diff --git a/internal/typeparams/common.go b/internal/typeparams/common.go index 9fc6b4b..961d036 100644 --- a/internal/typeparams/common.go +++ b/internal/typeparams/common.go
@@ -13,6 +13,7 @@ import ( "go/ast" "go/token" + "go/types" ) // A IndexExprData holds data from both ast.IndexExpr and the new @@ -23,3 +24,9 @@ Indices []ast.Expr // index expressions Rbrack token.Pos // position of "]" } + +// IsTypeParam reports whether t is a type parameter. +func IsTypeParam(t types.Type) bool { + _, ok := t.(*TypeParam) + return ok +}