From 57678d5e033fad85660e08a5f5146eeda4022415 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 13 Apr 2023 16:11:14 -0700 Subject: [PATCH] go/types, types2: factor out type parameter renaming from type inference Preparation for reverse type inference where there is no need to rename all type parameters supplied to type inference when passing generic functions as arguments to (possibly generic) function calls. This also leads to a better separation of concerns. Change-Id: Id487a5c1340b743519b9053edc43f8aa99408522 Reviewed-on: https://go-review.googlesource.com/c/go/+/484655 TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer Run-TryBot: Robert Griesemer Auto-Submit: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/call.go | 14 +++++++++++--- src/cmd/compile/internal/types2/infer.go | 12 +++++------- src/go/types/call.go | 14 +++++++++++--- src/go/types/infer.go | 12 +++++------- 4 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index bf561f2c87..7e8fce4350 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -90,8 +90,11 @@ func (check *Checker) funcInst(tsig *Signature, pos syntax.Pos, x *operand, inst } } + // Rename type parameters to avoid problems with recursive instantiations. // Note that NewTuple(params...) below is nil if len(params) == 0, as desired. - targs = check.infer(pos, sig.TypeParams().list(), targs, NewTuple(params...), args) + tparams, params2 := check.renameTParams(pos, sig.TypeParams().list(), NewTuple(params...)) + + targs = check.infer(pos, tparams, targs, params2, args) if targs == nil { // error was already reported x.mode = invalid @@ -457,7 +460,12 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T check.versionErrorf(call.Pos(), "go1.18", "implicit function instantiation") } } - targs := check.infer(call.Pos(), sig.TypeParams().list(), targs, sigParams, args) + + // Rename type parameters to avoid problems with recursive calls. + var tparams []*TypeParam + tparams, sigParams = check.renameTParams(call.Pos(), sig.TypeParams().list(), sigParams) + + targs := check.infer(call.Pos(), tparams, targs, sigParams, args) if targs == nil { return // error already reported } @@ -471,7 +479,7 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T // need to compute it from the adjusted list; otherwise we can // simply use the result signature's parameter list. if adjusted { - sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TypeParams().list(), targs), nil, check.context()).(*Tuple) + sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(tparams, targs), nil, check.context()).(*Tuple) } else { sigParams = rsig.params } diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 77e552d3f3..46f461ea09 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -49,13 +49,6 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, } // len(targs) < n - // Rename type parameters to avoid conflicts in recursive instantiation scenarios. - tparams, params = check.renameTParams(pos, tparams, params) - - if traceInference { - check.dump("-- rename: %s%s ➞ %s\n", tparams, params, targs) - } - // Make sure we have a "full" list of type arguments, some of which may // be nil (unknown). Make a copy so as to not clobber the incoming slice. if len(targs) < n { @@ -390,6 +383,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // renameTParams renames the type parameters in a function signature described by its // type and ordinary parameters (tparams and params) such that each type parameter is // given a new identity. renameTParams returns the new type and ordinary parameters. +// The positions is only used for debug traces. func (check *Checker) renameTParams(pos syntax.Pos, tparams []*TypeParam, params *Tuple) ([]*TypeParam, *Tuple) { // For the purpose of type inference we must differentiate type parameters // occurring in explicit type or value function arguments from the type @@ -418,6 +412,10 @@ func (check *Checker) renameTParams(pos syntax.Pos, tparams []*TypeParam, params // // Type parameter renaming turns the first example into the second // example by renaming the type parameter P into P2. + if len(tparams) == 0 { + return nil, params // nothing to do + } + tparams2 := make([]*TypeParam, len(tparams)) for i, tparam := range tparams { tname := NewTypeName(tparam.Obj().Pos(), tparam.Obj().Pkg(), tparam.Obj().Name(), nil) diff --git a/src/go/types/call.go b/src/go/types/call.go index 854ce7e406..418de06e76 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -94,8 +94,11 @@ func (check *Checker) funcInst(tsig *Signature, pos token.Pos, x *operand, ix *t } } + // Rename type parameters to avoid problems with recursive instantiations. // Note that NewTuple(params...) below is nil if len(params) == 0, as desired. - targs = check.infer(atPos(pos), sig.TypeParams().list(), targs, NewTuple(params...), args) + tparams, params2 := check.renameTParams(pos, sig.TypeParams().list(), NewTuple(params...)) + + targs = check.infer(atPos(pos), tparams, targs, params2, args) if targs == nil { // error was already reported x.mode = invalid @@ -460,7 +463,12 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type check.softErrorf(inNode(call, call.Lparen), UnsupportedFeature, "implicit function instantiation requires go1.18 or later") } } - targs := check.infer(call, sig.TypeParams().list(), targs, sigParams, args) + + // Rename type parameters to avoid problems with recursive calls. + var tparams []*TypeParam + tparams, sigParams = check.renameTParams(call.Pos(), sig.TypeParams().list(), sigParams) + + targs := check.infer(call, tparams, targs, sigParams, args) if targs == nil { return // error already reported } @@ -474,7 +482,7 @@ func (check *Checker) arguments(call *ast.CallExpr, sig *Signature, targs []Type // need to compute it from the adjusted list; otherwise we can // simply use the result signature's parameter list. if adjusted { - sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(sig.TypeParams().list(), targs), nil, check.context()).(*Tuple) + sigParams = check.subst(call.Pos(), sigParams, makeSubstMap(tparams, targs), nil, check.context()).(*Tuple) } else { sigParams = rsig.params } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 7ef7646e7d..f24c729d7a 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -51,13 +51,6 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, } // len(targs) < n - // Rename type parameters to avoid conflicts in recursive instantiation scenarios. - tparams, params = check.renameTParams(posn.Pos(), tparams, params) - - if traceInference { - check.dump("-- rename: %s%s ➞ %s\n", tparams, params, targs) - } - // Make sure we have a "full" list of type arguments, some of which may // be nil (unknown). Make a copy so as to not clobber the incoming slice. if len(targs) < n { @@ -392,6 +385,7 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // renameTParams renames the type parameters in a function signature described by its // type and ordinary parameters (tparams and params) such that each type parameter is // given a new identity. renameTParams returns the new type and ordinary parameters. +// The positions is only used for debug traces. func (check *Checker) renameTParams(pos token.Pos, tparams []*TypeParam, params *Tuple) ([]*TypeParam, *Tuple) { // For the purpose of type inference we must differentiate type parameters // occurring in explicit type or value function arguments from the type @@ -420,6 +414,10 @@ func (check *Checker) renameTParams(pos token.Pos, tparams []*TypeParam, params // // Type parameter renaming turns the first example into the second // example by renaming the type parameter P into P2. + if len(tparams) == 0 { + return nil, params // nothing to do + } + tparams2 := make([]*TypeParam, len(tparams)) for i, tparam := range tparams { tname := NewTypeName(tparam.Obj().Pos(), tparam.Obj().Pkg(), tparam.Obj().Name(), nil) -- 2.48.1