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