mirror of
https://github.com/golang/go
synced 2024-11-23 05:10:09 -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:
parent
d259a50d15
commit
57678d5e03
@ -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.
|
// 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 {
|
if targs == nil {
|
||||||
// error was already reported
|
// error was already reported
|
||||||
x.mode = invalid
|
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")
|
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 {
|
if targs == nil {
|
||||||
return // error already reported
|
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
|
// need to compute it from the adjusted list; otherwise we can
|
||||||
// simply use the result signature's parameter list.
|
// simply use the result signature's parameter list.
|
||||||
if adjusted {
|
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 {
|
} else {
|
||||||
sigParams = rsig.params
|
sigParams = rsig.params
|
||||||
}
|
}
|
||||||
|
@ -49,13 +49,6 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
|||||||
}
|
}
|
||||||
// len(targs) < n
|
// 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
|
// 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.
|
// be nil (unknown). Make a copy so as to not clobber the incoming slice.
|
||||||
if len(targs) < n {
|
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
|
// 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
|
// 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.
|
// 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) {
|
func (check *Checker) renameTParams(pos syntax.Pos, tparams []*TypeParam, params *Tuple) ([]*TypeParam, *Tuple) {
|
||||||
// For the purpose of type inference we must differentiate type parameters
|
// For the purpose of type inference we must differentiate type parameters
|
||||||
// occurring in explicit type or value function arguments from the type
|
// 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
|
// Type parameter renaming turns the first example into the second
|
||||||
// example by renaming the type parameter P into P2.
|
// example by renaming the type parameter P into P2.
|
||||||
|
if len(tparams) == 0 {
|
||||||
|
return nil, params // nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
tparams2 := make([]*TypeParam, len(tparams))
|
tparams2 := make([]*TypeParam, len(tparams))
|
||||||
for i, tparam := range tparams {
|
for i, tparam := range tparams {
|
||||||
tname := NewTypeName(tparam.Obj().Pos(), tparam.Obj().Pkg(), tparam.Obj().Name(), nil)
|
tname := NewTypeName(tparam.Obj().Pos(), tparam.Obj().Pkg(), tparam.Obj().Name(), nil)
|
||||||
|
@ -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.
|
// 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 {
|
if targs == nil {
|
||||||
// error was already reported
|
// error was already reported
|
||||||
x.mode = invalid
|
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")
|
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 {
|
if targs == nil {
|
||||||
return // error already reported
|
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
|
// need to compute it from the adjusted list; otherwise we can
|
||||||
// simply use the result signature's parameter list.
|
// simply use the result signature's parameter list.
|
||||||
if adjusted {
|
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 {
|
} else {
|
||||||
sigParams = rsig.params
|
sigParams = rsig.params
|
||||||
}
|
}
|
||||||
|
@ -51,13 +51,6 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
|
|||||||
}
|
}
|
||||||
// len(targs) < n
|
// 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
|
// 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.
|
// be nil (unknown). Make a copy so as to not clobber the incoming slice.
|
||||||
if len(targs) < n {
|
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
|
// 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
|
// 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.
|
// 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) {
|
func (check *Checker) renameTParams(pos token.Pos, tparams []*TypeParam, params *Tuple) ([]*TypeParam, *Tuple) {
|
||||||
// For the purpose of type inference we must differentiate type parameters
|
// For the purpose of type inference we must differentiate type parameters
|
||||||
// occurring in explicit type or value function arguments from the type
|
// 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
|
// Type parameter renaming turns the first example into the second
|
||||||
// example by renaming the type parameter P into P2.
|
// example by renaming the type parameter P into P2.
|
||||||
|
if len(tparams) == 0 {
|
||||||
|
return nil, params // nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
tparams2 := make([]*TypeParam, len(tparams))
|
tparams2 := make([]*TypeParam, len(tparams))
|
||||||
for i, tparam := range tparams {
|
for i, tparam := range tparams {
|
||||||
tname := NewTypeName(tparam.Obj().Pos(), tparam.Obj().Pkg(), tparam.Obj().Name(), nil)
|
tname := NewTypeName(tparam.Obj().Pos(), tparam.Obj().Pkg(), tparam.Obj().Name(), nil)
|
||||||
|
Loading…
Reference in New Issue
Block a user