]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: exclude untyped nil arguments early in type inference
authorRobert Griesemer <gri@golang.org>
Thu, 4 May 2023 17:54:12 +0000 (10:54 -0700)
committerGopher Robot <gobot@golang.org>
Fri, 5 May 2023 16:51:41 +0000 (16:51 +0000)
An untyped nil argument cannot be used to infer any type information.
We don't need to include it in the untyped arguments.

Change-Id: Ied44738ff1b135e65a3acfa19223cd3889b7fa7d
Reviewed-on: https://go-review.googlesource.com/c/go/+/492695
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/infer.go
src/cmd/compile/internal/types2/operand.go
src/go/types/infer.go
src/go/types/operand.go

index ce6bb91e9623eba80f54c9a11dab2d5790d67f75..fed85c3d9efa4f64b1985285be80b7e1380a729a 100644 (file)
@@ -163,12 +163,13 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
                                        errorf("type", par.typ, arg.typ, arg)
                                        return nil
                                }
-                       } else if _, ok := par.typ.(*TypeParam); ok {
+                       } else if _, ok := par.typ.(*TypeParam); ok && !arg.isNil() {
                                // Since default types are all basic (i.e., non-composite) types, an
                                // untyped argument will never match a composite parameter type; the
                                // only parameter type it can possibly match against is a *TypeParam.
                                // Thus, for untyped arguments we only need to look at parameter types
                                // that are single type parameters.
+                               // Also, untyped nils don't have a default type and can be ignored.
                                untyped = append(untyped, i)
                        }
                }
@@ -290,15 +291,14 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
                        j++
                }
        }
-       // untyped[:j] are the indices of parameters without a type yet
+       // untyped[:j] are the indices of parameters without a type yet.
+       // The respective default types are typed (not untyped) by construction.
        for _, i := range untyped[:j] {
                tpar := params.At(i).typ.(*TypeParam)
                arg := args[i]
                typ := Default(arg.typ)
-               // The default type for an untyped nil is untyped nil which must
-               // not be inferred as type parameter type. Ignore them by making
-               // sure all default types are typed.
-               if isTyped(typ) && !u.unify(tpar, typ) {
+               assert(isTyped(typ))
+               if !u.unify(tpar, typ) {
                        errorf("default type", tpar, typ, arg)
                        return nil
                }
index 344fe292c59999741016c4b25c6e2ee75ff4bc79..db9a6d84782b38a4eae7111b07b5ce809c6e8ee6 100644 (file)
@@ -235,7 +235,7 @@ func (x *operand) setConst(k syntax.LitKind, lit string) {
        x.val = val
 }
 
-// isNil reports whether x is a typed or the untyped nil value.
+// isNil reports whether x is the (untyped) nil value.
 func (x *operand) isNil() bool { return x.mode == nilvalue }
 
 // assignableTo reports whether x is assignable to a variable of type T. If the
index 9810c95c9b3e17795b0d9db8d979c851a8800e22..9ecef1e4481bb416dd295e274be5c9ee4643706b 100644 (file)
@@ -165,12 +165,13 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
                                        errorf("type", par.typ, arg.typ, arg)
                                        return nil
                                }
-                       } else if _, ok := par.typ.(*TypeParam); ok {
+                       } else if _, ok := par.typ.(*TypeParam); ok && !arg.isNil() {
                                // Since default types are all basic (i.e., non-composite) types, an
                                // untyped argument will never match a composite parameter type; the
                                // only parameter type it can possibly match against is a *TypeParam.
                                // Thus, for untyped arguments we only need to look at parameter types
                                // that are single type parameters.
+                               // Also, untyped nils don't have a default type and can be ignored.
                                untyped = append(untyped, i)
                        }
                }
@@ -292,15 +293,14 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
                        j++
                }
        }
-       // untyped[:j] are the indices of parameters without a type yet
+       // untyped[:j] are the indices of parameters without a type yet.
+       // The respective default types are typed (not untyped) by construction.
        for _, i := range untyped[:j] {
                tpar := params.At(i).typ.(*TypeParam)
                arg := args[i]
                typ := Default(arg.typ)
-               // The default type for an untyped nil is untyped nil which must
-               // not be inferred as type parameter type. Ignore them by making
-               // sure all default types are typed.
-               if isTyped(typ) && !u.unify(tpar, typ) {
+               assert(isTyped(typ))
+               if !u.unify(tpar, typ) {
                        errorf("default type", tpar, typ, arg)
                        return nil
                }
index c6c454283083dc2cc595ac25a69aa7e2ca4ef08a..449b2ebb07c3df3a5a27cc545c2b7f13ebe1e613 100644 (file)
@@ -222,10 +222,8 @@ func (x *operand) setConst(tok token.Token, lit string) {
        x.val = val
 }
 
-// isNil reports whether x is the nil value.
-func (x *operand) isNil() bool {
-       return x.mode == value && x.typ == Typ[UntypedNil]
-}
+// isNil reports whether x is the (untyped) nil value.
+func (x *operand) isNil() bool { return x.mode == value && x.typ == Typ[UntypedNil] }
 
 // assignableTo reports whether x is assignable to a variable of type T. If the
 // result is false and a non-nil cause is provided, it may be set to a more