Skip to content

Commit a1067eb

Browse files
committed
Disallow recursive lower bounds in constraints
These can lead to deep subtype errors, this also fixes #8976 but see also the next commit which fixes the underlying soundness issue.
1 parent 43e4bfa commit a1067eb

File tree

3 files changed

+16
-0
lines changed

3 files changed

+16
-0
lines changed

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

+4
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ trait ConstraintHandling[AbstractContext] {
8787

8888
protected def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean)(using AbstractContext): Boolean =
8989
if !constraint.contains(param) then true
90+
else if !isUpper && param.occursIn(bound)
91+
// We don't allow recursive lower bounds when defining a type,
92+
// so we shouldn't allow them as constraints either.
93+
false
9094
else
9195
val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param)
9296
val equalBounds = (if isUpper then lo else hi) eq bound

tests/neg/i8976.scala

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
trait Cons[X, Y]
2+
3+
def solve[X, Y](using Cons[X, Y] =:= Cons[1, Cons[2, Y]]) = ()
4+
5+
@main def main = solve // error
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
class Foo[F <: Foo[F]]
2+
class Bar extends Foo[Bar]
3+
4+
class A {
5+
def foo[T <: Foo[T], U >: Foo[T] <: T](x: T): T = x
6+
foo(new Bar) // error
7+
}

0 commit comments

Comments
 (0)