Skip to content

Commit 2317859

Browse files
committed
Put level checking under a config flag
Off by default
1 parent 78dbc59 commit 2317859

File tree

6 files changed

+72
-3
lines changed

6 files changed

+72
-3
lines changed

compiler/src/dotty/tools/dotc/config/Config.scala

+6
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,10 @@ object Config {
226226
* reduces the number of allocated denotations by ~50%.
227227
*/
228228
inline val reuseSymDenotations = true
229+
230+
/** If true, check levels of type variables and create fresh ones as needed.
231+
* This is necessary for soundness (see 3ab18a9), but also causes several
232+
* regressions that should be fixed before turning this on.
233+
*/
234+
inline val checkLevels = false
229235
}

compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

+4-3
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ trait ConstraintHandling {
9292

9393
/** Is `level` <= `maxLevel` or legal in the current context? */
9494
def levelOK(level: Int, maxLevel: Int)(using Context): Boolean =
95-
level <= maxLevel ||
96-
ctx.isAfterTyper || !ctx.typerState.isCommittable || // Leaks in these cases shouldn't break soundness
97-
level == Int.MaxValue // See `nestingLevel` above.
95+
level <= maxLevel
96+
|| ctx.isAfterTyper || !ctx.typerState.isCommittable // Leaks in these cases shouldn't break soundness
97+
|| level == Int.MaxValue // See `nestingLevel` above.
98+
|| !Config.checkLevels
9899

99100
/** If `param` is nested deeper than `maxLevel`, try to instantiate it to a
100101
* fresh type variable of level `maxLevel` and return the new variable.

tests/pos/i14494.scala

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object ImplNotFound:
2+
def main(args: Array[String]): Unit =
3+
val res: Seq[String | Int] = (??? : Seq[Int]).collect {
4+
case 1 => Seq("")
5+
case 2 => Seq(1)
6+
}.flatten

tests/pos/i15178.scala

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// This should be a neg test once level checking is re-enabled.
2+
3+
trait E[F[_]] {
4+
type T
5+
val value: F[T]
6+
}
7+
8+
object E {
9+
def apply[F[_], T1](value1: F[T1]) = new E[F] {
10+
type T = T1
11+
val value = value1
12+
}
13+
}
14+
15+
val a: Option[E[Ordering]] = Option(E(Ordering[Int]))
16+
val _ = a.map(it => E(it.value)) // there should be an error here
17+

tests/pos/i15184.scala

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
def test() = {
2+
func(_ => Box(Seq.empty[String]) )
3+
}
4+
5+
def func[R0](to0: Unit => R0): Unit = ???
6+
7+
trait JsonFormat[T]
8+
object JsonFormat{
9+
implicit def immSeqFormat: JsonFormat[Seq[String]] = ???
10+
11+
implicit def iterableFormat: JsonFormat[Iterable[String]] = ???
12+
}
13+
14+
case class Box[A1: JsonFormat](elem: A1)

tests/pos/i15216.scala

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
sealed abstract class Free[S[_], A] {
2+
final def map[B](f: A => B): Free[S, B] = ???
3+
final def flatMap[B](f: A => Free[S, B]): Free[S, B] = new Free[S, B] {}
4+
}
5+
6+
trait Parameter[T]
7+
def namedDouble(name: String): Free[Parameter, Double] = ???
8+
9+
type Double2 = (Double, Double)
10+
type Double3 = (Double, Double, Double)
11+
val spec: Free[Parameter, Either[Double3, Double2]] = for {
12+
result <-
13+
if (???) {
14+
for {
15+
x <- namedDouble("X")
16+
y <- namedDouble("Y")
17+
z <- namedDouble("Z")
18+
} yield Left((x, y, z))
19+
} else {
20+
for {
21+
x <- namedDouble("X")
22+
y <- namedDouble("Y")
23+
} yield Right((x, y))
24+
}
25+
} yield result

0 commit comments

Comments
 (0)