Skip to content

Commit 8b79883

Browse files
committed
EqualityTestTreeMaker: fix incorrect type of symbol
given a pattern object b x match { case y @ b => <body> } y inside the <body> `y` should have type b.type. Inherited from scalac EqualityTestTreeMaker would reset type of it in order to achive this. Dotty instead needs to know this in advance.
1 parent ac583c5 commit 8b79883

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

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

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
287287
)
288288
} else {
289289
assert(defn.isProductSubType(prev.tpe))
290-
Substitution(b, ref(prevSym))(next)
290+
Block(
291+
List(ValDef(prevSym, prev)),
292+
Substitution(b, ref(prevSym))(next)
293+
)
291294
}
292295
}
293296

@@ -432,8 +435,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
432435
val cond: Tree
433436
val res: Tree
434437

435-
lazy val nextBinder = freshSym(pos, nextBinderTp)
436-
lazy val localSubstitution = Substitution(List(prevBinder), List(ref(nextBinder)))
438+
val nextBinder: Symbol
439+
lazy val localSubstitution =
440+
if(nextBinder ne prevBinder) Substitution(List(prevBinder), List(ref(nextBinder)))
441+
else EmptySubstitution
437442

438443
def chainBefore(next: Tree)(casegen: Casegen): Tree =
439444
/*atPos(pos)(*/casegen.flatMapCond(cond, res, nextBinder, substitution(next))//)
@@ -728,7 +733,7 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
728733

729734
val prevBinder = testedBinder
730735

731-
override lazy val nextBinder = afterTest.asTerm
736+
val nextBinder = afterTest.asTerm
732737

733738
def needsOuterTest(patType: Type, selType: Type, currentOwner: Symbol) = {
734739
// See the test for SI-7214 for motivation for dealias. Later `treeCondStrategy#outerTest`
@@ -823,13 +828,14 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
823828
}
824829

825830
// need to substitute to deal with existential types -- TODO: deal with existentials better, don't substitute (see RichClass during quick.comp)
826-
case class EqualityTestTreeMaker(prevBinder: Symbol, patTree: Tree, override val pos: Position) extends CondTreeMaker {
827-
val nextBinderTp = prevBinder.info.widen
831+
case class EqualityTestTreeMaker(prevBinder: Symbol, subpatBinder: Symbol, patTree: Tree, override val pos: Position) extends CondTreeMaker {
832+
val nextBinderTp = patTree.tpe & prevBinder.info
833+
val nextBinder = if (prevBinder eq subpatBinder) freshSym(pos, nextBinderTp) else subpatBinder
828834

829835
// NOTE: generate `patTree == patBinder`, since the extractor must be in control of the equals method (also, patBinder may be null)
830836
// equals need not be well-behaved, so don't intersect with pattern's (stabilized) type (unlike MaybeBoundTyped's accumType, where it's required)
831837
val cond = codegen._equals(patTree, prevBinder)
832-
val res = ref(prevBinder)
838+
val res = ref(prevBinder).ensureConforms(nextBinderTp)
833839
override def toString = "ET"+((prevBinder.name, patTree))
834840
}
835841

@@ -1020,18 +1026,33 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
10201026
}
10211027
}
10221028

1029+
object SymbolAndValueBound {
1030+
def unapply(tree: Tree): Option[(Symbol, Tree)] = tree match {
1031+
case SymbolBound(sym, ConstantPattern(const)) => Some(sym -> const)
1032+
case _ => None
1033+
}
1034+
}
1035+
10231036
object TypeBound {
10241037
def unapply(tree: Tree): Option[Type] = tree match {
10251038
case Typed(_, _) => Some(tree.typeOpt)
10261039
case _ => None
10271040
}
10281041
}
10291042

1043+
object ConstantPattern {
1044+
def unapply(tree: Tree): Option[Tree] = tree match {
1045+
case Literal(Constant(_)) | Ident(_) | Select(_, _) | This(_) => Some(tree)
1046+
case _ => None
1047+
}
1048+
}
1049+
10301050
private def rebindTo(pattern: Tree) = BoundTree(binder, pattern)
10311051
private def step(treeMakers: TreeMaker*)(subpatterns: BoundTree*): TranslationStep = TranslationStep(treeMakers.toList, subpatterns.toList)
10321052

10331053
private def bindingStep(sub: Symbol, subpattern: Tree) = step(SubstOnlyTreeMaker(sub, binder))(rebindTo(subpattern))
1034-
private def equalityTestStep() = step(EqualityTestTreeMaker(binder, tree, pos))()
1054+
private def equalityTestStep(testedSymbol: Symbol, constantSymbol: Symbol, constant: Tree)
1055+
= step(EqualityTestTreeMaker(testedSymbol, constantSymbol, constant, pos))()
10351056
private def typeTestStep(sub: Symbol, subPt: Type) = step(TypeTestTreeMaker(sub, binder, subPt, sub.termRef)(pos))()
10361057
private def alternativesStep(alts: List[Tree]) = step(AlternativesTreeMaker(binder, translatedAlts(alts), alts.head.pos))()
10371058
private def translatedAlts(alts: List[Tree]) = alts map (alt => rebindTo(alt).translate())
@@ -1083,9 +1104,10 @@ class PatternMatcher extends MiniPhaseTransform with DenotTransformer {thisTrans
10831104
case _: UnApply | _: Apply| Typed(_: UnApply | _: Apply, _) => extractorStep()
10841105
case SymbolAndTypeBound(sym, tpe) => typeTestStep(sym, tpe)
10851106
case TypeBound(tpe) => typeTestStep(binder, tpe)
1107+
case SymbolAndValueBound(sym, const) => equalityTestStep(binder, sym, const)
10861108
case SymbolBound(sym, expr) => bindingStep(sym, expr)
10871109
case WildcardPattern() => noStep()
1088-
case Literal(Constant(_)) | Ident(_) | Select(_, _) | This(_) => equalityTestStep()
1110+
case ConstantPattern(const) => equalityTestStep(binder, binder, const)
10891111
case Alternative(alts) => alternativesStep(alts)
10901112
case _ => ctx.error(unsupportedPatternMsg, pos) ; noStep()
10911113
}

0 commit comments

Comments
 (0)