@@ -352,73 +352,11 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
352
352
}
353
353
}
354
354
355
- /** If we have member definitions
356
- *
357
- * type argSym v= from
358
- * type from v= to
359
- *
360
- * where the variances of both alias are the same, then enter a new definition
361
- *
362
- * type argSym v= to
363
- *
364
- * unless a definition for `argSym` already exists in the current scope.
365
- */
366
- def forwardRef (argSym : Symbol , from : Symbol , to : TypeBounds , cls : ClassSymbol , decls : Scope ) =
367
- argSym.info match {
368
- case info @ TypeBounds (lo2 @ TypeRef (_ : ThisType , name), hi2) =>
369
- if (name == from.name &&
370
- (lo2 eq hi2) &&
371
- info.variance == to.variance &&
372
- ! decls.lookup(argSym.name).exists &&
373
- ! ctx.settings.YsuppressParamForwarding .value) {
374
- // println(s"short-circuit ${argSym.name} was: ${argSym.info}, now: $to")
375
- enterArgBinding(argSym, to, cls, decls)
376
- }
377
- case _ =>
378
- }
379
-
380
-
381
355
/** Normalize a list of parent types of class `cls` that may contain refinements
382
356
* to a list of typerefs referring to classes, by converting all refinements to member
383
357
* definitions in scope `decls`. Can add members to `decls` as a side-effect.
384
358
*/
385
359
def normalizeToClassRefs (parents : List [Type ], cls : ClassSymbol , decls : Scope ): List [TypeRef ] = {
386
-
387
- /** If we just entered the type argument binding
388
- *
389
- * type From = To
390
- *
391
- * and there is a type argument binding in a parent in `prefs` of the form
392
- *
393
- * type X = From
394
- *
395
- * then also add the binding
396
- *
397
- * type X = To
398
- *
399
- * to the current scope, provided (1) variances of both aliases are the same, and
400
- * (2) X is not yet defined in current scope. This "short-circuiting" prevents
401
- * long chains of aliases which would have to be traversed in type comparers.
402
- *
403
- * Note: Test i1401.scala shows that `forwardRefs` is also necessary
404
- * for typechecking in the case where self types refer to type parameters
405
- * that are upper-bounded by subclass instances.
406
- */
407
- def forwardRefs (from : Symbol , to : Type , prefs : List [TypeRef ]) = to match {
408
- case to @ TypeBounds (lo1, hi1) if lo1 eq hi1 =>
409
- for (pref <- prefs) {
410
- def forward ()(implicit ctx : Context ): Unit =
411
- for (argSym <- pref.decls)
412
- if (argSym is BaseTypeArg )
413
- forwardRef(argSym, from, to, cls, decls)
414
- pref.info match {
415
- case info : TempClassInfo => info.addSuspension(implicit ctx => forward())
416
- case _ => forward()
417
- }
418
- }
419
- case _ =>
420
- }
421
-
422
360
// println(s"normalizing $parents of $cls in ${cls.owner}") // !!! DEBUG
423
361
424
362
// A map consolidating all refinements arising from parent type parameters
@@ -461,16 +399,70 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
461
399
s " redefinition of ${decls.lookup(name).debugString} in ${cls.showLocated}" )
462
400
enterArgBinding(formals(name), refinedInfo, cls, decls)
463
401
}
464
- // Forward definitions in super classes that have one of the refined parameters
465
- // as aliases directly to the refined info.
466
- // Note that this cannot be fused with the previous loop because we now
467
- // assume that all arguments have been entered in `decls`.
468
- refinements foreachBinding { (name, refinedInfo) =>
469
- forwardRefs(formals(name), refinedInfo, parentRefs)
470
- }
402
+
403
+ if (! ctx.settings.YsuppressParamForwarding .value)
404
+ forwardParamBindings(parentRefs, refinements, cls, decls)
405
+
471
406
parentRefs
472
407
}
473
408
409
+ /** Forward parameter bindings in baseclasses to argument types of
410
+ * class `cls` if possible.
411
+ * If there have member definitions
412
+ *
413
+ * type param v= middle
414
+ * type middle v= to
415
+ *
416
+ * where the variances of both alias are the same, then enter a new definition
417
+ *
418
+ * type param v= to
419
+ *
420
+ * If multiple forwarders would be generated, join their `to` types with an `&`.
421
+ *
422
+ * @param cls The class for which parameter bindings should be forwarded
423
+ * @param decls Its scope
424
+ * @param parentRefs The parent type references of `cls`
425
+ * @param paramBindings The type parameter bindings generated for `cls`
426
+ *
427
+ */
428
+ def forwardParamBindings (parentRefs : List [TypeRef ],
429
+ paramBindings : SimpleMap [TypeName , Type ],
430
+ cls : ClassSymbol , decls : Scope )(implicit ctx : Context ) = {
431
+
432
+ def forwardRef (argSym : Symbol , from : TypeName , to : TypeAlias ) = argSym.info match {
433
+ case info @ TypeAlias (TypeRef (_ : ThisType , `from`)) if info.variance == to.variance =>
434
+ val existing = decls.lookup(argSym.name)
435
+ if (existing.exists) existing.info = existing.info & to
436
+ else enterArgBinding(argSym, to, cls, decls)
437
+ case _ =>
438
+ }
439
+
440
+ def forwardRefs (from : TypeName , to : Type ) = to match {
441
+ case to : TypeAlias =>
442
+ for (pref <- parentRefs) {
443
+ def forward ()(implicit ctx : Context ): Unit =
444
+ for (argSym <- pref.decls)
445
+ if (argSym is BaseTypeArg ) forwardRef(argSym, from, to)
446
+ pref.info match {
447
+ case info : TempClassInfo => info.addSuspension(implicit ctx => forward())
448
+ case _ => forward()
449
+ }
450
+ }
451
+ case _ =>
452
+ }
453
+
454
+ paramBindings.foreachBinding(forwardRefs)
455
+ }
456
+
457
+ /** Used only for debugging: All BaseTypeArg definitions in
458
+ * `cls` and all its base classes.
459
+ */
460
+ def allBaseTypeArgs (cls : ClassSymbol )(implicit ctx : Context ) =
461
+ for { bc <- cls.baseClasses
462
+ sym <- bc.info.decls.toList
463
+ if sym.is(BaseTypeArg )
464
+ } yield sym
465
+
474
466
/** An argument bounds violation is a triple consisting of
475
467
* - the argument tree
476
468
* - a string "upper" or "lower" indicating which bound is violated
0 commit comments