From a5350558e6e2db16bfe09f2ba8104549c6598c46 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 4 May 2023 10:54:12 -0700 Subject: [PATCH] go/types, types2: exclude untyped nil arguments early in type inference 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 Run-TryBot: Robert Griesemer Auto-Submit: Robert Griesemer TryBot-Result: Gopher Robot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/infer.go | 12 ++++++------ src/cmd/compile/internal/types2/operand.go | 2 +- src/go/types/infer.go | 12 ++++++------ src/go/types/operand.go | 6 ++---- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index ce6bb91e9623eb..fed85c3d9efa4f 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -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 } diff --git a/src/cmd/compile/internal/types2/operand.go b/src/cmd/compile/internal/types2/operand.go index 344fe292c59999..db9a6d84782b38 100644 --- a/src/cmd/compile/internal/types2/operand.go +++ b/src/cmd/compile/internal/types2/operand.go @@ -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 diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 9810c95c9b3e17..9ecef1e4481bb4 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -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 } diff --git a/src/go/types/operand.go b/src/go/types/operand.go index c6c454283083dc..449b2ebb07c3df 100644 --- a/src/go/types/operand.go +++ b/src/go/types/operand.go @@ -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