From 191885cda9aa7d60b25527efe0dfc95c15f3338d Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Mon, 22 Apr 2024 19:15:20 +0200 Subject: [PATCH 1/3] Instantiate constraint entries when updated to equal bounds --- .../tools/dotc/core/ConstraintHandling.scala | 2 +- .../tools/dotc/core/OrderingConstraint.scala | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 109929f0c6f5..656d1e1cf5a0 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -327,7 +327,7 @@ trait ConstraintHandling { (c1 eq constraint) || { constraint = c1 - val TypeBounds(lo, hi) = constraint.entry(param): @unchecked + val TypeBounds(lo, hi) = constraint.nonParamBounds(param) isSub(lo, hi) } end addOneBound diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 8256a3cdbab1..5049ca3dd964 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -104,6 +104,18 @@ object OrderingConstraint { def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[Type])(using Context): OrderingConstraint = c.newConstraint(boundsMap = c.boundsMap.updated(poly, entries)) def initial = NoType + + override def update(prev: OrderingConstraint, current: OrderingConstraint, + poly: TypeLambda, idx: Int, entry: Type)(using Context): OrderingConstraint = + entry match + case TypeBounds(lo, hi) if lo eq hi => + val replaceParams = new TypeMap: + def apply(tp: Type): Type = tp match + case tp: TypeParamRef => current.typeVarOfParam(tp) + case _ => mapOver(tp) + super.update(prev, current, poly, idx, replaceParams(hi)) + case _ => + super.update(prev, current, poly, idx, entry) } private val lowerLens: ConstraintLens[List[TypeParamRef]] = new ConstraintLens[List[TypeParamRef]] { @@ -483,7 +495,10 @@ class OrderingConstraint(private val boundsMap: ParamBounds, case param: TypeParamRef if contains(param) => todos += (if isUpper then order(_, _, param) else order(_, param, _)) NoType - case tp: TypeBounds => + case tp: TypeBounds if tp.lo ne tp.hi => + // IMPROVE + // - pass current ? or + // - do opt in add too val lo1 = stripParams(tp.lo, todos, !isUpper).orElse(defn.NothingType) val hi1 = stripParams(tp.hi, todos, isUpper).orElse(tp.topType) tp.derivedTypeBounds(lo1, hi1) From 3d3581727e3ab28abac45ceb65dd0b54cc2a5107 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Mon, 22 Apr 2024 19:30:26 +0200 Subject: [PATCH 2/3] Pass current OrderingConstraint to stripParams --- .../tools/dotc/core/OrderingConstraint.scala | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 5049ca3dd964..c5e14e06139f 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -489,29 +489,27 @@ class OrderingConstraint(private val boundsMap: ParamBounds, * @param isUpper If true, `bound` is an upper bound, else a lower bound. */ private def stripParams( + current: OrderingConstraint, tp: Type, todos: mutable.ListBuffer[(OrderingConstraint, TypeParamRef) => OrderingConstraint], isUpper: Boolean)(using Context): Type = tp match { - case param: TypeParamRef if contains(param) => + case param: TypeParamRef if current.contains(param) => todos += (if isUpper then order(_, _, param) else order(_, param, _)) NoType - case tp: TypeBounds if tp.lo ne tp.hi => - // IMPROVE - // - pass current ? or - // - do opt in add too - val lo1 = stripParams(tp.lo, todos, !isUpper).orElse(defn.NothingType) - val hi1 = stripParams(tp.hi, todos, isUpper).orElse(tp.topType) + case tp: TypeBounds => + val lo1 = stripParams(current, tp.lo, todos, !isUpper).orElse(defn.NothingType) + val hi1 = stripParams(current, tp.hi, todos, isUpper).orElse(tp.topType) tp.derivedTypeBounds(lo1, hi1) case tp: AndType if isUpper => - val tp1 = stripParams(tp.tp1, todos, isUpper) - val tp2 = stripParams(tp.tp2, todos, isUpper) + val tp1 = stripParams(current, tp.tp1, todos, isUpper) + val tp2 = stripParams(current, tp.tp2, todos, isUpper) if (tp1.exists) if (tp2.exists) tp.derivedAndType(tp1, tp2) else tp1 else tp2 case tp: OrType if !isUpper => - val tp1 = stripParams(tp.tp1, todos, isUpper) - val tp2 = stripParams(tp.tp2, todos, isUpper) + val tp1 = stripParams(current, tp.tp1, todos, isUpper) + val tp2 = stripParams(current, tp.tp2, todos, isUpper) if (tp1.exists) if (tp2.exists) tp.derivedOrType(tp1, tp2) else tp1 @@ -542,7 +540,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, while (i < poly.paramNames.length) { val param = poly.paramRefs(i) val bounds = dropWildcards(nonParamBounds(param)) - val stripped = stripParams(bounds, todos, isUpper = true) + val stripped = stripParams(current, bounds, todos, isUpper = true) current = boundsLens.update(this, current, param, stripped) while todos.nonEmpty do current = todos.head(current, param) From 6cb6d380f8289a660b4574a287566e136d48f686 Mon Sep 17 00:00:00 2001 From: Eugene Flesselle Date: Mon, 22 Apr 2024 20:20:55 +0200 Subject: [PATCH 3/3] Revert to equal bounds when typeVarOfParam is unknown See sbt-test/source-dependencies/inline-rec-change-typaram for an example --- compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index c5e14e06139f..e3f93547c260 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -111,7 +111,7 @@ object OrderingConstraint { case TypeBounds(lo, hi) if lo eq hi => val replaceParams = new TypeMap: def apply(tp: Type): Type = tp match - case tp: TypeParamRef => current.typeVarOfParam(tp) + case tp: TypeParamRef => current.typeVarOfParam(tp).orElse(tp) case _ => mapOver(tp) super.update(prev, current, poly, idx, replaceParams(hi)) case _ =>