Skip to content

Commit 0121d82

Browse files
committed
Handle dependent parameters hidden behind a TypeVar
This is needed for type inference with a type variable selection (added in the next commit of this PR) to work properly, but it also affects master. Because dependencies can now span multiple TypeLambdas, `addToConstraint` had to be adjusted to properly propagate all constraints. i5735 doesn't compile anymore but I don't think it ever really made sense.
1 parent 23e6d6c commit 0121d82

File tree

4 files changed

+14
-5
lines changed

4 files changed

+14
-5
lines changed

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

+3-2
Original file line numberDiff line numberDiff line change
@@ -445,8 +445,9 @@ trait ConstraintHandling[AbstractContext] {
445445
if lower.nonEmpty && !bounds.lo.isRef(defn.NothingClass)
446446
|| upper.nonEmpty && !bounds.hi.isAny
447447
then constr.println(i"INIT*** $tl")
448-
lower.forall(addOneBound(_, bounds.hi, isUpper = true)) &&
449-
upper.forall(addOneBound(_, bounds.lo, isUpper = false))
448+
449+
lower.forall(loParam => addOneBound(loParam, bounds.hi, isUpper = true) && addOneBound(param, constraint.nonParamBounds(loParam).lo, isUpper = false))
450+
&& upper.forall(upParam => addOneBound(upParam, bounds.lo, isUpper = false) && addOneBound(param, constraint.nonParamBounds(upParam).hi, isUpper = true))
450451
case _ =>
451452
// Happens if param was already solved while processing earlier params of the same TypeLambda.
452453
// See #4720.

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
232232
* @param isUpper If true, `bound` is an upper bound, else a lower bound.
233233
*/
234234
private def stripParams(tp: Type, paramBuf: mutable.ListBuffer[TypeParamRef],
235-
isUpper: Boolean)(implicit ctx: Context): Type = tp match {
235+
isUpper: Boolean)(implicit ctx: Context): Type = tp.stripTypeVar match {
236236
case param: TypeParamRef if contains(param) =>
237237
if (!paramBuf.contains(param)) paramBuf += param
238238
NoType
@@ -365,7 +365,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
365365
* Q <: tp implies Q <: P and isUpper = true, or
366366
* tp <: Q implies P <: Q and isUpper = false
367367
*/
368-
private def dependentParams(tp: Type, isUpper: Boolean): List[TypeParamRef] = tp match
368+
private def dependentParams(tp: Type, isUpper: Boolean)(using Context): List[TypeParamRef] = tp.stripTypeVar match
369369
case param: TypeParamRef if contains(param) =>
370370
param :: (if (isUpper) upper(param) else lower(param))
371371
case tp: AndType if isUpper =>

tests/pos/i5735.scala renamed to tests/neg/i5735.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ object Test {
88
class Foo[T] { def apply[Y >: T <: Nested[T, Tuple2, Unit]](t: T): T = t }
99
def foo[T] = new Foo[T]
1010

11-
foo.apply((21, ()))
11+
foo.apply((21, ())) // error
1212
}

tests/pos/dependent-typevar.scala

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Foo[A] {
2+
// Previously, we did not record the constraint ordering `A <: B` here
3+
def bar[B >: A <: String]: String = ""
4+
}
5+
object Test {
6+
// ... which prevented the following from typechecking.
7+
val ret = (new Foo).bar
8+
}

0 commit comments

Comments
 (0)