Skip to content

Commit

Permalink
Normalize match type usage during implicit lookup
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed May 10, 2023
1 parent d4a8600 commit 5bafff7
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 1 deletion.
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3180,7 +3180,7 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
tp
case Nil =>
val casesText = MatchTypeTrace.noMatchesText(scrut, cases)
throw TypeError(em"Match type reduction $casesText")
throw MatchTypeReductionError(em"Match type reduction $casesText")

inFrozenConstraint {
// Empty types break the basic assumption that if a scrutinee and a
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 @@ -46,6 +46,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
7 changes: 7 additions & 0 deletions compiler/src/dotty/tools/dotc/typer/Implicits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,13 @@ trait ImplicitRunInfo:
case t: TypeLambda =>
for p <- t.paramRefs do partSeen += p
traverseChildren(t)
case t: MatchType =>
traverseChildren(t)
traverse(try t.normalized catch case _: MatchTypeReductionError => t)
case MatchType.InDisguise(mt)
if !t.isInstanceOf[LazyRef] // skip recursive applications (eg. Tuple.Map)
=>
traverse(mt)
case t =>
traverseChildren(t)

Expand Down
25 changes: 25 additions & 0 deletions tests/pos/i17395.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
trait TC[T]

object TC {
def optionTCForPart[T](implicit tc: TC[ExtractPart[T]]): TC[Option[ExtractPart[T]]] = new TC[Option[ExtractPart[T]]] {}
}

type ExtractPart[T] = T match {
case PartField[t] => t
}
type PartField[T] = Any { type Part = T }

class ValuePartHolder {
type Part = Value
}

class Value
object Value {
implicit val tcValue: TC[Value] = new {}
}

@main def main(): Unit = {
// import Value.tcValue // explicit import works around the issue, but shouldn't be necessary
val tc = TC.optionTCForPart[ValuePartHolder]
println(tc)
}

0 comments on commit 5bafff7

Please sign in to comment.