diff options
author | Martin Odersky <odersky@gmail.com> | 2017-03-01 22:10:17 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2017-03-01 22:11:45 +0100 |
commit | 1d237bb1f0c7aac949b52601e26e96fff0fe4ffd (patch) | |
tree | fc1f8cdcf01bc9939ee50b1d138c00616ddbc72d /compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala | |
parent | 58b71ca50ded400efa92ac8d92f4378844baaf7d (diff) | |
download | dotty-1d237bb1f0c7aac949b52601e26e96fff0fe4ffd.tar.gz dotty-1d237bb1f0c7aac949b52601e26e96fff0fe4ffd.tar.bz2 dotty-1d237bb1f0c7aac949b52601e26e96fff0fe4ffd.zip |
Make alignArgsInAnd safe and turn it on by default
Turned out hmaps.scala requires the arg alignment to compile.
So we have our first counterexample that we cannot drop this
hack. Now it is made safe in the sense that no constraints get
lost anymore.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala')
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 3aa20f15b..89861f6db 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -44,6 +44,13 @@ trait ConstraintHandling { try op finally alwaysFluid = saved } + /** If set, align arguments `S1`, `S2`when taking the glb + * `T1 { X = S1 } & T2 { X = S2 }` of a constraint upper bound for some type parameter. + * Aligning means computing `S1 =:= S2` which may change the current constraint. + * See note in TypeComparer#distributeAnd. + */ + protected var homogenizeArgs = false + /** We are currently comparing polytypes. Used as a flag for * optimization: when `false`, no need to do an expensive `pruneLambdaParams` */ @@ -64,7 +71,8 @@ trait ConstraintHandling { } if (Config.checkConstraintsSeparated) assert(!occursIn(bound), s"$param occurs in $bound") - val c1 = constraint.narrowBound(param, bound, isUpper) + val newBound = narrowedBound(param, bound, isUpper) + val c1 = constraint.updateEntry(param, newBound) (c1 eq constraint) || { constraint = c1 val TypeBounds(lo, hi) = constraint.entry(param) @@ -72,6 +80,20 @@ trait ConstraintHandling { } } + /** Narrow one of the bounds of type parameter `param` + * If `isUpper` is true, ensure that `param <: `bound`, otherwise ensure + * that `param >: bound`. + */ + def narrowedBound(param: PolyParam, bound: Type, isUpper: Boolean)(implicit ctx: Context): TypeBounds = { + val oldBounds @ TypeBounds(lo, hi) = constraint.nonParamBounds(param) + val saved = homogenizeArgs + homogenizeArgs = Config.alignArgsInAnd + try + if (isUpper) oldBounds.derivedTypeBounds(lo, hi & bound) + else oldBounds.derivedTypeBounds(lo | bound, hi) + finally homogenizeArgs = saved + } + protected def addUpperBound(param: PolyParam, bound: Type): Boolean = { def description = i"constraint $param <: $bound to\n$constraint" if (bound.isRef(defn.NothingClass) && ctx.typerState.isGlobalCommittable) { |