@@ -321,73 +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- ! 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-
350324 /** Normalize a list of parent types of class `cls` that may contain refinements
351325 * to a list of typerefs referring to classes, by converting all refinements to member
352326 * definitions in scope `decls`. Can add members to `decls` as a side-effect.
353327 */
354328 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-
391329 // println(s"normalizing $parents of $cls in ${cls.owner}") // !!! DEBUG
392330
393331 // A map consolidating all refinements arising from parent type parameters
@@ -430,16 +368,70 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
430368 s " redefinition of ${decls.lookup(name).debugString} in ${cls.showLocated}" )
431369 enterArgBinding(formals(name), refinedInfo, cls, decls)
432370 }
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+
440375 parentRefs
441376 }
442377
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+
443435 /** An argument bounds violation is a triple consisting of
444436 * - the argument tree
445437 * - a string "upper" or "lower" indicating which bound is violated
0 commit comments