103 lines
5.7 KiB
Diff
103 lines
5.7 KiB
Diff
# UNDF: UNDF-2026-000000271
|
|
diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
|
|
index 0154c70..c88a321 100644
|
|
--- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
|
|
+++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala
|
|
@@ -41,8 +41,9 @@ object OrderingConstraint {
|
|
/** The type of `OrderingConstraint#boundsMap` */
|
|
private type ParamBounds = ArrayValuedMap[Type]
|
|
|
|
- /** The type of `OrderingConstraint#lowerMap`, `OrderingConstraint#upperMap` */
|
|
- private type ParamOrdering = ArrayValuedMap[List[TypeParamRef]]
|
|
+ /** The type of `OrderingConstraint#lowerMap`, `OrderingConstraint#upperMap`.
|
|
+ * Each entry is a Set for O(1) membership tests in `isLess` (CWE-407 fix). */
|
|
+ private type ParamOrdering = ArrayValuedMap[Set[TypeParamRef]]
|
|
|
|
/** A lens for updating a single entry array in one of the three constraint maps */
|
|
private abstract class ConstraintLens[T <: AnyRef: ClassTag] {
|
|
@@ -106,20 +107,20 @@ object OrderingConstraint {
|
|
def initial = NoType
|
|
}
|
|
|
|
- private val lowerLens: ConstraintLens[List[TypeParamRef]] = new ConstraintLens[List[TypeParamRef]] {
|
|
- def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] | Null =
|
|
+ private val lowerLens: ConstraintLens[Set[TypeParamRef]] = new ConstraintLens[Set[TypeParamRef]] {
|
|
+ def entries(c: OrderingConstraint, poly: TypeLambda): Array[Set[TypeParamRef]] | Null =
|
|
c.lowerMap(poly)
|
|
- def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[List[TypeParamRef]])(using Context): OrderingConstraint =
|
|
+ def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[Set[TypeParamRef]])(using Context): OrderingConstraint =
|
|
c.newConstraint(lowerMap = c.lowerMap.updated(poly, entries))
|
|
- def initial = Nil
|
|
+ def initial = Set.empty
|
|
}
|
|
|
|
- private val upperLens: ConstraintLens[List[TypeParamRef]] = new ConstraintLens[List[TypeParamRef]] {
|
|
- def entries(c: OrderingConstraint, poly: TypeLambda): Array[List[TypeParamRef]] | Null =
|
|
+ private val upperLens: ConstraintLens[Set[TypeParamRef]] = new ConstraintLens[Set[TypeParamRef]] {
|
|
+ def entries(c: OrderingConstraint, poly: TypeLambda): Array[Set[TypeParamRef]] | Null =
|
|
c.upperMap(poly)
|
|
- def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[List[TypeParamRef]])(using Context): OrderingConstraint =
|
|
+ def updateEntries(c: OrderingConstraint, poly: TypeLambda, entries: Array[Set[TypeParamRef]])(using Context): OrderingConstraint =
|
|
c.newConstraint(upperMap = c.upperMap.updated(poly, entries))
|
|
- def initial = Nil
|
|
+ def initial = Set.empty
|
|
}
|
|
|
|
@sharable
|
|
@@ -207,8 +208,12 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
|
|
|
|
// ---------- Dependency handling ----------------------------------------------
|
|
|
|
- def lower(param: TypeParamRef): List[TypeParamRef] = lowerLens(this, param.binder, param.paramNum)
|
|
- def upper(param: TypeParamRef): List[TypeParamRef] = upperLens(this, param.binder, param.paramNum)
|
|
+ // Private O(1)-membership set accessors (internal use only, avoids .toList cost in isLess)
|
|
+ private def lowerSet(param: TypeParamRef): Set[TypeParamRef] = lowerLens(this, param.binder, param.paramNum)
|
|
+ private def upperSet(param: TypeParamRef): Set[TypeParamRef] = upperLens(this, param.binder, param.paramNum)
|
|
+
|
|
+ def lower(param: TypeParamRef): List[TypeParamRef] = lowerSet(param).toList
|
|
+ def upper(param: TypeParamRef): List[TypeParamRef] = upperSet(param).toList
|
|
|
|
def minLower(param: TypeParamRef): List[TypeParamRef] = {
|
|
val all = lower(param)
|
|
@@ -240,7 +245,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
|
|
// ---------- Info related to TypeParamRefs -------------------------------------------
|
|
|
|
def isLess(param1: TypeParamRef, param2: TypeParamRef): Boolean =
|
|
- upper(param1).contains(param2)
|
|
+ upperSet(param1).contains(param2) // O(1) hash lookup; was O(n) List.contains (CWE-407)
|
|
|
|
def nonParamBounds(param: TypeParamRef)(using Context): TypeBounds =
|
|
entry(param).bounds
|
|
@@ -624,8 +629,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
|
|
else
|
|
param1 :: lower
|
|
}
|
|
- val current1 = newLower.foldLeft(current)(upperLens.map(this, _, _, newUpper ::: _))
|
|
- val current2 = newUpper.foldLeft(current1)(lowerLens.map(this, _, _, newLower ::: _))
|
|
+ val current1 = newLower.foldLeft(current)(upperLens.map(this, _, _, _ ++ newUpper))
|
|
+ val current2 = newUpper.foldLeft(current1)(lowerLens.map(this, _, _, _ ++ newLower))
|
|
current2
|
|
end if
|
|
end order
|
|
@@ -697,8 +702,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
|
|
// dependency adjustment, we need to pretend that `param` is still unbound.
|
|
// We achieve that by passing a `ignoreBinding = param` to `adjustDeps` below.
|
|
|
|
- def removeParamFrom(ps: List[TypeParamRef]) =
|
|
- ps.filterConserve(param ne _)
|
|
+ def removeParamFrom(ps: Set[TypeParamRef]) =
|
|
+ ps - param
|
|
|
|
for lo <- lower(param) do
|
|
current = upperLens.map(this, current, lo, removeParamFrom)
|
|
@@ -764,8 +769,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
|
|
|
|
def remove(pt: TypeLambda)(using Context): This = {
|
|
def removeFromOrdering(po: ParamOrdering) = {
|
|
- def removeFromBoundss(key: TypeLambda, bndss: Array[List[TypeParamRef]]): Array[List[TypeParamRef]] = {
|
|
- val bndss1 = bndss.map(_.filterConserve(_.binder ne pt))
|
|
+ def removeFromBoundss(key: TypeLambda, bndss: Array[Set[TypeParamRef]]): Array[Set[TypeParamRef]] = {
|
|
+ val bndss1 = bndss.map(_.filterNot(_.binder eq pt))
|
|
if (bndss.corresponds(bndss1)(_ eq _)) bndss else bndss1
|
|
}
|
|
po.remove(pt).mapValuesNow(removeFromBoundss)
|