@@ -710,7 +710,7 @@ object Erasure {
710
710
if (sym.isEffectivelyErased) erasedDef(sym)
711
711
else
712
712
val restpe = if sym.isConstructor then defn.UnitType else sym.info.resultType
713
- var vparams = outer.paramDefs (sym)
713
+ var vparams = outerParamDefs (sym)
714
714
::: ddef.vparamss.flatten.filterConserve(! _.symbol.is(Flags .Erased ))
715
715
716
716
def skipContextClosures (rhs : Tree , crCount : Int )(using Context ): Tree =
@@ -746,6 +746,28 @@ object Erasure {
746
746
super .typedDefDef(ddef1, sym)
747
747
end typedDefDef
748
748
749
+ /** The outer parameter definition of a constructor if it needs one */
750
+ private def outerParamDefs (constr : Symbol )(using ctx : Context ): List [ValDef ] =
751
+ if constr.isConstructor && hasOuterParam(constr.owner.asClass) then
752
+ constr.info match
753
+ case MethodTpe (outerName :: _, outerType :: _, _) =>
754
+ val outerSym = ctx.newSymbol(constr, outerName, Flags .Param , outerType)
755
+ ValDef (outerSym) :: Nil
756
+ case _ =>
757
+ // There's a possible race condition that a constructor was looked at
758
+ // after erasure before we had a chance to run ExplicitOuter on its class
759
+ // If furthermore the enclosing class does not always have constructors,
760
+ // but needs constructors in this particular case, we miss the constructor
761
+ // accessor that's produced with an `enteredAfter` in ExplicitOuter, so
762
+ // `tranformInfo` of the constructor in erasure yields a method type without
763
+ // an outer parameter. We fix this problem by adding the missing outer
764
+ // parameter here.
765
+ constr.copySymDenotation(
766
+ info = outer.addParam(constr.owner.asClass, constr.info)
767
+ ).installAfter(erasurePhase)
768
+ outerParamDefs(constr)
769
+ else Nil
770
+
749
771
override def typedClosure (tree : untpd.Closure , pt : Type )(implicit ctx : Context ): Tree = {
750
772
val xxl = defn.isXXLFunctionClass(tree.typeOpt.typeSymbol)
751
773
var implClosure @ Closure (_, meth, _) = super .typedClosure(tree, pt)
0 commit comments