Skip to content

Commit

Permalink
Revert "ErrorType instead of throwing in match type "no cases""
Browse files Browse the repository at this point in the history
This reverts commit 9ae1598

Note that the changes in Typer:
```
val unsimplifiedType = result.tpe
simplify(result, pt, locked)
result.tpe.stripTypeVar match
  case e: ErrorType if !unsimplifiedType.isErroneous =>
    errorTree(xtree, e.msg, xtree.srcPos)
  case _ => result
```
cannot be reverted yet since the MatchReducer now also reduces to an `ErrorType` for MatchTypeLegacyPatterns, introduced after 9ae1598.
  • Loading branch information
EugeneFlesselle committed Mar 17, 2024
1 parent c79c664 commit b2c544a
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 39 deletions.
19 changes: 3 additions & 16 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3595,22 +3595,9 @@ class MatchReducer(initctx: Context) extends TypeComparer(initctx) {
NoType
case Nil =>
val casesText = MatchTypeTrace.noMatchesText(scrut, cases)
ErrorType(reporting.MatchTypeNoCases(casesText))

inFrozenConstraint {
if scrut.isError then
// if the scrutinee is an error type
// then just return that as the result
// not doing so will result in the first type case matching
// because ErrorType (as a FlexType) is <:< any type case
// this situation can arise from any kind of nesting of match types,
// e.g. neg/i12049 `Tuple.Concat[Reverse[ts], (t2, t1)]`
// if Reverse[ts] fails with no matches,
// the error type should be the reduction of the Concat too
scrut
else
recur(cases)
}
throw MatchTypeReductionError(em"Match type reduction $casesText")

inFrozenConstraint(recur(cases))
}
}

Expand Down
3 changes: 3 additions & 0 deletions compiler/src/dotty/tools/dotc/core/TypeErrors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ object TypeError:
def toMessage(using Context) = msg
end TypeError

class MatchTypeReductionError(msg: Message)(using Context) extends TypeError:
def toMessage(using Context) = msg

class MalformedType(pre: Type, denot: Denotation, absMembers: Set[Name])(using Context) extends TypeError:
def toMessage(using Context) = em"malformed type: $pre is not a legal prefix for $denot because it contains abstract type member${if (absMembers.size == 1) "" else "s"} ${absMembers.mkString(", ")}"

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ trait ImplicitRunInfo:
traverseChildren(t)
case t =>
traverseChildren(t)
traverse(t.normalized)
traverse(try t.normalized catch case _: MatchTypeReductionError => t)
catch case ex: Throwable => handleRecursive("collectParts of", t.show, ex)

def apply(tp: Type): collection.Set[Type] =
Expand Down
49 changes: 45 additions & 4 deletions tests/neg-macros/toexproftuple.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
import scala.quoted._, scala.deriving.*
import scala.quoted._, scala.deriving.* // error
// ^
// Match type reduction failed since selector ((2 : Int), quoted.Expr[(3 : Int)])
// matches none of the cases
//
// case quoted.Expr[x] *: t => x *: scala.Tuple.InverseMap[t, quoted.Expr]
// case EmptyTuple => EmptyTuple

inline def mcr: Any = ${mcrImpl}
inline def mcr: Any = ${mcrImpl} // error
// ^
// Match type reduction failed since selector ((2 : Int), quoted.Expr[(3 : Int)])
// matches none of the cases
//
// case quoted.Expr[x] *: t => x *: scala.Tuple.InverseMap[t, quoted.Expr]
// case EmptyTuple => EmptyTuple

