@@ -598,7 +598,11 @@ func (check *Checker) updateExprVal(x ast.Expr, val constant.Value) {
598598func (check * Checker ) convertUntyped (x * operand , target Type ) {
599599 newType , val , code := check .implicitTypeAndValue (x , target )
600600 if code != 0 {
601- check .invalidConversion (code , x , safeUnderlying (target ))
601+ t := target
602+ if ! tparamIsIface || ! isTypeParam (target ) {
603+ t = safeUnderlying (target )
604+ }
605+ check .invalidConversion (code , x , t )
602606 x .mode = invalid
603607 return
604608 }
@@ -678,6 +682,7 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
678682 }
679683 case * TypeParam :
680684 // TODO(gri) review this code - doesn't look quite right
685+ assert (! tparamIsIface )
681686 ok := u .underIs (func (t Type ) bool {
682687 if t == nil {
683688 return false
@@ -693,6 +698,24 @@ func (check *Checker) implicitTypeAndValue(x *operand, target Type) (Type, const
693698 return Typ [UntypedNil ], nil , 0
694699 }
695700 case * Interface :
701+ if tparamIsIface && isTypeParam (target ) {
702+ // TODO(gri) review this code - doesn't look quite right
703+ ok := u .typeSet ().underIs (func (t Type ) bool {
704+ if t == nil {
705+ return false
706+ }
707+ target , _ , _ := check .implicitTypeAndValue (x , t )
708+ return target != nil
709+ })
710+ if ! ok {
711+ return nil , nil , _InvalidUntypedConversion
712+ }
713+ // keep nil untyped (was bug #39755)
714+ if x .isNil () {
715+ return Typ [UntypedNil ], nil , 0
716+ }
717+ break
718+ }
696719 // Values must have concrete dynamic types. If the value is nil,
697720 // keep it untyped (this is important for tools such as go vet which
698721 // need the dynamic type for argument checking of say, print
@@ -961,8 +984,9 @@ func (check *Checker) binary(x *operand, e ast.Expr, lhs, rhs ast.Expr, op token
961984 return
962985 }
963986
987+ // TODO(gri) make canMix more efficient - called for each binary operation
964988 canMix := func (x , y * operand ) bool {
965- if IsInterface (x .typ ) || IsInterface (y .typ ) {
989+ if IsInterface (x .typ ) && ! isTypeParam ( x . typ ) || IsInterface ( y . typ ) && ! isTypeParam (y .typ ) {
966990 return true
967991 }
968992 if allBoolean (x .typ ) != allBoolean (y .typ ) {
@@ -1219,7 +1243,11 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
12191243 case hint != nil :
12201244 // no composite literal type present - use hint (element type of enclosing type)
12211245 typ = hint
1222- base , _ = deref (under (typ )) // *T implies &T{}
1246+ base = typ
1247+ if ! isTypeParam (typ ) {
1248+ base = under (typ )
1249+ }
1250+ base , _ = deref (base ) // *T implies &T{}
12231251
12241252 default :
12251253 // TODO(gri) provide better error messages depending on context
0 commit comments