aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Constraint.scala6
-rw-r--r--src/dotty/tools/dotc/core/ConstraintHandling.scala3
-rw-r--r--src/dotty/tools/dotc/core/OrderingConstraint.scala12
-rw-r--r--src/dotty/tools/dotc/core/TypeComparer.scala18
-rw-r--r--src/dotty/tools/dotc/core/Types.scala2
-rw-r--r--src/dotty/tools/dotc/typer/Implicits.scala6
-rw-r--r--src/dotty/tools/dotc/typer/ProtoTypes.scala2
7 files changed, 27 insertions, 22 deletions
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala
index d6e1589e0..bc0d476a9 100644
--- a/src/dotty/tools/dotc/core/Constraint.scala
+++ b/src/dotty/tools/dotc/core/Constraint.scala
@@ -92,11 +92,13 @@ abstract class Constraint extends Showable {
*/
def updateEntry(param: PolyParam, tp: Type)(implicit ctx: Context): This
- /** A constraint that includes the relationship `p1 <: p2`
+ /** A constraint that includes the relationship `p1 <: p2`.
+ * `<:` relationships between parameters ("edges") are propagated, but
+ * non-parameter bounds are left alone.
*/
def addLess(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This
- /** A constraint resulting by adding p2 = p1 to this constraint, and at the same
+ /** A constraint resulting from adding p2 = p1 to this constraint, and at the same
* time transferring all bounds of p2 to p1
*/
def unify(p1: PolyParam, p2: PolyParam)(implicit ctx: Context): This
diff --git a/src/dotty/tools/dotc/core/ConstraintHandling.scala b/src/dotty/tools/dotc/core/ConstraintHandling.scala
index 02f5bf87f..478fc5740 100644
--- a/src/dotty/tools/dotc/core/ConstraintHandling.scala
+++ b/src/dotty/tools/dotc/core/ConstraintHandling.scala
@@ -218,7 +218,8 @@ trait ConstraintHandling {
* `bound` is assumed to be in normalized form, as specified in `firstTry` and
* `secondTry` of `TypeComparer`. In particular, it should not be an alias type,
* lazy ref, typevar, wildcard type, error type. In addition, upper bounds may
- * not be AndTypes and lower bounds may not be OrTypes.
+ * not be AndTypes and lower bounds may not be OrTypes. This is assured by the
+ * way isSubType is organized.
*/
protected def addConstraint(param: PolyParam, bound: Type, fromBelow: Boolean): Boolean = {
def description = i"constr $param ${if (fromBelow) ">:" else "<:"} $bound:\n$constraint"
diff --git a/src/dotty/tools/dotc/core/OrderingConstraint.scala b/src/dotty/tools/dotc/core/OrderingConstraint.scala
index ec2a65416..e265c0b98 100644
--- a/src/dotty/tools/dotc/core/OrderingConstraint.scala
+++ b/src/dotty/tools/dotc/core/OrderingConstraint.scala
@@ -14,10 +14,10 @@ import reflect.ClassTag
object OrderingConstraint {
- /** The type of `Constraint#boundsMap` */
+ /** The type of `OrderingConstraint#boundsMap` */
type ParamBounds = SimpleMap[PolyType, Array[Type]]
- /** The type of `Constraint#lowerMap`, `Constraint#upperMap` */
+ /** The type of `OrderingConstraint#lowerMap`, `OrderingConstraint#upperMap` */
type ParamOrdering = SimpleMap[PolyType, Array[List[PolyParam]]]
/** A new constraint with given maps */
@@ -117,10 +117,10 @@ import OrderingConstraint._
*
* @param lowerMap a map from PolyTypes to arrays. Each array entry corresponds
* to a parameter P of the polytype; it contains all constrained parameters
- * Q that are known to be smaller than P, i.e. P <: Q.
+ * Q that are known to be smaller than P, i.e. Q <: P.
* @param upperMap a map from PolyTypes to arrays. Each array entry corresponds
* to a parameter P of the polytype; it contains all constrained parameters
- * Q that are known to be greater than P, i.e. Q <: P.
+ * Q that are known to be greater than P, i.e. P <: Q.
*/
class OrderingConstraint(private val boundsMap: ParamBounds,
private val lowerMap : ParamOrdering,
@@ -272,8 +272,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds,
// ---------- Updates ------------------------------------------------------------
- /** An updated partial order matrix that incorporates `less` and also reflects that `param` relates
- * to `p2` wrt <:< if `inOrder` is true, `>:>` otherwise.
+ /** Add the fact `param1 <: param2` to the constraint `current` and propagate
+ * `<:<` relationships between parameters ("edges") but not bounds.
*/
private def order(current: This, param1: PolyParam, param2: PolyParam)(implicit ctx: Context): This =
if (param1 == param2 || current.isLess(param1, param2)) this
diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala
index 6d5d78448..06f03b9f9 100644
--- a/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -299,7 +299,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
val gbounds2 = ctx.gadt.bounds(tp2.symbol)
(gbounds2 != null) &&
(isSubTypeWhenFrozen(tp1, gbounds2.lo) ||
- narrowGADTBounds(tp2, tp1, isLowerBound = true))
+ narrowGADTBounds(tp2, tp1, isUpper = false))
}
((frozenConstraint || !isCappable(tp1)) && isSubType(tp1, lo2) ||
compareGADT ||
@@ -414,7 +414,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
val gbounds1 = ctx.gadt.bounds(tp1.symbol)
(gbounds1 != null) &&
(isSubTypeWhenFrozen(gbounds1.hi, tp2) ||
- narrowGADTBounds(tp1, tp2, isLowerBound = false))
+ narrowGADTBounds(tp1, tp2, isUpper = true))
}
isSubType(hi1, tp2) || compareGADT
case _ =>
@@ -616,16 +616,20 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling wi
//})
}
- private def narrowGADTBounds(tr: NamedType, bound: Type, isLowerBound: Boolean): Boolean =
+ /** Narrow gadt.bounds for the type parameter referenced by `tr` to include
+ * `bound` as an upper or lower bound (which depends on `isUpper`).
+ * Test that the resulting bounds are still satisfiable.
+ */
+ private def narrowGADTBounds(tr: NamedType, bound: Type, isUpper: Boolean): Boolean =
ctx.mode.is(Mode.GADTflexible) && {
val tparam = tr.symbol
- val bound1 = deSkolemize(bound, toSuper = isLowerBound)
- typr.println(s"narrow gadt bound of $tparam: ${tparam.info} from ${if (isLowerBound) "below" else "above"} to $bound1 ${bound1.isRef(tparam)}")
+ val bound1 = deSkolemize(bound, toSuper = !isUpper)
+ typr.println(s"narrow gadt bound of $tparam: ${tparam.info} from ${if (isUpper) "above" else "below"} to $bound1 ${bound1.isRef(tparam)}")
!bound1.isRef(tparam) && {
val oldBounds = ctx.gadt.bounds(tparam)
val newBounds =
- if (isLowerBound) TypeBounds(oldBounds.lo | bound1, oldBounds.hi)
- else TypeBounds(oldBounds.lo, oldBounds.hi & bound1)
+ if (isUpper) TypeBounds(oldBounds.lo, oldBounds.hi & bound1)
+ else TypeBounds(oldBounds.lo | bound1, oldBounds.hi)
isSubType(newBounds.lo, newBounds.hi) &&
{ ctx.gadt.setBounds(tparam, newBounds); true }
}
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 30e394941..e986e680d 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -761,7 +761,7 @@ object Types {
* a reference to the "this" of the current refined type. But does follow
* aliases in order to avoid such references. Example:
*
- * Lambda$I { type $hk$Arg0 = String, type Apply = this<0>.$hk$Arg0 } # Apply
+ * Lambda$I { type $hk$Arg0 = String, type Apply = Lambda$I{...}.$hk$Arg0 } # Apply
*
* Here, the refinement for `Apply` has a refined this node, yet dereferencing ones more
* yields `String` as the result of lookupRefined.
diff --git a/src/dotty/tools/dotc/typer/Implicits.scala b/src/dotty/tools/dotc/typer/Implicits.scala
index 24d9ebf6d..5111f10bd 100644
--- a/src/dotty/tools/dotc/typer/Implicits.scala
+++ b/src/dotty/tools/dotc/typer/Implicits.scala
@@ -450,10 +450,8 @@ trait Implicits { self: Typer =>
private def nestedContext = ctx.fresh.setMode(ctx.mode &~ Mode.ImplicitsEnabled)
private def implicitProto(resultType: Type, f: Type => Type) =
- if (argument.isEmpty) f(resultType) else ViewProto(f(argument.tpe/*.widen*/), f(resultType))
- // !!! TODO: check performance implications
- // If we do the widen, SyntheticMethods, line 66 fails to compile
- // val synthetic = sym.copy(...)
+ if (argument.isEmpty) f(resultType) else ViewProto(f(argument.tpe.widen), f(resultType))
+ // Not clear whether we need to drop the `.widen` here. All tests pass with it in place, though.
assert(argument.isEmpty || argument.tpe.isValueType || argument.tpe.isInstanceOf[ExprType],
d"found: ${argument.tpe}, expected: $pt")
diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala
index 521f0deaa..e4d58cb19 100644
--- a/src/dotty/tools/dotc/typer/ProtoTypes.scala
+++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala
@@ -376,7 +376,7 @@ object ProtoTypes {
tp.derivedRefinedType(wildApprox(tp.parent, theMap), tp.refinedName, wildApprox(tp.refinedInfo, theMap))
case tp: TypeAlias => // default case, inlined for speed
tp.derivedTypeAlias(wildApprox(tp.alias, theMap))
- case tp @ PolyParam(poly, pnum) => // !!! todo adapt to TrackingConstraint
+ case tp @ PolyParam(poly, pnum) =>
ctx.typerState.constraint.entry(tp) match {
case bounds: TypeBounds => wildApprox(WildcardType(bounds))
case NoType => WildcardType(wildApprox(poly.paramBounds(pnum)).bounds)