@@ -710,7 +710,7 @@ object Erasure {
710710 if (sym.isEffectivelyErased) erasedDef(sym)
711711 else
712712 val restpe = if sym.isConstructor then defn.UnitType else sym.info.resultType
713- var vparams = outer.paramDefs (sym)
713+ var vparams = outerParamDefs (sym)
714714 ::: ddef.vparamss.flatten.filterConserve(! _.symbol.is(Flags .Erased ))
715715
716716 def skipContextClosures (rhs : Tree , crCount : Int )(using Context ): Tree =
@@ -746,6 +746,28 @@ object Erasure {
746746 super .typedDefDef(ddef1, sym)
747747 end typedDefDef
748748
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+
749771 override def typedClosure (tree : untpd.Closure , pt : Type )(implicit ctx : Context ): Tree = {
750772 val xxl = defn.isXXLFunctionClass(tree.typeOpt.typeSymbol)
751773 var implClosure @ Closure (_, meth, _) = super .typedClosure(tree, pt)
0 commit comments