Skip to content

Commit f55959c

Browse files
committed
Test outer pointer in pattern matches
1 parent e8eb6d9 commit f55959c

File tree

5 files changed

+48
-6
lines changed

5 files changed

+48
-6
lines changed

compiler/src/dotty/tools/dotc/ast/tpd.scala

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import Denotations._, Decorators._, DenotTransformers._
1212
import collection.mutable
1313
import util.{Property, SourceFile, NoSource}
1414
import typer.ErrorReporting._
15-
import NameKinds.TempResultName
15+
import NameKinds.{TempResultName, OuterSelectName}
1616

1717
import scala.annotation.tailrec
1818
import scala.io.Codec
@@ -811,6 +811,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
811811
}
812812
else Assign(tree, rhs)
813813

814+
/** A synthetic select with that will be turned into an outer path by ExplicitOuter.
815+
* @param levels How many outer levels to select
816+
* @param tp The type of the destination of the outer path.
817+
*/
818+
def outerSelect(levels: Int, tp: Type)(implicit ctx: Context): Tree =
819+
untpd.Select(tree, OuterSelectName(EmptyTermName, levels)).withType(tp)
820+
814821
// --- Higher order traversal methods -------------------------------
815822

816823
/** Apply `f` to each subtree of this tree */

compiler/src/dotty/tools/dotc/transform/PatMat.scala

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ object PatMat {
2222

2323
abstract class Node
2424

25-
class Translator(implicit ctx: Context) {
25+
class Translator(resultType: Type, trans: TreeTransform)(implicit ctx: Context, info: TransformerInfo) {
2626

2727
def patmatGenerated(sym: Symbol) =
2828
sym.is(Synthetic) &&
@@ -100,7 +100,42 @@ object PatMat {
100100

101101
class TypeTest(scrut: Symbol, tpt: Tree, ons: Node, onf: Node) extends Test(scrut, ons, onf) {
102102
def pos = tpt.pos
103-
def condition = scrutinee.select(defn.Any_typeTest).appliedToType(tpt.tpe)
103+
private val expectedTp = tpt.tpe
104+
105+
private def outerTestNeeded(implicit ctx: Context): Boolean = {
106+
// See the test for SI-7214 for motivation for dealias. Later `treeCondStrategy#outerTest`
107+
// generates an outer test based on `patType.prefix` with automatically dealises.
108+
expectedTp.dealias match {
109+
case tref @ TypeRef(pre: SingletonType, name) =>
110+
tref.symbol.isClass &&
111+
ExplicitOuter.needsOuterIfReferenced(tref.symbol.asClass)
112+
case _ =>
113+
false
114+
}
115+
}
116+
117+
private def outerTest: Tree = trans.transformFollowingDeep {
118+
val expectedOuter = singleton(expectedTp.normalizedPrefix)
119+
val expectedClass = expectedTp.dealias.classSymbol.asClass
120+
ExplicitOuter.ensureOuterAccessors(expectedClass)(ctx.withPhase(ctx.explicitOuterPhase.next))
121+
scrutinee.ensureConforms(expectedTp)
122+
.outerSelect(1, expectedOuter.tpe.widen)
123+
.select(defn.Object_eq)
124+
.appliedTo(expectedOuter)
125+
}
126+
127+
def condition = expectedTp.dealias match {
128+
case expectedTp: SingletonType =>
129+
val test =
130+
if (expectedTp.widen.derivesFrom(defn.ObjectClass))
131+
scrutinee.ensureConforms(defn.ObjectType).select(defn.Object_eq)
132+
else
133+
scrutinee.select(defn.Any_==)
134+
test.appliedTo(singleton(expectedTp))
135+
case _ =>
136+
val typeTest = scrutinee.select(defn.Any_typeTest).appliedToType(tpt.tpe)
137+
if (outerTestNeeded) typeTest.and(outerTest) else typeTest
138+
}
104139
override def toString = i"TypeTest($scrutinee: $tpt)"
105140
}
106141

@@ -450,7 +485,7 @@ class PatMat extends MiniPhaseTransform {
450485
override def runsAfterGroupsOf = Set(classOf[TailRec]) // tailrec is not capable of reversing the patmat tranformation made for tree
451486

452487
override def transformMatch(tree: Match)(implicit ctx: Context, info: TransformerInfo): Tree = {
453-
val translated = new Translator()(ctx).translateMatch(tree)
488+
val translated = new Translator(tree.tpe, this).translateMatch(tree)
454489

455490
// check exhaustivity and unreachability
456491
val engine = new patmat.SpaceEngine

compiler/src/dotty/tools/dotc/typer/Inliner.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import StdNames.nme
1515
import Contexts.Context
1616
import Names.{Name, TermName, EmptyTermName}
1717
import NameOps._
18-
import NameKinds.{InlineAccessorName, OuterSelectName}
18+
import NameKinds.InlineAccessorName
1919
import SymDenotations.SymDenotation
2020
import Annotations._
2121
import transform.ExplicitOuter
@@ -412,7 +412,7 @@ class Inliner(call: tpd.Tree, rhs: tpd.Tree)(implicit ctx: Context) {
412412
lazy val rhsClsSym = selfSym.info.widenDealias.classSymbol
413413
val rhs =
414414
if (lastSelf.exists)
415-
untpd.Select(ref(lastSelf), OuterSelectName(EmptyTermName, lastLevel - level)).withType(selfSym.info)
415+
ref(lastSelf).outerSelect(lastLevel - level, selfSym.info)
416416
else if (rhsClsSym.is(Module))
417417
ref(rhsClsSym.sourceModule)
418418
else
File renamed without changes.
File renamed without changes.

0 commit comments

Comments
 (0)