@@ -789,9 +789,36 @@ class Namer { typer: Typer =>
789
789
/** The type signature of a DefDef with given symbol */
790
790
def defDefSig (ddef : DefDef , sym : Symbol )(implicit ctx : Context ) = {
791
791
val DefDef (name, tparams, vparamss, _, _) = ddef
792
- completeParams(tparams)
793
- vparamss foreach completeParams
794
792
val isConstructor = name == nme.CONSTRUCTOR
793
+
794
+ // The following 3 lines replace what was previously just completeParams(tparams).
795
+ // But that can cause bad bounds being computed, as witnessed by
796
+ // tests/pos/paramcycle.scala. The problematic sequence is this:
797
+ // 0. Class constructor gets completed.
798
+ // 1. Type parameter CP of constructor gets completed
799
+ // 2. As a first step CP's bounds are set to Nothing..Any.
800
+ // 3. CP's real type bound demands the completion of corresponding type parameter DP
801
+ // of enclosing class.
802
+ // 4. Type parameter DP has a rhs a DerivedFromParam tree, as installed by
803
+ // desugar.classDef
804
+ // 5. The completion of DP then copies the current bounds of CP, which are still Nothing..Any.
805
+ // 6. The completion of CP finishes installing the real type bounds.
806
+ // Consequence: CP ends up with the wrong bounds!
807
+ // To avoid this we always complete type parameters of a class before the type parameters
808
+ // of the class constructor, but after having indexed the constructor parameters (because
809
+ // indexing is needed to provide a symbol to copy for DP's completion.
810
+ // With the patch, we get instead the following sequence:
811
+ // 0. Class constructor gets completed.
812
+ // 1. Class constructor parameter CP is indexed.
813
+ // 2. Class parameter DP starts completion.
814
+ // 3. Info of CP is computed (to be copied to DP).
815
+ // 4. CP is completed.
816
+ // 5. Info of CP is copied to DP and DP is completed.
817
+ index(tparams)
818
+ if (isConstructor) sym.owner.typeParams.foreach(_.ensureCompleted())
819
+ for (tparam <- tparams) typedAheadExpr(tparam)
820
+
821
+ vparamss foreach completeParams
795
822
def typeParams = tparams map symbolOfTree
796
823
val paramSymss = ctx.normalizeIfConstructor(vparamss.nestedMap(symbolOfTree), isConstructor)
797
824
def wrapMethType (restpe : Type ): Type = {
@@ -834,8 +861,11 @@ class Namer { typer: Typer =>
834
861
case bounds : TypeBounds => bounds
835
862
case alias => TypeAlias (alias, if (sym is Local ) sym.variance else 0 )
836
863
}
837
- sym.info = NoCompleter
838
- sym.info = checkNonCyclic(sym, unsafeInfo, reportErrors = true )
864
+ if (isDerived) sym.info = unsafeInfo
865
+ else {
866
+ sym.info = NoCompleter
867
+ sym.info = checkNonCyclic(sym, unsafeInfo, reportErrors = true )
868
+ }
839
869
etaExpandArgs.apply(sym.info)
840
870
}
841
871
0 commit comments