Skip to content

Commit b105108

Browse files
wip
1 parent 9b4552b commit b105108

File tree

8 files changed

+112
-136
lines changed

8 files changed

+112
-136
lines changed

compiler/src/dotty/tools/dotc/core/Normalize.scala

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,10 @@ private final class NormalizeMap(implicit ctx: Context) extends TypeMap {
259259
case Left(cond1) => Stuck( TypeOf.If.derived(tp)(cond1, thenb, elseb) )
260260
}
261261

262-
case tp @ TypeOf.Match(selector, cases) =>
263-
new PatternMatcher.Translator(NoType, null)(ctx.enterTypeOf())
264-
.evaluateMatch(tp.tree.asInstanceOf[Match], normalizeBoolType).getOrElse(Stuck(tp))
262+
// case tp @ TypeOf.Match(_, _) =>
263+
// apply(tp.translated)
264+
// new PatternMatcher.Translator(NoType, null)(ctx.enterTypeOf())
265+
// .evaluateMatch(tp.tree.asInstanceOf[Match], normalizeBoolType).getOrElse(Stuck(tp))
265266

266267
case tp =>
267268
mapOver(tp) match {

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 42 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -4186,7 +4186,7 @@ object Types {
41864186
// ----- TypeOf -------------------------------------------------------------------------
41874187

41884188
/** Type that represents the precise type of a given term.
4189-
* Precision is only kept for Apply, TypeApply, If and Match trees.
4189+
* Precision is only kept for Apply, TypeApply and If trees.
41904190
*
41914191
* The idea behind this type is to be able to compute more precise types
41924192
* when more information is available.
@@ -4200,7 +4200,6 @@ object Types {
42004200
* TypeOf(u, Apply(fun, args)) ~ SuspendedApply(u, fun, args)
42014201
* TypeOf(u, TypeApply(fun, args)) ~ SuspendedTypeApply(u, fun, args)
42024202
* TypeOf(u, If(cond, thenp, elsep)) ~ SuspendedIf(u, cond, thenp, elsep)
4203-
* TypeOf(u, Match(selector, cases)) ~ SuspendedMatch(u, selector, cases)
42044203
*
42054204
* Where u is the type that the tree would have had otherwise.
42064205
*
@@ -4229,16 +4228,13 @@ object Types {
42294228
}
42304229
case nil => args2.isEmpty
42314230
}
4232-
// FIXME: compareArgs is incorrect for Match. Add compareCaseDef.
42334231
(this.tree, that.tree) match {
42344232
case (t1: Apply, t2: Apply) =>
42354233
(t1.fun.tpe eql t2.fun.tpe) && compareArgs(t1.args, t2.args)
42364234
case (t1: TypeApply, t2: TypeApply) =>
42374235
(t1.fun.tpe eql t2.fun.tpe) && compareArgs(t1.args, t2.args)
42384236
case (t1: If, t2: If) =>
42394237
(t1.cond.tpe eql t2.cond.tpe) && (t1.thenp.tpe eql t2.thenp.tpe) && (t1.elsep.tpe eql t2.elsep.tpe)
4240-
case (t1: Match, t2: Match) =>
4241-
(t1.selector.tpe eql t2.selector.tpe) && compareArgs(t1.cases, t2.cases)
42424238
case (t1, t2) =>
42434239
false
42444240
}
@@ -4251,7 +4247,6 @@ object Types {
42514247
override def computeHash(bs: Hashable.Binders) = {
42524248
val delta = tree match {
42534249
case _: If => 11
4254-
case _: Match => 17
42554250
case _: Apply => 23
42564251
case _: TypeApply => 29
42574252
}
@@ -4269,6 +4264,7 @@ object Types {
42694264

42704265
def apply(underlyingTp: Type, tree: untpd.Tree)(implicit ctx: Context): TypeOf = {
42714266
assert(!ctx.erasedTypes)
4267+
assert(isLegalTopLevelTree(tree.asInstanceOf[Tree]))
42724268
val tree1 = tree.clone.asInstanceOf[Tree]
42734269
// This is a safety net to keep us from touching a TypeOf's tree's type.
42744270
// Assuming we never look at this type, it would be safe to simply reuse
@@ -4282,7 +4278,7 @@ object Types {
42824278
def unapply(to: TypeOf): Option[(Type, Tree)] = Some((to.underlyingTp, to.tree))
42834279

42844280
def isLegalTopLevelTree(tree: Tree): Boolean = tree match {
4285-
case _: TypeApply | _: Apply | _: If | _: Match => true
4281+
case _: TypeApply | _: Apply | _: If => true
42864282
case _ => false
42874283
}
42884284

@@ -4324,6 +4320,16 @@ object Types {
43244320
tp
43254321

43264322
object If {
4323+
/** For explicit creation in patmat */
4324+
def apply(condTp: Type, thenTp: Type, elseTp: Type)(implicit ctx: Context): TypeOf = {
4325+
val thenTree = dummyTreeOfType(thenTp)
4326+
val elseTree = dummyTreeOfType(elseTp)
4327+
val ifTree = untpd.If(dummyTreeOfType(condTp), thenTree, elseTree)
4328+
ctx.typeAssigner.assignType(ifTree, thenTree, elseTree)(ctx.enterTypeOf()).tpe
4329+
.asInstanceOf[TypeOf]
4330+
}
4331+
4332+
/** For unpickling */
43274333
def apply(underlyingTp: Type, condTp: Type, thenTp: Type, elseTp: Type)(implicit ctx: Context): TypeOf =
43284334
TypeOf(underlyingTp, untpd.If(
43294335
dummyTreeOfType(condTp),
@@ -4348,32 +4354,35 @@ object Types {
43484354
}
43494355

43504356
object Match {
4351-
def apply(underlyingTp: Type, selectorTp: Type,
4352-
caseTriples: List[(Type, Type, Type)])(implicit ctx: Context): TypeOf =
4353-
TypeOf(underlyingTp, untpd.Match(
4354-
dummyTreeOfType(selectorTp),
4355-
caseTriples.map { case (patTp, guardTp, bodyTp) =>
4356-
ast.tpd.CaseDef(
4357-
dummyTreeOfType(patTp),
4358-
if (guardTp.exists) dummyTreeOfType(guardTp) else EmptyTree,
4359-
dummyTreeOfType(bodyTp))
4360-
}
4361-
))
4362-
4363-
def unapply(to: TypeOf): Option[(Type, List[(Type, Type, Type)])] = to.tree match {
4364-
case Trees.Match(selector, cases) =>
4365-
val caseTriples = cases.map { cse => (cse.pat.tpe, cse.guard.tpe, cse.body.tpe) }
4366-
Some((selector.tpe, caseTriples))
4367-
case _ => None
4368-
}
4369-
4370-
def derived(to: TypeOf)(selectorTp: Type, caseTriples: List[(Type, Type, Type)])(implicit ctx: Context): Type =
4371-
finalizeDerived(to, to.tree match {
4372-
case Trees.Match(selector, cases) =>
4373-
val ctx1 = ctx.enterTypeOf()
4374-
val cases1 = casesWithTpes(cases, caseTriples)(ctx1)
4375-
cpy.Match(to.tree)(treeWithTpe(selector, selectorTp), cases1)(ctx1)
4376-
})
4357+
def apply(underlyingTp: Type, tree: Match)(implicit ctx: Context): Type =
4358+
new transform.PatternMatcher.Translator(NoType, null)(ctx.enterTypeOf())
4359+
.typeTranslateMatch(tree)
4360+
// def apply(underlyingTp: Type, selectorTp: Type,
4361+
// caseTriples: List[(Type, Type, Type)])(implicit ctx: Context): TypeOf =
4362+
// TypeOf(underlyingTp, untpd.Match(
4363+
// dummyTreeOfType(selectorTp),
4364+
// caseTriples.map { case (patTp, guardTp, bodyTp) =>
4365+
// ast.tpd.CaseDef(
4366+
// dummyTreeOfType(patTp),
4367+
// if (guardTp.exists) dummyTreeOfType(guardTp) else EmptyTree,
4368+
// dummyTreeOfType(bodyTp))
4369+
// }
4370+
// ))
4371+
4372+
// def unapply(to: TypeOf): Option[(Type, List[(Type, Type, Type)])] = to.tree match {
4373+
// case Trees.Match(selector, cases) =>
4374+
// val caseTriples = cases.map { cse => (cse.pat.tpe, cse.guard.tpe, cse.body.tpe) }
4375+
// Some((selector.tpe, caseTriples))
4376+
// case _ => None
4377+
// }
4378+
4379+
// def derived(to: TypeOf)(selectorTp: Type, caseTriples: List[(Type, Type, Type)])(implicit ctx: Context): Type =
4380+
// finalizeDerived(to, to.tree match {
4381+
// case Trees.Match(selector, cases) =>
4382+
// val ctx1 = ctx.enterTypeOf()
4383+
// val cases1 = casesWithTpes(cases, caseTriples)(ctx1)
4384+
// cpy.Match(to.tree)(treeWithTpe(selector, selectorTp), cases1)(ctx1)
4385+
// })
43774386
}
43784387

43794388
object Apply {
@@ -4492,9 +4501,6 @@ object Types {
44924501
object Generic {
44934502
def unapply(to: TypeOf): Option[List[Type]] = to.tree match {
44944503
case Trees.If(cond, thenb, elseb) => Some(cond.tpe :: thenb.tpe :: elseb.tpe :: Nil)
4495-
case Trees.Match(selector, cases) =>
4496-
val caseTriplesFlattened = cases.flatMap { cse => List(cse.pat.tpe, cse.guard.tpe, cse.body.tpe) }
4497-
Some(selector.tpe :: caseTriplesFlattened)
44984504
case Trees.Apply(fn, args) => Some(fn.tpe :: args.map(_.tpe))
44994505
case Trees.TypeApply(fn, args) => Some(fn.tpe :: args.map(_.tpe))
45004506
}
@@ -4661,9 +4667,6 @@ object Types {
46614667
TypeOf.Apply.derived(tp)(this(tree.fun.tpe), tree.args.map(t => this(t.tpe)))
46624668
case tree: If =>
46634669
TypeOf.If.derived(tp)(this(tree.cond.tpe), this(tree.thenp.tpe), this(tree.elsep.tpe))
4664-
case tree: Match =>
4665-
val caseTriples = tree.cases.map { cse => (this(cse.pat.tpe), this(cse.guard.tpe), this(cse.body.tpe)) }
4666-
TypeOf.Match.derived(tp)(this(tree.selector.tpe), caseTriples)
46674670
case tree =>
46684671
throw new AssertionError(s"TypeOf shouldn't contain $tree as top-level node.")
46694672
}

compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -161,19 +161,12 @@ class TreePickler(pickler: TastyPickler) {
161161
withLength {
162162
val treeKind = to.tree match {
163163
case _: If => TypeOfTags.If
164-
case _: Match => TypeOfTags.Match
165164
case _: Apply => TypeOfTags.Apply
166165
case _: TypeApply => TypeOfTags.TypeApply
167166
}
168167
writeByte(treeKind)
169168
pickleType(to.underlying, richTypes = true)
170169
to match {
171-
case TypeOf.Match(selectorTp, caseTriples) =>
172-
pickleType(selectorTp, richTypes = true)
173-
caseTriples.foreach {
174-
case (patTp, NoType, bodyTp) => writeByte(2); pickleTypes(patTp :: bodyTp :: Nil)
175-
case (patTp, guardTp, bodyTp) => writeByte(3); pickleTypes(patTp :: guardTp :: bodyTp :: Nil)
176-
}
177170
case TypeOf.Generic(types) =>
178171
pickleTypes(types)
179172
}

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -298,26 +298,15 @@ class TreeUnpickler(reader: TastyReader,
298298
val treeKind = readByte()
299299
val underlying = readType()
300300
val TT = TypeOfTags
301-
if (treeKind == TT.Match) {
302-
val selectorTp = readType()
303-
val caseTriples = until(end) {
304-
readByte() match {
305-
case 2 => (readType(), NoType, readType())
306-
case 3 => (readType(), readType(), readType())
307-
}
308-
}
309-
TypeOf.Match(underlying, selectorTp, caseTriples)
310-
} else {
311-
val types = until(end)(readType())
312-
(treeKind, types) match {
313-
case (TT.If, List(cond, thenb, elseb)) =>
314-
TypeOf.If(underlying, cond, thenb, elseb)
315-
case (TT.Apply, fn :: args) =>
316-
TypeOf.Apply(underlying, fn, args)
317-
case (TT.TypeApply, fn :: args) =>
318-
TypeOf.TypeApply(underlying, fn, args)
319-
case _ => throw new AssertionError(s"Inconsistant types in TypeOf: $types")
320-
}
301+
val types = until(end)(readType())
302+
(treeKind, types) match {
303+
case (TT.If, List(cond, thenb, elseb)) =>
304+
TypeOf.If(underlying, cond, thenb, elseb)
305+
case (TT.Apply, fn :: args) =>
306+
TypeOf.Apply(underlying, fn, args)
307+
case (TT.TypeApply, fn :: args) =>
308+
TypeOf.TypeApply(underlying, fn, args)
309+
case _ => throw new AssertionError(s"Inconsistant types in TypeOf: $types")
321310
}
322311
}
323312

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

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ object PatternMatcher {
262262
/** Plan for matching the sequence in `getResult` against sequence elements
263263
* and a possible last varargs argument `args`.
264264
*/
265-
def unapplySeqPlan(getResult: Symbol, args: List[Tree]): Plan = args.lastOption match {
265+
def unapplySeqPlan(getResult: Symbol, args: List[Tree]): Plan = args.lastOption match { //XXXX
266266
case Some(VarArgPattern(arg)) =>
267267
val matchRemaining =
268268
if (args.length == 1) {
@@ -326,7 +326,7 @@ object PatternMatcher {
326326
}
327327

328328
// begin patternPlan
329-
swapBind(tree) match {
329+
swapBind(tree) match { //XXXX
330330
case Typed(pat, tpt) =>
331331
TestPlan(TypeTest(tpt), scrutinee, tree.pos,
332332
letAbstract(ref(scrutinee).asInstance(tpt.tpe)) { casted =>
@@ -510,7 +510,7 @@ object PatternMatcher {
510510
def mergeTests(plan: Plan): Plan = {
511511
class SubstituteIdent(from: TermSymbol, to: TermSymbol) extends PlanTransform {
512512
override val treeMap = new TreeMap {
513-
override def transform(tree: Tree)(implicit ctx: Context) = tree match {
513+
override def transform(tree: Tree)(implicit ctx: Context) = tree match { //XXXX
514514
case tree: Ident if tree.symbol == from => ref(to)
515515
case _ => super.transform(tree)
516516
}
@@ -593,7 +593,7 @@ object PatternMatcher {
593593

594594
object Inliner extends PlanTransform {
595595
override val treeMap = new TreeMap {
596-
override def transform(tree: Tree)(implicit ctx: Context) = tree match {
596+
override def transform(tree: Tree)(implicit ctx: Context) = tree match { //XXXX
597597
case tree: Ident =>
598598
val sym = tree.symbol
599599
if (toDrop(sym)) transform(initializer(sym))
@@ -693,8 +693,8 @@ object PatternMatcher {
693693

694694
@tailrec
695695
private def canFallThrough(plan: Plan): Boolean = plan match {
696-
case _:ReturnPlan | _:ResultPlan => false
697-
case _:TestPlan | _:LabeledPlan => true
696+
case _: ReturnPlan | _: ResultPlan => false
697+
case _: TestPlan | _: LabeledPlan => true
698698
case LetPlan(_, body) => canFallThrough(body)
699699
case SeqPlan(_, tail) => canFallThrough(tail)
700700
}
@@ -710,7 +710,7 @@ object PatternMatcher {
710710
(tpe isRef defn.ShortClass) ||
711711
(tpe isRef defn.CharClass)
712712

713-
def isIntConst(tree: Tree) = tree match {
713+
def isIntConst(tree: Tree) = tree match { ///XXXX
714714
case Literal(const) => const.isIntRange
715715
case _ => false
716716
}
@@ -944,17 +944,21 @@ object PatternMatcher {
944944
Labeled(resultLabel, result)
945945
}
946946

947-
948947
/** Evaluate pattern match to a precise type, if possible, and return NoType otherwise. */
949-
def evaluateMatch(tree: Match, evalBoolType: Type => Either[Type, Boolean]): Option[Type] = {
950-
val plan = matchPlan(tree)
951-
patmatch.println(i"Plan for $tree: ${show(plan)}")
952-
val result = evaluate(plan, evalBoolType)
953-
patmatch.println(i"Plan evaluation: $result")
954-
result
955-
}
956-
957-
private def evaluate(plan0: Plan, evalBoolType: Type => Either[Type, Boolean]): Option[Type] = {
948+
// def evaluateMatch(tree: Match, evalBoolType: Type => Either[Type, Boolean]): Option[Type] = {
949+
// val plan = matchPlan(tree)
950+
// println
951+
// println
952+
// patmatch.println(i"Plan for $tree: ${show(plan)}")
953+
// val result = evaluate(plan, evalBoolType)
954+
// /*patmatch.*/println(i"Plan evaluation: $result")
955+
// result
956+
// }
957+
958+
def typeTranslateMatch(tree: Match): Type =
959+
typeTranslatePlan(matchPlan(tree))
960+
961+
private def typeTranslatePlan(plan0: Plan): Type = {
958962
assert(ctx.isDependent)
959963

960964
def nextPlan(label: Symbol): Plan = {
@@ -970,32 +974,40 @@ object PatternMatcher {
970974
rec(label, plan0, None).get
971975
}
972976

973-
def evalTest(testPlan: TestPlan): Option[Boolean] = testPlan match {
974-
case TestPlan(test, scrut, _, _) =>
977+
def evalTest(testPlan: TestPlan): Type = testPlan match {
978+
case TestPlan(test, scrutinee, _, _) =>
975979
test match {
976-
case TypeTest(tpt) => Normalize.erasedTypeTest(scrut.tpe, tpt.tpe) // FIXME: unsound
977-
case NonNullTest => Some(false)
978-
case _ => evalBoolType(emitCondition(testPlan).tpe).toOption
980+
case TypeTest(tpt) =>
981+
// Like emitCondition(test) with the crazy outer stuff and
982+
// patmet specific isInstanceOfPM gone.
983+
val expectedTp = tpt.tpe
984+
expectedTp.dealias match {
985+
case expectedTp: SingletonType =>
986+
scrutinee.isInstance(expectedTp).tpe
987+
case _ =>
988+
scrutinee.select(defn.Any_isInstanceOf).appliedToType(expectedTp).tpe
989+
}
990+
case NonNullTest => ConstantType(Constants.Constant(false))
991+
case _ => emitCondition(testPlan).tpe
979992
}
980993
}
981994

982-
@tailrec def evalPlan(plan: Plan, nexts: List[Plan]): Option[Type] =
995+
def evalPlan(plan: Plan, nexts: List[Plan]): Type =
983996
plan match {
984997
case LetPlan(sym, body) => evalPlan(body, nexts)
985998
case LabeledPlan(label, expr) => evalPlan(expr, nexts)
986999
case SeqPlan(head, tail) => evalPlan(head, tail :: nexts)
9871000
case ReturnPlan(label) => evalPlan(nextPlan(label), nexts)
988-
case ResultPlan(tree) => Some(tree.tpe)
1001+
case ResultPlan(tree) => tree.tpe
9891002
case plan: TestPlan =>
990-
evalTest(plan) match {
991-
case None => None
992-
case Some(true) => evalPlan(plan.onSuccess, nexts)
993-
case Some(false) =>
994-
nexts match {
995-
case head :: tail => evalPlan(head, tail)
996-
case _ => throw new AssertionError("Malformed Plan")
997-
}
998-
}
1003+
val condTp = evalTest(plan)
1004+
val thenTp = evalPlan(plan.onSuccess, nexts)
1005+
val elseTp =
1006+
nexts match {
1007+
case head :: tail => evalPlan(head, tail)
1008+
case _ => throw new AssertionError("Malformed Plan")
1009+
}
1010+
TypeOf.If(condTp, thenTp, elseTp)
9991011
}
10001012

10011013
evalPlan(plan0, Nil)

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,12 +499,13 @@ trait TypeAssigner {
499499
tree.withType(ownType)
500500
}
501501

502-
def assignType(tree: untpd.Match, scrutinee: Tree, cases: List[CaseDef])(implicit ctx: Context) = {
502+
def assignType(tree: untpd.Match, scrutinee: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = {
503503
val underlying = ctx.typeComparer.lub(cases.tpes)
504+
val typed = tree.withType(underlying)
504505
if (!ctx.erasedTypes && ctx.isDependent)
505-
tree.withType(TypeOf(underlying, tree))
506+
tree.clone.withType(TypeOf.Match(underlying, typed))
506507
else
507-
tree.withType(underlying)
508+
typed
508509
}
509510

510511
def assignType(tree: untpd.Labeled)(implicit ctx: Context) =

0 commit comments

Comments
 (0)