diff --git a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala index cf170d91ebb9..277daf799065 100644 --- a/compiler/src/dotty/tools/dotc/typer/Inferencing.scala +++ b/compiler/src/dotty/tools/dotc/typer/Inferencing.scala @@ -393,7 +393,7 @@ object Inferencing { def maximizeType(tp: Type, span: Span, fromScala2x: Boolean)(using Context): List[Symbol] = { Stats.record("maximizeType") val vs = variances(tp) - val patternBound = new mutable.ListBuffer[Symbol] + val patternBindings = new mutable.ListBuffer[(Symbol, TypeParamRef)] vs foreachBinding { (tvar, v) => if (v == 1) tvar.instantiate(fromBelow = false) else if (v == -1) tvar.instantiate(fromBelow = true) @@ -406,11 +406,17 @@ object Inferencing { // Instead, we simultaneously add them later on. val wildCard = newPatternBoundSymbol(UniqueName.fresh(tvar.origin.paramName), bounds, span, addToGadt = false) tvar.instantiateWith(wildCard.typeRef) - patternBound += wildCard + patternBindings += ((wildCard, tvar.origin)) } } } - val res = patternBound.toList + val res = patternBindings.toList.map { (boundSym, _) => + // substitute bounds of pattern bound variables to deal with possible F-bounds + for (wildCard, param) <- patternBindings do + boundSym.info = boundSym.info.substParam(param, wildCard.typeRef) + boundSym + } + // We add the created symbols to GADT constraint here. if (res.nonEmpty) ctx.gadt.addToConstraint(res) res diff --git a/tests/pos-deep-subtype/i9759.scala b/tests/pos-deep-subtype/i9759.scala new file mode 100644 index 000000000000..045a934c811b --- /dev/null +++ b/tests/pos-deep-subtype/i9759.scala @@ -0,0 +1,16 @@ +sealed trait Expr[A <: Expr[A]] + +case class Equals[A <: Value[A]](lhs: Expr[A], rhs: Expr[A]) extends Expr[Value.Boolean] + +sealed trait Value[A <: Value[A]] extends Expr[A] +object Value { + case class String(value: java.lang.String) extends Value[String] + case class Int(value: Long) extends Value[Int] + case class Boolean(value: java.lang.Boolean) extends Value[Boolean] +} + +object Main extends App { + def evaluate[A <: Value[A]](expr: Expr[A]): A = expr match { + case Equals(Value.String(lhs), Value.String(rhs)) => Value.Boolean(lhs == rhs) + } +} \ No newline at end of file