From 73a4684caa1567c06e239dc657b82ede77777e3b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 28 Apr 2023 17:46:00 -0700 Subject: [PATCH] go/types, types2: isParameterized must be able to handle tuples CL 484615 rewrote isParameterized by handling tuple types only where they occur (function signatures). However, isParameterized is also called from Checker.callExpr, with a result parameter list which is a tuple. This CL handles tuples again. Fixes #59890. Change-Id: I35159ff65f23322432557e6abcab939933933d40 Reviewed-on: https://go-review.googlesource.com/c/go/+/490695 Reviewed-by: Robert Griesemer Auto-Submit: Robert Griesemer TryBot-Result: Gopher Robot Reviewed-by: Robert Findley Run-TryBot: Robert Griesemer --- src/cmd/compile/internal/types2/call.go | 4 ++-- src/cmd/compile/internal/types2/infer.go | 10 +++++++--- src/go/types/call.go | 4 ++-- src/go/types/infer.go | 10 +++++++--- .../types/testdata/fixedbugs/issue59890.go | 17 +++++++++++++++++ 5 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 src/internal/types/testdata/fixedbugs/issue59890.go diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 7e8fce43506..20cde9f44ed 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -329,8 +329,8 @@ func (check *Checker) callExpr(x *operand, call *syntax.CallExpr) exprKind { x.expr = call check.hasCallOrRecv = true - // if type inference failed, a parametrized result must be invalidated - // (operands cannot have a parametrized type) + // if type inference failed, a parameterized result must be invalidated + // (operands cannot have a parameterized type) if x.mode == value && sig.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ) { x.mode = invalid } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 46f461ea093..dbe621cded5 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -498,9 +498,13 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { case *Pointer: return w.isParameterized(t.base) - // case *Tuple: - // This case should not occur because tuples only appear - // in signatures where they are handled explicitly. + case *Tuple: + // This case does not occur from within isParameterized + // because tuples only appear in signatures where they + // are handled explicitly. But isParameterized is also + // called by Checker.callExpr with a function result tuple + // if instantiation failed (go.dev/issue/59890). + return t != nil && w.varList(t.vars) case *Signature: // t.tparams may not be nil if we are looking at a signature diff --git a/src/go/types/call.go b/src/go/types/call.go index 418de06e768..979de2338f2 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -334,8 +334,8 @@ func (check *Checker) callExpr(x *operand, call *ast.CallExpr) exprKind { x.expr = call check.hasCallOrRecv = true - // if type inference failed, a parametrized result must be invalidated - // (operands cannot have a parametrized type) + // if type inference failed, a parameterized result must be invalidated + // (operands cannot have a parameterized type) if x.mode == value && sig.TypeParams().Len() > 0 && isParameterized(sig.TypeParams().list(), x.typ) { x.mode = invalid } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index f24c729d7af..3aa66105c40 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -500,9 +500,13 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) { case *Pointer: return w.isParameterized(t.base) - // case *Tuple: - // This case should not occur because tuples only appear - // in signatures where they are handled explicitly. + case *Tuple: + // This case does not occur from within isParameterized + // because tuples only appear in signatures where they + // are handled explicitly. But isParameterized is also + // called by Checker.callExpr with a function result tuple + // if instantiation failed (go.dev/issue/59890). + return t != nil && w.varList(t.vars) case *Signature: // t.tparams may not be nil if we are looking at a signature diff --git a/src/internal/types/testdata/fixedbugs/issue59890.go b/src/internal/types/testdata/fixedbugs/issue59890.go new file mode 100644 index 00000000000..ed7afd939aa --- /dev/null +++ b/src/internal/types/testdata/fixedbugs/issue59890.go @@ -0,0 +1,17 @@ +// Copyright 2023 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _() { g /* ERROR "cannot infer T" */ () } + +func g[T any]() (_ /* ERROR "cannot use _ as value or type" */, int) { panic(0) } + +// test case from issue + +var _ = append(f /* ERROR "cannot infer T" */ ()()) + +func f[T any]() (_ /* ERROR "cannot use _" */, _ /* ERROR "cannot use _" */, int) { + panic("not implemented") +}