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