diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 0ceaaac75063..67655cea8688 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -287,11 +287,24 @@ trait ConstraintHandling { end legalBound protected def addOneBound(param: TypeParamRef, rawBound: Type, isUpper: Boolean)(using Context): Boolean = + + // Replace top-level occurrences of `param` in `bound` by `Nothing` + def sanitize(bound: Type): Type = + if bound.stripped eq param then defn.NothingType + else bound match + case bound: AndOrType => + bound.derivedAndOrType(sanitize(bound.tp1), sanitize(bound.tp2)) + case _ => + bound + if !constraint.contains(param) then true - else if !isUpper && param.occursIn(rawBound) then - // We don't allow recursive lower bounds when defining a type, - // so we shouldn't allow them as constraints either. - false + else if !isUpper && param.occursIn(rawBound.widen) then + val rawBound1 = sanitize(rawBound.widenDealias) + if param.occursIn(rawBound1) then + // We don't allow recursive lower bounds when defining a type, + // so we shouldn't allow them as constraints either. + false + else addOneBound(param, rawBound1, isUpper) else // Narrow one of the bounds of type parameter `param` diff --git a/tests/neg/i21535.check b/tests/neg/i21535.check new file mode 100644 index 000000000000..7a24f2196ec8 --- /dev/null +++ b/tests/neg/i21535.check @@ -0,0 +1,11 @@ +-- [E007] Type Mismatch Error: tests/neg/i21535.scala:7:4 -------------------------------------------------------------- +3 | (if (true) then +4 | new A(66) +5 | else +6 | m1() +7 | ).m2(p1 = p); // error + | ^ + | Found: (Int | Short) @uncheckedVariance + | Required: Int & Short + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg/i21535.scala b/tests/neg/i21535.scala new file mode 100644 index 000000000000..f9573f823160 --- /dev/null +++ b/tests/neg/i21535.scala @@ -0,0 +1,16 @@ +def test() = { + val p = 10.toShort + (if (true) then + new A(66) + else + m1() + ).m2(p1 = p); // error + +} + +def m1(): A[Short] = new A(10) + +class A[D](var f: D) { + + def m2(p1: D = f, p2: D = f): Unit = {} +} \ No newline at end of file