Skip to content

Match type trace improvements #20178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/MatchTypeTrace.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ object MatchTypeTrace:

private val MatchTrace = new Property.Key[MatchTrace]

/** Execute `op` and if it involves a failed match type reduction
/** Execute `op` and if it is a failed match type reduction
* return the trace of that reduction. Otherwise return the empty string.
*/
def record(op: Context ?=> Any)(using Context): String =
Expand Down
3 changes: 2 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1536,7 +1536,8 @@ object Types extends TypeUtils {

/** If this type can be normalized at the top-level by rewriting match types
* of S[n] types, the result after applying all toplevel normalizations,
* otherwise NoType
* otherwise NoType. Note applied match aliases are not beta reduced
* if the underlying MatchType is stuck.
*/
def tryNormalize(using Context): Type = NoType

Expand Down
9 changes: 5 additions & 4 deletions compiler/src/dotty/tools/dotc/typer/ErrorReporting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ object ErrorReporting {
val collectMatchTrace = new TypeAccumulator[String]:
def apply(s: String, tp: Type): String =
if s.nonEmpty then s
else tp match
case tp: AppliedType if tp.isMatchAlias => MatchTypeTrace.record(tp.tryNormalize)
case tp: MatchType => MatchTypeTrace.record(tp.tryNormalize)
case _ => foldOver(s, tp)
else
val normed = tp.normalized
val toTrace = if normed.isMatchAlias then normed else normed.dealias
val r = MatchTypeTrace.record(toTrace.tryNormalize)
if r.nonEmpty then r else foldOver(s, tp)
tps.foldLeft("")(collectMatchTrace)

/** A mixin trait that can produce added elements for an error message */
Expand Down
14 changes: 7 additions & 7 deletions tests/neg/i12049.check → tests/neg/i12049a.check
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-- [E007] Type Mismatch Error: tests/neg/i12049.scala:6:16 -------------------------------------------------------------
-- [E007] Type Mismatch Error: tests/neg/i12049a.scala:6:16 ------------------------------------------------------------
6 |val x: String = ??? : M[B] // error
| ^^^^^^^^^^
| Found: M[B]
Expand All @@ -15,7 +15,7 @@
| case B => String
|
| longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: tests/neg/i12049.scala:14:17 ------------------------------------------------------------
-- [E007] Type Mismatch Error: tests/neg/i12049a.scala:14:17 -----------------------------------------------------------
14 |val y3: String = ??? : Last[Int *: Int *: Boolean *: String *: EmptyTuple] // error
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| Found: Last[EmptyTuple]
Expand All @@ -31,7 +31,7 @@
| case t *: EmptyTuple => t
|
| longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: tests/neg/i12049.scala:22:20 ------------------------------------------------------------
-- [E007] Type Mismatch Error: tests/neg/i12049a.scala:22:20 -----------------------------------------------------------
22 |val z3: (A, B, A) = ??? : Reverse[(A, B, A)] // error
| ^^^^^^^^^^^^^^^^^^^^^^^^
| Found: Tuple.Concat[Reverse[A *: EmptyTuple.type], (B, A)]
Expand All @@ -48,7 +48,7 @@
| case EmptyTuple => EmptyTuple
|
| longer explanation available when compiling with `-explain`
-- [E172] Type Error: tests/neg/i12049.scala:24:20 ---------------------------------------------------------------------
-- [E172] Type Error: tests/neg/i12049a.scala:24:20 --------------------------------------------------------------------
24 |val _ = summon[M[B]] // error
| ^
| No given instance of type M[B] was found for parameter x of method summon in object Predef
Expand All @@ -62,7 +62,7 @@
| Therefore, reduction cannot advance to the remaining case
|
| case B => String
-- [E172] Type Error: tests/neg/i12049.scala:25:78 ---------------------------------------------------------------------
-- [E172] Type Error: tests/neg/i12049a.scala:25:78 --------------------------------------------------------------------
25 |val _ = summon[String =:= Last[Int *: Int *: Boolean *: String *: EmptyTuple]] // error
| ^
| Cannot prove that String =:= Last[EmptyTuple].
Expand All @@ -75,7 +75,7 @@
|
| case _ *: _ *: t => Last[t]
| case t *: EmptyTuple => t
-- [E172] Type Error: tests/neg/i12049.scala:26:48 ---------------------------------------------------------------------
-- [E172] Type Error: tests/neg/i12049a.scala:26:48 --------------------------------------------------------------------
26 |val _ = summon[(A, B, A) =:= Reverse[(A, B, A)]] // error
| ^
| Cannot prove that (A, B, A) =:= Tuple.Concat[Reverse[A *: EmptyTuple.type], (B, A)].
Expand All @@ -89,7 +89,7 @@
|
| case t1 *: t2 *: ts => Tuple.Concat[Reverse[ts], (t2, t1)]
| case EmptyTuple => EmptyTuple
-- [E008] Not Found Error: tests/neg/i12049.scala:28:21 ----------------------------------------------------------------
-- [E008] Not Found Error: tests/neg/i12049a.scala:28:21 ---------------------------------------------------------------
28 |val _ = (??? : M[B]).length // error
| ^^^^^^^^^^^^^^^^^^^
| value length is not a member of M[B]
Expand Down
File renamed without changes.
17 changes: 17 additions & 0 deletions tests/neg/i12049b.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

-- [E007] Type Mismatch Error: tests/neg/i12049b/B_2.scala:2:17 --------------------------------------------------------
2 |val y1: String = foo // error
| ^^^
| Found: Last[(Int, Int, Boolean, String)]
| Required: String
|
| Note: a match type could not be fully reduced:
|
| trying to reduce Last[EmptyTuple]
| failed since selector EmptyTuple
| matches none of the cases
|
| case _ *: _ *: t => Last[t]
| case t *: EmptyTuple => t
|
| longer explanation available when compiling with `-explain`
6 changes: 6 additions & 0 deletions tests/neg/i12049b/A_1.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

type Last[X <: Tuple] = X match
case _ *: _ *: t => Last[t]
case t *: EmptyTuple => t

def foo: Last[Int *: Int *: Boolean *: String *: EmptyTuple] = ???
2 changes: 2 additions & 0 deletions tests/neg/i12049b/B_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

val y1: String = foo // error
34 changes: 34 additions & 0 deletions tests/neg/i12049c.check
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
-- [E007] Type Mismatch Error: tests/neg/i12049c.scala:9:16 ------------------------------------------------------------
9 |val x: String = ??? : M[B] // error
| ^^^^^^^^^^
| Found: M[B]
| Required: String
|
| Note: a match type could not be fully reduced:
|
| trying to reduce M[B]
| failed since selector B
| does not match case A => Int
| and cannot be shown to be disjoint from it either.
| Therefore, reduction cannot advance to the remaining case
|
| case B => String
|
| longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: tests/neg/i12049c.scala:12:17 -----------------------------------------------------------
12 |val x2: String = ??? : MB // error
| ^^^^^^^^
| Found: MB
| Required: String
|
| Note: a match type could not be fully reduced:
|
| trying to reduce M[B]
| failed since selector B
| does not match case A => Int
| and cannot be shown to be disjoint from it either.
| Therefore, reduction cannot advance to the remaining case
|
| case B => String
|
| longer explanation available when compiling with `-explain`
12 changes: 12 additions & 0 deletions tests/neg/i12049c.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

trait A
trait B

type M[X] = X match
case A => Int
case B => String

val x: String = ??? : M[B] // error

type MB = M[B]
val x2: String = ??? : MB // error
Loading