Skip to content

Commit cdc4eec

Browse files
committed
Polishings
- `ctx.harmonizeUnion(tp)` now becomes `tp.widenUnion`. - Same order of operations in local type inference of Namer and type variable instantiation. First, simplify, then widen, then widenUnion.
1 parent 1c8cfa4 commit cdc4eec

File tree

5 files changed

+35
-39
lines changed

5 files changed

+35
-39
lines changed

compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -258,21 +258,19 @@ trait ConstraintHandling {
258258
}
259259

260260
// First, solve the constraint.
261-
var inst = approximation(param, fromBelow)
261+
var inst = approximation(param, fromBelow).simplified
262262

263263
// Then, approximate by (1.) - (3.) and simplify as follows.
264264
// 1. If instance is from below and is a singleton type, yet
265265
// upper bound is not a singleton type, widen the instance.
266266
if (fromBelow && isSingleton(inst) && !isSingleton(upperBound))
267267
inst = inst.widen
268268

269-
inst = inst.simplified
270-
271269
// 2. If instance is from below and is a fully-defined union type, yet upper bound
272270
// is not a union type, approximate the union type from above by an intersection
273271
// of all common base types.
274-
if (fromBelow && isOrType(inst) && /*isFullyDefined(inst) &&*/ !isOrType(upperBound))
275-
inst = ctx.harmonizeUnion(inst)
272+
if (fromBelow && isOrType(inst) && !isOrType(upperBound))
273+
inst = inst.widenUnion
276274

277275
inst
278276
}

compiler/src/dotty/tools/dotc/core/TypeComparer.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
331331
else thirdTry(tp1, tp2)
332332
case tp1 @ OrType(tp11, tp12) =>
333333
def joinOK = tp2.dealias match {
334-
case tp12: HKApply =>
334+
case _: HKApply =>
335335
// If we apply the default algorithm for `A[X] | B[Y] <: C[Z]` where `C` is a
336336
// type parameter, we will instantiate `C` to `A` and then fail when comparing
337337
// with `B[Y]`. To do the right thing, we need to instantiate `C` to the

compiler/src/dotty/tools/dotc/core/TypeOps.scala

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -273,37 +273,6 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
273273
}
274274
}
275275

276-
/** Given a disjunction T1 | ... | Tn of types with potentially embedded
277-
* type variables, constrain type variables further if this eliminates
278-
* some of the branches of the disjunction. Do this also for disjunctions
279-
* embedded in intersections, as parents in refinements, and in recursive types.
280-
*
281-
* For instance, if `A` is an unconstrained type variable, then
282-
*
283-
* ArrayBuffer[Int] | ArrayBuffer[A]
284-
*
285-
* is approximated by constraining `A` to be =:= to `Int` and returning `ArrayBuffer[Int]`
286-
* instead of `ArrayBuffer[_ >: Int | A <: Int & A]`
287-
*/
288-
def harmonizeUnion(tp: Type): Type = tp match {
289-
case tp: OrType =>
290-
joinIfScala2(ctx.typeComparer.lub(harmonizeUnion(tp.tp1), harmonizeUnion(tp.tp2), canConstrain = true))
291-
case tp @ AndType(tp1, tp2) =>
292-
tp derived_& (harmonizeUnion(tp1), harmonizeUnion(tp2))
293-
case tp: RefinedType =>
294-
tp.derivedRefinedType(harmonizeUnion(tp.parent), tp.refinedName, tp.refinedInfo)
295-
case tp: RecType =>
296-
tp.rebind(harmonizeUnion(tp.parent))
297-
case _ =>
298-
tp
299-
}
300-
301-
/** Under -language:Scala2: Replace or-types with their joins */
302-
private def joinIfScala2(tp: Type) = tp match {
303-
case tp: OrType => tp.join
304-
case _ => tp
305-
}
306-
307276
/** Not currently needed:
308277
*
309278
def liftToRec(f: (Type, Type) => Type)(tp1: Type, tp2: Type)(implicit ctx: Context) = {

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,35 @@ object Types {
872872
case _ => this
873873
}
874874

875+
/** If this type contains embedded union types, replace them by their joins.
876+
* "Embedded" means: inside intersectons or recursive types, or in prefixes of refined types.
877+
* If an embedded union is found, we first try to simplify or eliminate it by
878+
* re-lubbing it while allowing type parameters to be constrained further.
879+
* Any remaining union types are replaced by their joins.
880+
*
881+
* For instance, if `A` is an unconstrained type variable, then
882+
*
883+
* ArrayBuffer[Int] | ArrayBuffer[A]
884+
*
885+
* is approximated by constraining `A` to be =:= to `Int` and returning `ArrayBuffer[Int]`
886+
* instead of `ArrayBuffer[_ >: Int | A <: Int & A]`
887+
*/
888+
def widenUnion(implicit ctx: Context): Type = this match {
889+
case OrType(tp1, tp2) =>
890+
ctx.typeComparer.lub(tp1.widenUnion, tp2.widenUnion, canConstrain = true) match {
891+
case union: OrType => union.join
892+
case res => res
893+
}
894+
case tp @ AndType(tp1, tp2) =>
895+
tp derived_& (tp1.widenUnion, tp2.widenUnion)
896+
case tp: RefinedType =>
897+
tp.derivedRefinedType(tp.parent.widenUnion, tp.refinedName, tp.refinedInfo)
898+
case tp: RecType =>
899+
tp.rebind(tp.parent.widenUnion)
900+
case _ =>
901+
this
902+
}
903+
875904
/** Eliminate anonymous classes */
876905
final def deAnonymize(implicit ctx: Context): Type = this match {
877906
case tp:TypeRef if tp.symbol.isAnonymousClass =>

compiler/src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1034,13 +1034,13 @@ class Namer { typer: Typer =>
10341034
// println(s"owner = ${sym.owner}, decls = ${sym.owner.info.decls.show}")
10351035
def isInline = sym.is(FinalOrInline, butNot = Method | Mutable)
10361036

1037-
// Widen rhs type and approximate `|' but keep ConstantTypes if
1037+
// Widen rhs type and eliminate `|' but keep ConstantTypes if
10381038
// definition is inline (i.e. final in Scala2) and keep module singleton types
10391039
// instead of widening to the underlying module class types.
10401040
def widenRhs(tp: Type): Type = tp.widenTermRefExpr match {
10411041
case ctp: ConstantType if isInline => ctp
10421042
case ref: TypeRef if ref.symbol.is(ModuleClass) => tp
1043-
case _ => ctx.harmonizeUnion(tp.widen)
1043+
case _ => tp.widen.widenUnion
10441044
}
10451045

10461046
// Replace aliases to Unit by Unit itself. If we leave the alias in

0 commit comments

Comments
 (0)