Skip to content

Commit

Permalink
Allow type parameters to be widened, but consider them poison
Browse files Browse the repository at this point in the history
  • Loading branch information
dwijnand committed Mar 30, 2023
1 parent 01bb05f commit d0f9f5f
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ trait ConstraintHandling {
* toplevel; it is turned on again when we add parts of the scrutinee to the constraint.
*/
protected var canWidenAbstract: Boolean = true
protected var poisoned: Set[TypeParamRef] = Set.empty

protected var myNecessaryConstraintsOnly = false
/** When collecting the constraints needed for a particular subtyping
Expand Down
18 changes: 14 additions & 4 deletions compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -877,9 +877,13 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
override def apply(x: Boolean, t: Type) =
x && t.match
case t: TypeParamRef =>
variance == 0 || (t.binder ne caseLambda) || t.paramName.is(WildcardParamName)
variance == 0
|| (t.binder ne caseLambda)
|| t.paramName.is(WildcardParamName)
|| { poisoned += t; true }
case _ =>
foldOver(x, t)

canWidenAbstract && acc(true, tp)

def tryBaseType(cls2: Symbol) = {
Expand Down Expand Up @@ -3110,6 +3114,7 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
}

def matchCases(scrut: Type, cases: List[Type])(using Context): Type = {
var poisoned: Set[TypeParamRef] = Set.empty

def paramInstances(canApprox: Boolean) = new TypeAccumulator[Array[Type]]:
def apply(insts: Array[Type], t: Type) = t match
Expand All @@ -3121,10 +3126,10 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {
case entry: TypeBounds =>
val lo = fullLowerBound(param)
val hi = fullUpperBound(param)
if isSubType(hi, lo) then lo.simplified else Range(lo, hi)
if !poisoned(param) && isSubType(hi, lo) then lo.simplified else Range(lo, hi)
case inst =>
assert(inst.exists, i"param = $param\nconstraint = $constraint")
inst.simplified
if !poisoned(param) then inst.simplified else Range(inst, inst)
insts
case _ =>
foldOver(insts, t)
Expand Down Expand Up @@ -3152,9 +3157,14 @@ class TrackingTypeComparer(initctx: Context) extends TypeComparer(initctx) {

def matches(canWidenAbstract: Boolean): Boolean =
val saved = this.canWidenAbstract
val savedPoisoned = this.poisoned
this.canWidenAbstract = canWidenAbstract
this.poisoned = Set.empty
try necessarySubType(scrut, pat)
finally this.canWidenAbstract = saved
finally
poisoned = this.poisoned
this.poisoned = savedPoisoned
this.canWidenAbstract = saved

def redux(canApprox: Boolean): MatchResult =
caseLambda match
Expand Down
6 changes: 4 additions & 2 deletions tests/neg/6570-1.check
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
|
| trying to reduce M[T]
| failed since selector T
| does not match case Cov[x] => N[x]
| and cannot be shown to be disjoint from it either.
| does not uniquely determine parameter x in
| case Cov[x] => N[x]
| The computed bounds for the parameter are:
| x >: Box[Int]
|
| longer explanation available when compiling with `-explain`
18 changes: 12 additions & 6 deletions tests/neg/i11982a.check
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
|
| trying to reduce Tuple.Tail[X]
| failed since selector X
| does not match case _ *: xs => xs
| and cannot be shown to be disjoint from it either.
| does not uniquely determine parameter xs in
| case _ *: xs => xs
| The computed bounds for the parameter are:
| xs >: Any *: EmptyTuple.type <: Tuple
|
| longer explanation available when compiling with `-explain`
-- [E057] Type Mismatch Error: tests/neg/i11982a.scala:10:38 -----------------------------------------------------------
Expand All @@ -20,8 +22,10 @@
|
| trying to reduce Tuple.Tail[X]
| failed since selector X
| does not match case _ *: xs => xs
| and cannot be shown to be disjoint from it either.
| does not uniquely determine parameter xs in
| case _ *: xs => xs
| The computed bounds for the parameter are:
| xs >: Any *: EmptyTuple.type <: Tuple
|
| longer explanation available when compiling with `-explain`
-- [E057] Type Mismatch Error: tests/neg/i11982a.scala:12:25 -----------------------------------------------------------
Expand All @@ -33,7 +37,9 @@
|
| trying to reduce Tuple.Tail[X]
| failed since selector X
| does not match case _ *: xs => xs
| and cannot be shown to be disjoint from it either.
| does not uniquely determine parameter xs in
| case _ *: xs => xs
| The computed bounds for the parameter are:
| xs >: Any *: EmptyTuple.type <: Tuple
|
| longer explanation available when compiling with `-explain`
21 changes: 15 additions & 6 deletions tests/neg/i13780.check
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
|
| trying to reduce Head[X]
| failed since selector X
| does not match case (a, b) => a
| and cannot be shown to be disjoint from it either.
| does not uniquely determine parameters a, b in
| case (a, b) => a
| The computed bounds for the parameters are:
| a >: Any
| b >: Any
|
| longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: tests/neg/i13780.scala:18:31 ------------------------------------------------------------
Expand All @@ -28,8 +31,11 @@
|
| trying to reduce Head[X]
| failed since selector X
| does not match case (a, b) => a
| and cannot be shown to be disjoint from it either.
| does not uniquely determine parameters a, b in
| case (a, b) => a
| The computed bounds for the parameters are:
| a >: Int
| b >: Int
|
| longer explanation available when compiling with `-explain`
-- [E007] Type Mismatch Error: tests/neg/i13780.scala:23:37 ------------------------------------------------------------
Expand All @@ -45,7 +51,10 @@
|
| trying to reduce Head[X]
| failed since selector X
| does not match case (a, b) => a
| and cannot be shown to be disjoint from it either.
| does not uniquely determine parameters a, b in
| case (a, b) => a
| The computed bounds for the parameters are:
| a >: String
| b >: String
|
| longer explanation available when compiling with `-explain`

0 comments on commit d0f9f5f

Please sign in to comment.