1
0
mirror of https://github.com/golang/go synced 2024-11-22 22:00:02 -07:00

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 <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Robert Griesemer 2023-04-13 16:11:14 -07:00 committed by Gopher Robot
parent d259a50d15
commit 57678d5e03
4 changed files with 32 additions and 20 deletions

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)