Skip to content
Closed
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
44 changes: 24 additions & 20 deletions compiler/src/dotty/tools/dotc/transform/TypeTestsCasts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -144,26 +144,30 @@ object TypeTestsCasts {
case _ => recur(defn.AnyType, tpT)
}
case tpe @ AppliedType(tycon, targs) if !trustTypeApplication =>
X.widenDealias match {
case OrType(tp1, tp2) =>
// This case is required to retrofit type inference,
// which cut constraints in the following two cases:
// - T1 <:< T2 | T3
// - T1 & T2 <:< T3
// See TypeComparer#either
recur(tp1, P) && recur(tp2, P)
case tpX: FlexibleType =>
recur(tpX.underlying, P)
case x =>
// always false test warnings are emitted elsewhere
// provablyDisjoint wants fully applied types as input; because we're in the middle of erasure, we sometimes get raw types here
val xApplied =
val tparams = x.typeParams
if tparams.isEmpty then x else x.appliedTo(tparams.map(_ => WildcardType))
TypeComparer.provablyDisjoint(xApplied, tpe.derivedAppliedType(tycon, targs.map(_ => WildcardType)))
|| typeArgsDeterminable(X, tpe)
||| i"its type arguments can't be determined from $X"
}
val abstractArgs = targs.filter(arg => isAbstract(arg) && !arg.isInstanceOf[WildcardType] )
if abstractArgs.nonEmpty && !tycon.classSymbol.is(Final) then
i"type arguments $abstractArgs refer to abstract types,"
else
X.widenDealias match {
case OrType(tp1, tp2) =>
// This case is required to retrofit type inference,
// which cut constraints in the following two cases:
// - T1 <:< T2 | T3
// - T1 & T2 <:< T3
// See TypeComparer#either
recur(tp1, P) && recur(tp2, P)
case tpX: FlexibleType =>
recur(tpX.underlying, P)
case x =>
// always false test warnings are emitted elsewhere
// provablyDisjoint wants fully applied types as input; because we're in the middle of erasure, we sometimes get raw types here
val xApplied =
val tparams = x.typeParams
if tparams.isEmpty then x else x.appliedTo(tparams.map(_ => WildcardType))
TypeComparer.provablyDisjoint(xApplied, tpe.derivedAppliedType(tycon, targs.map(_ => WildcardType)))
|| typeArgsDeterminable(X, tpe)
||| i"its type arguments can't be determined from $X"
}
case AndType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
case OrType(tp1, tp2) => recur(X, tp1) && recur(X, tp2)
case AnnotatedType(t, _) => recur(X, t)
Expand Down
13 changes: 13 additions & 0 deletions tests/neg/i24322.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
trait A[+T]:
def x: T
trait B[+T] extends A[T]:
def y: T

object Troll extends A[Int] with B[Any]:
def x: Int = 0
def y: Any = ""

def f[T](a: A[T]): T = a match {
case b: B[T] => b.y // error
case _ => a.x
}
10 changes: 10 additions & 0 deletions tests/pos/i24322.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
trait A[+T]:
def x: T
final class B[+T] extends A[T]:
def x: T = ???
def y: T = ???

def f[T](a: A[T]): T = a match {
case b: B[T] => b.y // compiles without warning
case _ => a.x
}
Loading