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 ce6bb91e96..fed85c3d9e 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 344fe292c5..db9a6d8478 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 9810c95c9b..9ecef1e448 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 c6c4542830..449b2ebb07 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 -- 2.48.1