From d6528ded4f7655511dd382b50ffe4d1ce9bde434 Mon Sep 17 00:00:00 2001 From: Georg Schmid Date: Sat, 21 Apr 2018 16:39:14 +0200 Subject: [PATCH] Fix #4342: Handle Scala2 method calls with an outer param When calling a Scala 2.x method with an outer parameter, adapt to the old behavior in picking the outer parameter's type, i.e., prefer the enclosing class's self type, rather than the enclosing class itself. --- .../tools/dotc/transform/ExplicitOuter.scala | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index b789f8f95958..3900474bf1cd 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -140,6 +140,20 @@ object ExplicitOuter { private def newOuterAccessors(cls: ClassSymbol)(implicit ctx: Context) = newOuterAccessor(cls, cls) :: (if (cls is Trait) Nil else newOuterParamAccessor(cls) :: Nil) + /** Scala 2.x and Dotty don't always agree on what should be the type of the outer parameter, + * so we replicate the old behavior when passing arguments to methods coming from Scala 2.x. + */ + private def outerClass(cls: ClassSymbol)(implicit ctx: Context): Symbol = { + val encl = cls.owner.enclosingClass + if (cls.is(Scala2x)) + encl.asClass.classInfo.selfInfo match { + case tp: TypeRef => tp.classSymbol + case self: Symbol => self + case _ => encl + } + else encl + } + /** A new outer accessor or param accessor. * @param owner The class where the outer accessor is located * @param cls The class relative to which the outer is computed (can be a base class of owner) @@ -155,7 +169,7 @@ object ExplicitOuter { */ private def newOuterSym(owner: ClassSymbol, cls: ClassSymbol, name: TermName, flags: FlagSet)(implicit ctx: Context) = { val outerThis = owner.owner.enclosingClass.thisType - val outerCls = cls.owner.enclosingClass + val outerCls = outerClass(cls) val target = if (owner == cls) outerCls.appliedRef @@ -340,7 +354,7 @@ object ExplicitOuter { if (hasOuterParam(cls)) { val mt @ MethodTpe(pnames, ptypes, restpe) = tp mt.derivedLambdaType( - nme.OUTER :: pnames, cls.owner.enclosingClass.typeRef :: ptypes, restpe) + nme.OUTER :: pnames, outerClass(cls).typeRef :: ptypes, restpe) } else tp /** If function in an apply node is a constructor that needs to be passed an