Skip to content

Commit

Permalink
Fix #1515: Don't narrow gadt bounds when frozen
Browse files Browse the repository at this point in the history
Fixes #1515. Review by @smarter.
  • Loading branch information
odersky committed Oct 14, 2016
1 parent 8bfaada commit a4594dd
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 21 deletions.
43 changes: 22 additions & 21 deletions src/dotty/tools/dotc/core/TypeComparer.scala
Expand Up @@ -965,28 +965,29 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
* Test that the resulting bounds are still satisfiable.
*/
private def narrowGADTBounds(tr: NamedType, bound: Type, isUpper: Boolean): Boolean =
ctx.mode.is(Mode.GADTflexible) && {
val tparam = tr.symbol
typr.println(i"narrow gadt bound of $tparam: ${tparam.info} from ${if (isUpper) "above" else "below"} to $bound ${bound.isRef(tparam)}")
if (bound.isRef(tparam)) false
else bound match {
case bound: TypeRef
if bound.symbol.is(BindDefinedType) && ctx.gadt.bounds.contains(bound.symbol) &&
!tr.symbol.is(BindDefinedType) =>
// Avoid having pattern-bound types in gadt bounds,
// as these might be eliminated once the pattern is typechecked.
// Pattern-bound type symbols should be narrowed first, only if that fails
// should symbols in the environment be constrained.
narrowGADTBounds(bound, tr, !isUpper)
case _ =>
val oldBounds = ctx.gadt.bounds(tparam)
val newBounds =
if (isUpper) TypeBounds(oldBounds.lo, oldBounds.hi & bound)
else TypeBounds(oldBounds.lo | bound, oldBounds.hi)
isSubType(newBounds.lo, newBounds.hi) &&
{ ctx.gadt.setBounds(tparam, newBounds); true }
ctx.mode.is(Mode.GADTflexible) && !frozenConstraint && {
val tparam = tr.symbol
typr.println(i"narrow gadt bound of $tparam: ${tparam.info} from ${if (isUpper) "above" else "below"} to $bound ${bound.isRef(tparam)}")
if (bound.isRef(tparam)) false
else bound match {
case bound: TypeRef
if bound.symbol.is(BindDefinedType) &&
ctx.gadt.bounds.contains(bound.symbol) &&
!tr.symbol.is(BindDefinedType) =>
// Avoid having pattern-bound types in gadt bounds,
// as these might be eliminated once the pattern is typechecked.
// Pattern-bound type symbols should be narrowed first, only if that fails
// should symbols in the environment be constrained.
narrowGADTBounds(bound, tr, !isUpper)
case _ =>
val oldBounds = ctx.gadt.bounds(tparam)
val newBounds =
if (isUpper) TypeBounds(oldBounds.lo, oldBounds.hi & bound)
else TypeBounds(oldBounds.lo | bound, oldBounds.hi)
isSubType(newBounds.lo, newBounds.hi) &&
{ ctx.gadt.setBounds(tparam, newBounds); true }
}
}
}

// Tests around `matches`

Expand Down
16 changes: 16 additions & 0 deletions tests/pos/i1515.scala
@@ -0,0 +1,16 @@
sealed trait Trait[T]

final case class Case[T](e: T) extends Trait[T]

object Demo {
def main(args: Array[String]): Unit = {

def f[H](t: Trait[H]): Unit =
t match {
case Case(e) => println(Some(e))
}

f(Case(1))

}
}

0 comments on commit a4594dd

Please sign in to comment.