Skip to content

Commit

Permalink
Lub MatchTypeTree case body types and store as the inferred bound
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed Feb 26, 2024
1 parent 8f2b6cf commit c25edde
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 13 deletions.
13 changes: 1 addition & 12 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1030,17 +1030,6 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
if tp1 ne tp1norm then recur(tp1norm, tp2)
else either(recur(tp11, tp2), recur(tp12, tp2))
case tp1: MatchType =>
def compareUpper =
val lub1 = tp1.cases.foldLeft(defn.NothingType: Type): (acc, case1) =>
if acc.exists then
val rhs = case1.resultType match { case defn.MatchCase(_, body) => body }
val isRecursive = rhs.existsPart(_.isInstanceOf[LazyRef])
if isRecursive then NoType else lub(acc, rhs)
else acc
if lub1.exists then
recur(lub1, tp2)
else
recur(tp1.underlying, tp2)
def compareMatch = tp2 match {
case tp2: MatchType =>
// we allow a small number of scrutinee types to be widened:
Expand All @@ -1058,7 +1047,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
tp1.cases.corresponds(tp2.cases)(isSubType)
case _ => false
}
(!caseLambda.exists || canWidenAbstract) && compareUpper || compareMatch
(!caseLambda.exists || canWidenAbstract) && recur(tp1.underlying, tp2) || compareMatch
case tp1: AnnotatedType if tp1.isRefining =>
isNewSubType(tp1.parent)
case JavaArrayType(elem1) =>
Expand Down
10 changes: 9 additions & 1 deletion compiler/src/dotty/tools/dotc/typer/Typer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2373,7 +2373,15 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
report.error(MatchTypeScrutineeCannotBeHigherKinded(sel1Tpe), sel1.srcPos)
val pt1 = if (bound1.isEmpty) pt else bound1.tpe
val cases1 = tree.cases.mapconserve(typedTypeCase(_, sel1Tpe, pt1))
assignType(cpy.MatchTypeTree(tree)(bound1, sel1, cases1), bound1, sel1, cases1)
val bound2 = if tree.bound.isEmpty then
val lub = cases1.foldLeft(defn.NothingType: Type): (acc, case1) =>
if !acc.exists then NoType
else if case1.body.tpe.existsPart(_.isInstanceOf[LazyRef]) then NoType
else acc | TypeOps.avoid(case1.body.tpe, patVars(case1))
if lub.exists then TypeTree(lub, inferred = true)
else bound1
else bound1
assignType(cpy.MatchTypeTree(tree)(bound2, sel1, cases1), bound2, sel1, cases1)
}

def typedByNameTypeTree(tree: untpd.ByNameTypeTree)(using Context): ByNameTypeTree = tree.result match
Expand Down

0 comments on commit c25edde

Please sign in to comment.