Skip to content

Commit d68c106

Browse files
committed
Enable outer tests in pattern matcher.
And a test for this.
1 parent 5f04610 commit d68c106

File tree

3 files changed

+30
-8
lines changed

3 files changed

+30
-8
lines changed

src/dotty/tools/dotc/transform/ExplicitOuter.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import core.Names._
1313
import core.NameOps._
1414
import ast.Trees._
1515
import SymUtils._
16+
import dotty.tools.dotc.core.Phases.Phase
1617
import util.Attachment
1718
import collection.mutable
1819

@@ -27,6 +28,8 @@ import collection.mutable
2728
* - add outer parameters to constructors
2829
* - pass outer arguments in constructor calls
2930
* - replace outer this by outer paths.
31+
*
32+
* needs to run after pattern matcher as it can add outer checks and force creation of $outer
3033
*/
3134
class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransformer =>
3235
import ExplicitOuter._
@@ -36,6 +39,10 @@ class ExplicitOuter extends MiniPhaseTransform with InfoTransformer { thisTransf
3639

3740
override def phaseName: String = "explicitOuter"
3841

42+
/** List of names of phases that should have finished their processing of all compilation units
43+
* before this phase starts
44+
*/
45+
override def runsAfter: Set[Class[_ <: Phase]] = Set(classOf[PatternMatcher])
3946
override def treeTransformPhase = thisTransformer.next
4047

4148
/** Add outer accessors if a class always needs an outer pointer */
@@ -171,7 +178,7 @@ object ExplicitOuter {
171178
* result is phase dependent. In that case we use a backup strategy where we search all
172179
* definitions in the class to find the one with the OuterAccessor flag.
173180
*/
174-
private def outerAccessor(cls: ClassSymbol)(implicit ctx: Context): Symbol =
181+
def outerAccessor(cls: ClassSymbol)(implicit ctx: Context): Symbol =
175182
cls.info.member(outerAccName(cls)).suchThat(_ is OuterAccessor).symbol orElse
176183
cls.info.decls.find(_ is OuterAccessor).getOrElse(NoSymbol)
177184

src/dotty/tools/dotc/transform/PatternMatcher.scala

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -666,14 +666,16 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
666666
val expectedOuter = expectedTp.normalizedPrefix match {
667667
//case ThisType(clazz) => This(clazz)
668668
//case NoType => Literal(Constant(true)) // fallback for SI-6183 todo?
669-
case pre => ref(pre.typeSymbol)
669+
case pre => ref(pre.termSymbol)
670670
}
671671

672672
// ExplicitOuter replaces `Select(q, outerSym) OBJ_EQ expectedPrefix` by `Select(q, outerAccessor(outerSym.owner)) OBJ_EQ expectedPrefix`
673673
// if there's an outer accessor, otherwise the condition becomes `true` -- TODO: can we improve needsOuterTest so there's always an outerAccessor?
674674
// val outer = expectedTp.typeSymbol.newMethod(vpmName.outer, newFlags = SYNTHETIC | ARTIFACT) setInfo expectedTp.prefix
675675

676-
codegen._asInstanceOf(testedBinder, expectedTp).select("<outer>".toTermName).select(ctx.definitions.Object_eq).appliedTo(expectedOuter)
676+
val expectedClass = expectedTp.dealias.classSymbol.asClass
677+
ExplicitOuter.ensureOuterAccessors(expectedClass)
678+
codegen._asInstanceOf(testedBinder, expectedTp).select(ExplicitOuter.outerAccessor(expectedClass)).select(ctx.definitions.Object_eq).appliedTo(expectedOuter)
677679
}
678680
}
679681

@@ -750,11 +752,12 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
750752

751753
override lazy val localSubstitution: Substitution = EmptySubstitution
752754

753-
lazy val outerTestNeeded = (
754-
(expectedTp.normalizedPrefix.typeSymbol ne NoSymbol)
755-
&& !expectedTp.normalizedPrefix.typeSymbol.isPackageObject
756-
&& false &&needsOuterTest(expectedTp, testedBinder.info, matchOwner)
757-
)
755+
def outerTestNeeded = {
756+
val np = expectedTp.normalizedPrefix
757+
val ts = np.termSymbol
758+
(ts ne NoSymbol) && needsOuterTest(expectedTp, testedBinder.info, matchOwner)
759+
760+
}
758761

759762
// the logic to generate the run-time test that follows from the fact that
760763
// a `prevBinder` is expected to have type `expectedTp`

tests/pos/Patterns.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,16 @@ object Patterns {
7777
}
7878
case _ => ys.isEmpty
7979
}
80+
81+
class A{
82+
class B
83+
}
84+
val a1 = new A
85+
val a2 = new A
86+
d match {
87+
case t: a1.B =>
88+
t
89+
case t: a2.B =>
90+
t
91+
}
8092
}

0 commit comments

Comments
 (0)