From 71c90ff30de819c90dddae87a0154e9192981635 Mon Sep 17 00:00:00 2001 From: odersky Date: Wed, 14 Dec 2022 18:32:16 +0100 Subject: [PATCH] Dealias before checking for outer references in types Fixes #15827 --- .../tools/dotc/transform/ExplicitOuter.scala | 10 ++-- .../test/dotc/pos-test-pickling.blacklist | 1 + tests/pos/i15827.scala | 55 +++++++++++++++++++ 3 files changed, 61 insertions(+), 5 deletions(-) create mode 100644 tests/pos/i15827.scala diff --git a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala index c1536022a2ac..cddfe51275c8 100644 --- a/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala +++ b/compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala @@ -256,7 +256,6 @@ object ExplicitOuter { */ def referencesOuter(cls: Symbol, tree: Tree)(using Context): Boolean = - val test = new TreeAccumulator[Boolean]: private var inInline = false @@ -302,19 +301,20 @@ object ExplicitOuter { def containsOuterRefs(t: Tree): Boolean = t match case _: This | _: Ident => isOuterRef(t.tpe) case nw: New => - val newCls = nw.tpe.classSymbol + val newType = nw.tpe.dealias + val newCls = newType.classSymbol isOuterSym(newCls.owner.enclosingClass) || - hasOuterPrefix(nw.tpe) || + hasOuterPrefix(newType) || newCls.owner.isTerm && cls.isProperlyContainedIn(newCls) // newCls might get proxies for free variables. If current class is // properly contained in newCls, it needs an outer path to newCls access the // proxies and forward them to the new instance. case app: TypeApply if app.symbol.isTypeTest => // Type tests of singletons translate to `eq` tests with references, which might require outer pointers - containsOuterRefsAtTopLevel(app.args.head.tpe) + containsOuterRefsAtTopLevel(app.args.head.tpe.dealias) case t: TypeTree if inInline => // Expansions of inline methods must be able to address outer types - containsOuterRefsAnywhere(t.tpe) + containsOuterRefsAnywhere(t.tpe.dealias) case _ => false diff --git a/compiler/test/dotc/pos-test-pickling.blacklist b/compiler/test/dotc/pos-test-pickling.blacklist index 30126f07b49a..cdbad2160f2a 100644 --- a/compiler/test/dotc/pos-test-pickling.blacklist +++ b/compiler/test/dotc/pos-test-pickling.blacklist @@ -45,6 +45,7 @@ i9999.scala i6505.scala i15158.scala i15155.scala +i15827.scala # Opaque type i5720.scala diff --git a/tests/pos/i15827.scala b/tests/pos/i15827.scala new file mode 100644 index 000000000000..b3624dc4f296 --- /dev/null +++ b/tests/pos/i15827.scala @@ -0,0 +1,55 @@ + +trait Mirr { + type MirroredTp + type Elems <: Tuple +} +trait MirrP extends Mirr { + def fromProduct(x: Product): MirroredTp +} +trait MirrS extends Mirr + +def outer3Local = { + class Wrapper { + object Nested { + sealed trait Color + } + } + val wrapper = new Wrapper + import wrapper.Nested.Color + + object Inner { + case object Red extends Color + case object Green extends Color + case object Blue extends Color + case class Rgb(hex: Int) extends Color + case object Rgb + } + + object CallSite { + def run = + import Inner.* + val M: (MirrS { type MirroredTp = Color; type Elems = (Inner.Red.type, Inner.Green.type, Inner.Blue.type, Inner.Rgb) }) = + new MirrS { + type MirroredTp = Color + type Elems = (Inner.Red.type, Inner.Green.type, Inner.Blue.type, Inner.Rgb) + } + + val M_Rgb = + type TRgb = Tuple.Elem[M.Elems, 3] + new MirrP { + type MirroredTp = TRgb + type Elems = Int *: EmptyTuple + + def fromProduct(x: Product): MirroredTp = + new TRgb(x.productElement(0).asInstanceOf[Int]) + }: (MirrP { + type MirroredTp = TRgb + type Elems = Int *: EmptyTuple + }) + } + + CallSite.run +} + +@main def Test = + outer3Local