]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: factor out type parameter renaming from type inference
authorRobert Griesemer <gri@golang.org>
Thu, 13 Apr 2023 23:11:14 +0000 (16:11 -0700)
committerGopher Robot <gobot@golang.org>
Mon, 17 Apr 2023 14:01:19 +0000 (14:01 +0000)
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>
src/cmd/compile/internal/types2/call.go
src/cmd/compile/internal/types2/infer.go
src/go/types/call.go
src/go/types/infer.go

index bf561f2c872aa5decc69f6f3c33fb687a8309f96..7e8fce43506ff861a945047acc9f489738ed770c 100644 (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
                }
index 77e552d3f3112c77c47ed74a44ffa62c0c1358dd..46f461ea0933521316bd044d24b19ea10ac3c482 100644 (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)
index 854ce7e406b9fa4ecc5b7fa1ac1e42fdfed70f82..418de06e76887c68f873e2c6d52bde090844410e 100644 (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
                }
index 7ef7646e7dacf78026c479500951390bce41942b..f24c729d7af79c870c74e3984c049f902a8dae10 100644 (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)