@@ -236,10 +236,10 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
236
236
u .tracef ("-- type parameter %s = %s: core(%s) = %s, single = %v" , tpar , tx , tpar , core , single )
237
237
}
238
238
239
- // If there is a core term (i.e., a core type with tilde information)
240
- // unify the type parameter with the core type.
239
+ // If the type parameter's constraint has a core term (i.e., a core type with tilde information)
240
+ // try to unify the type parameter with that core type.
241
241
if core != nil {
242
- // A type parameter can be unified with its core type in two cases.
242
+ // A type parameter can be unified with its constraint's core type in two cases.
243
243
switch {
244
244
case tx != nil :
245
245
if traceInference {
@@ -266,33 +266,42 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
266
266
if traceInference {
267
267
u .tracef ("-> set type parameter %s to constraint core type %s" , tpar , core .typ )
268
268
}
269
- // The corresponding type argument tx is unknown and there's a single
270
- // specific type and no tilde.
269
+ // The corresponding type argument tx is unknown and the core term
270
+ // describes a single specific type and no tilde.
271
271
// In this case the type argument must be that single type; set it.
272
272
u .set (tpar , core .typ )
273
273
}
274
- } else {
275
- if tx != nil {
276
- if traceInference {
277
- u .tracef ("-> unify type parameter %s (type %s) methods with constraint methods" , tpar , tx )
278
- }
279
- // We don't have a core type, but the type argument tx is known.
280
- // It must have (at least) all the methods of the type constraint,
281
- // and the method signatures must unify; otherwise tx cannot satisfy
282
- // the constraint.
283
- // TODO(gri) Now that unification handles interfaces, this code can
284
- // be reduced to calling u.unify(tx, tpar.iface(), assign)
285
- // (which will compare signatures exactly as we do below).
286
- // We leave it as is for now because missingMethod provides
287
- // a failure cause which allows for a better error message.
288
- // Eventually, unify should return an error with cause.
289
- var cause string
290
- constraint := tpar .iface ()
291
- if m , _ := check .missingMethod (tx , constraint , true , func (x , y Type ) bool { return u .unify (x , y , exact ) }, & cause ); m != nil {
292
- // TODO(gri) better error message (see TODO above)
293
- err .addf (pos , "%s (type %s) does not satisfy %s %s" , tpar , tx , tpar .Constraint (), cause )
294
- return nil
295
- }
274
+ }
275
+
276
+ // Independent of whether there is a core term, if the type argument tx is known
277
+ // it must implement the methods of the type constraint, possibly after unification
278
+ // of the relevant method signatures, otherwise tx cannot satisfy the constraint.
279
+ // This unification step may provide additional type arguments.
280
+ //
281
+ // Note: The type argument tx may be known but contain references to other type
282
+ // parameters (i.e., tx may still be parameterized).
283
+ // In this case the methods of tx don't correctly reflect the final method set
284
+ // and we may get a missing method error below. Skip this step in this case.
285
+ //
286
+ // TODO(gri) We should be able continue even with a parameterized tx if we add
287
+ // a simplify step beforehand (see below). This will require factoring out the
288
+ // simplify phase so we can call it from here.
289
+ if tx != nil && ! isParameterized (tparams , tx ) {
290
+ if traceInference {
291
+ u .tracef ("-> unify type parameter %s (type %s) methods with constraint methods" , tpar , tx )
292
+ }
293
+ // TODO(gri) Now that unification handles interfaces, this code can
294
+ // be reduced to calling u.unify(tx, tpar.iface(), assign)
295
+ // (which will compare signatures exactly as we do below).
296
+ // We leave it as is for now because missingMethod provides
297
+ // a failure cause which allows for a better error message.
298
+ // Eventually, unify should return an error with cause.
299
+ var cause string
300
+ constraint := tpar .iface ()
301
+ if m , _ := check .missingMethod (tx , constraint , true , func (x , y Type ) bool { return u .unify (x , y , exact ) }, & cause ); m != nil {
302
+ // TODO(gri) better error message (see TODO above)
303
+ err .addf (pos , "%s (type %s) does not satisfy %s %s" , tpar , tx , tpar .Constraint (), cause )
304
+ return nil
296
305
}
297
306
}
298
307
}
0 commit comments