def mcrImpl(using ctx: Quotes): Expr[Any] = {
def mcrImpl(using ctx: Quotes): Expr[Any] = { // error // error
//^
// Match type reduction failed since selector ((2 : Int), quoted.Expr[(3 : Int)])
// matches none of the cases
//
// case quoted.Expr[x] *: t => x *: scala.Tuple.InverseMap[t, quoted.Expr]
// case EmptyTuple => EmptyTuple

// ^
// Match type reduction failed since selector ((2 : Int), quoted.Expr[(3 : Int)])
// matches none of the cases
//
// case quoted.Expr[x] *: t => x *: scala.Tuple.InverseMap[t, quoted.Expr]
// case EmptyTuple => EmptyTuple

val tpl: (Expr[1], Expr[2], Expr[3]) = ('{1}, '{2}, '{3})
'{val res: (1, 3, 3) = ${Expr.ofTuple(tpl)}; res} // error
Expand All @@ -11,12 +36,28 @@ def mcrImpl(using ctx: Quotes): Expr[Any] = {
// Required: quoted.Expr[((1 : Int), (3 : Int), (3 : Int))]

val tpl2: (Expr[1], 2, Expr[3]) = ('{1}, 2, '{3})
'{val res = ${Expr.ofTuple(tpl2)}; res} // error
'{val res = ${Expr.ofTuple(tpl2)}; res} // error // error // error // error
// ^
// Cannot prove that (quoted.Expr[(1 : Int)], (2 : Int), quoted.Expr[(3 : Int)]) =:= scala.Tuple.Map[
// scala.Tuple.InverseMap[
// (quoted.Expr[(1 : Int)], (2 : Int), quoted.Expr[(3 : Int)])
// , quoted.Expr]
// , quoted.Expr].

// ^
// Match type reduction failed since selector ((2 : Int), quoted.Expr[(3 : Int)])
// matches none of the cases
//
// case quoted.Expr[x] *: t => x *: scala.Tuple.InverseMap[t, quoted.Expr]
// case EmptyTuple => EmptyTuple

// ^
// Cyclic reference involving val res

// ^
// Match type reduction failed since selector ((2 : Int), quoted.Expr[(3 : Int)])
// matches none of the cases
//
// case quoted.Expr[x] *: t => x *: scala.Tuple.InverseMap[t, quoted.Expr]
// case EmptyTuple => EmptyTuple
}
20 changes: 10 additions & 10 deletions tests/neg/i12049.check
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@
| case B => String
|
| longer explanation available when compiling with `-explain`
-- [E184] Type Error: tests/neg/i12049.scala:14:23 ---------------------------------------------------------------------
-- Error: tests/neg/i12049.scala:14:23 ---------------------------------------------------------------------------------
14 |val y3: String = ??? : Last[Int *: Int *: Boolean *: String *: EmptyTuple] // error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| Match type reduction failed since selector EmptyTuple
| ^
| Match type reduction failed since selector EmptyTuple.type
| matches none of the cases
|
| case _ *: _ *: t => Last[t]
| case t *: EmptyTuple => t
-- [E184] Type Error: tests/neg/i12049.scala:22:26 ---------------------------------------------------------------------
-- Error: tests/neg/i12049.scala:22:26 ---------------------------------------------------------------------------------
22 |val z3: (A, B, A) = ??? : Reverse[(A, B, A)] // error
| ^^^^^^^^^^^^^^^^^^
| ^
| Match type reduction failed since selector A *: EmptyTuple.type
| matches none of the cases
|
Expand All @@ -45,17 +45,17 @@
| Therefore, reduction cannot advance to the remaining case
|
| case B => String
-- [E184] Type Error: tests/neg/i12049.scala:25:26 ---------------------------------------------------------------------
-- Error: tests/neg/i12049.scala:25:26 ---------------------------------------------------------------------------------
25 |val _ = summon[String =:= Last[Int *: Int *: Boolean *: String *: EmptyTuple]] // error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| Match type reduction failed since selector EmptyTuple
| ^
| Match type reduction failed since selector EmptyTuple.type
| matches none of the cases
|
| case _ *: _ *: t => Last[t]
| case t *: EmptyTuple => t
-- [E184] Type Error: tests/neg/i12049.scala:26:29 ---------------------------------------------------------------------
-- Error: tests/neg/i12049.scala:26:29 ---------------------------------------------------------------------------------
26 |val _ = summon[(A, B, A) =:= Reverse[(A, B, A)]] // error
| ^^^^^^^^^^^^^^^^^^
| ^
| Match type reduction failed since selector A *: EmptyTuple.type
| matches none of the cases
|
Expand Down
8 changes: 4 additions & 4 deletions tests/neg/i13757-match-type-anykind.scala
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
object Test:
type AnyKindMatchType1[X <: AnyKind] = X match // error: the scrutinee of a match type cannot be higher-kinded
type AnyKindMatchType1[X <: AnyKind] = X match // error: the scrutinee of a match type cannot be higher-kinded // error
case Option[a] => Int

type AnyKindMatchType2[X <: AnyKind] = X match // error: the scrutinee of a match type cannot be higher-kinded
case Option => Int // error: Missing type parameter for Option

type AnyKindMatchType3[X <: AnyKind] = X match // error: the scrutinee of a match type cannot be higher-kinded
type AnyKindMatchType3[X <: AnyKind] = X match // error: the scrutinee of a match type cannot be higher-kinded // error
case _ => Int

type AnyKindMatchType4[X <: Option] = X match // error // error: the scrutinee of a match type cannot be higher-kinded
type AnyKindMatchType4[X <: Option] = X match // error // error: the scrutinee of a match type cannot be higher-kinded // error
case _ => Int

type AnyKindMatchType5[X[_]] = X match // error: the scrutinee of a match type cannot be higher-kinded
type AnyKindMatchType5[X[_]] = X match // error: the scrutinee of a match type cannot be higher-kinded // error
case _ => Int
end Test
8 changes: 4 additions & 4 deletions tests/neg/matchtype-seq.check
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
-- [E184] Type Error: tests/neg/matchtype-seq.scala:9:11 ---------------------------------------------------------------
-- Error: tests/neg/matchtype-seq.scala:9:11 ---------------------------------------------------------------------------
9 | identity[T1[3]]("") // error
| ^^^^^
| ^
| Match type reduction failed since selector (3 : Int)
| matches none of the cases
|
| case (1 : Int) => Int
| case (2 : Int) => String
-- [E184] Type Error: tests/neg/matchtype-seq.scala:10:11 --------------------------------------------------------------
-- Error: tests/neg/matchtype-seq.scala:10:11 --------------------------------------------------------------------------
10 | identity[T1[3]](1) // error
| ^^^^^
| ^
| Match type reduction failed since selector (3 : Int)
| matches none of the cases
|
Expand Down

0 comments on commit b2c544a

Please sign in to comment.