@@ -321,72 +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
- // println(s"short-circuit ${argSym.name} was: ${argSym.info}, now: $to")
343
- enterArgBinding(argSym, to, cls, decls)
344
- }
345
- case _ =>
346
- }
347
-
348
-
349
324
/** Normalize a list of parent types of class `cls` that may contain refinements
350
325
* to a list of typerefs referring to classes, by converting all refinements to member
351
326
* definitions in scope `decls`. Can add members to `decls` as a side-effect.
352
327
*/
353
328
def normalizeToClassRefs (parents : List [Type ], cls : ClassSymbol , decls : Scope ): List [TypeRef ] = {
354
-
355
- /** If we just entered the type argument binding
356
- *
357
- * type From = To
358
- *
359
- * and there is a type argument binding in a parent in `prefs` of the form
360
- *
361
- * type X = From
362
- *
363
- * then also add the binding
364
- *
365
- * type X = To
366
- *
367
- * to the current scope, provided (1) variances of both aliases are the same, and
368
- * (2) X is not yet defined in current scope. This "short-circuiting" prevents
369
- * long chains of aliases which would have to be traversed in type comparers.
370
- *
371
- * Note: Test i1401.scala shows that `forwardRefs` is also necessary
372
- * for typechecking in the case where self types refer to type parameters
373
- * that are upper-bounded by subclass instances.
374
- */
375
- def forwardRefs (from : Symbol , to : Type , prefs : List [TypeRef ]) = to match {
376
- case to @ TypeBounds (lo1, hi1) if lo1 eq hi1 =>
377
- for (pref <- prefs) {
378
- def forward ()(implicit ctx : Context ): Unit =
379
- for (argSym <- pref.decls)
380
- if (argSym is BaseTypeArg )
381
- forwardRef(argSym, from, to, cls, decls)
382
- pref.info match {
383
- case info : TempClassInfo => info.addSuspension(implicit ctx => forward())
384
- case _ => forward()
385
- }
386
- }
387
- case _ =>
388
- }
389
-
390
329
// println(s"normalizing $parents of $cls in ${cls.owner}") // !!! DEBUG
391
330
392
331
// A map consolidating all refinements arising from parent type parameters
@@ -429,16 +368,70 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
429
368
s " redefinition of ${decls.lookup(name).debugString} in ${cls.showLocated}" )
430
369
enterArgBinding(formals(name), refinedInfo, cls, decls)
431
370
}
432
- // Forward definitions in super classes that have one of the refined parameters
433
- // as aliases directly to the refined info.
434
- // Note that this cannot be fused with the previous loop because we now
435
- // assume that all arguments have been entered in `decls`.
436
- refinements foreachBinding { (name, refinedInfo) =>
437
- forwardRefs(formals(name), refinedInfo, parentRefs)
438
- }
371
+
372
+ if (Config .forwardTypeParams)
373
+ forwardParamBindings(parentRefs, refinements, cls, decls)
374
+
439
375
parentRefs
440
376
}
441
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
+
442
435
/** An argument bounds violation is a triple consisting of
443
436
* - the argument tree
444
437
* - a string "upper" or "lower" indicating which bound is violated
0 commit comments