@@ -321,72 +321,11 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
321321 }
322322 }
323323
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-
349324 /** Normalize a list of parent types of class `cls` that may contain refinements
350325 * to a list of typerefs referring to classes, by converting all refinements to member
351326 * definitions in scope `decls`. Can add members to `decls` as a side-effect.
352327 */
353328 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-
390329 // println(s"normalizing $parents of $cls in ${cls.owner}") // !!! DEBUG
391330
392331 // A map consolidating all refinements arising from parent type parameters
@@ -429,16 +368,70 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
429368 s " redefinition of ${decls.lookup(name).debugString} in ${cls.showLocated}" )
430369 enterArgBinding(formals(name), refinedInfo, cls, decls)
431370 }
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+
439375 parentRefs
440376 }
441377
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+
442435 /** An argument bounds violation is a triple consisting of
443436 * - the argument tree
444437 * - a string "upper" or "lower" indicating which bound is violated
0 commit comments