From 8f4c020660d4c8a7bab9a7363551d07176e638eb Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 29 Aug 2021 06:49:28 -0700 Subject: [PATCH] cmd/compile: fix bug with Inferred targs We were using the type from the wrong Node (the partially filled-in FUNCINST) rather than the original function node - which is pointed to by the OFUNCINST)) to set the final fully-substituted type of the OFUNCINST. So fixed the node reference. Also, added check so we don't do any work at all if the OFUNCINST already has all type args filled in. Added few extra cases to the test file issue48030.go, to cover fully-specified type args, partially inferred type args, and fully inferred type args. Fixes #48030 Change-Id: If9e4f2e0514d68b9d241f30c423259133932b25b Reviewed-on: https://go-review.googlesource.com/c/go/+/346229 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Go Bot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 16 +++++++++------- test/typeparam/issue48030.go | 26 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 test/typeparam/issue48030.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 0e5257d7cf9..863acf587d8 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -126,13 +126,15 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { targs[i] = ir.TypeNode(g.typ(inferred.TArgs.At(i))) } if fun.Op() == ir.OFUNCINST { - // Replace explicit type args with the full list that - // includes the additional inferred type args. - // Substitute the type args for the type params in - // the generic function's type. - fun.(*ir.InstExpr).Targs = targs - newt := g.substType(fun.Type(), fun.Type().TParams(), targs) - typed(newt, fun) + if len(fun.(*ir.InstExpr).Targs) < len(targs) { + // Replace explicit type args with the full list that + // includes the additional inferred type args. + // Substitute the type args for the type params in + // the generic function's type. + fun.(*ir.InstExpr).Targs = targs + newt := g.substType(fun.(*ir.InstExpr).X.Type(), fun.(*ir.InstExpr).X.Type().TParams(), targs) + typed(newt, fun) + } } else { // Create a function instantiation here, given there // are only inferred type args (e.g. min(5,6), where diff --git a/test/typeparam/issue48030.go b/test/typeparam/issue48030.go new file mode 100644 index 00000000000..9fc44288418 --- /dev/null +++ b/test/typeparam/issue48030.go @@ -0,0 +1,26 @@ +// run -gcflags=-G=3 + +// Copyright 2021 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 main + +type Src[T any] func() Src[T] + +func Seq[T any]() Src[T] { + return nil +} + +func Seq2[T1 any, T2 any](v1 T1, v2 T2) Src[T2] { + return nil +} + +func main() { + // Type args fully supplied + Seq[int]() + // Partial inference of type args + Seq2[int](5, "abc") + // Full inference of type args + Seq2(5, "abc") +}