Skip to content

Commit 7f4af84

Browse files
committed
Polishings and comments
1 parent cdce995 commit 7f4af84

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@ trait ConstraintHandling {
551551
wideInst.dropRepeatedAnnot
552552
end widenInferred
553553

554+
/** Convert all toplevel union types in `tp` to hard unions */
554555
extension (tp: Type) private def hardenUnions(using Context): Type = tp.widen match
555556
case tp: AndType =>
556557
tp.derivedAndType(tp.tp1.hardenUnions, tp.tp2.hardenUnions)

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -519,7 +519,17 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
519519
// On the other hand, we could get a combinatorial explosion by applying such joins
520520
// recursively, so we do it only once. See i14870.scala as a test case, which would
521521
// loop for a very long time without the recursion brake.
522-
if res && !tp1.isSoft then hardenTypeVars(tp2)
522+
523+
if res && !tp1.isSoft then
524+
// We use a heuristic here where every toplevel type variable on the right hand side
525+
// is marked so that it converts all soft unions in its lower bound to hard unions
526+
// before it is instantiated. The reason is that the union might have come from
527+
// (decomposed and reconstituted0 `tp1`. But of cousre there might be fals positives
528+
// where we also treat unions that come from elsewhere as hard unions. Or the constraint
529+
// that created the union is ultimately thrown away, but the type variable will
530+
// stay marked. So it is a coarse measure to take. But it works in the obvious cases.
531+
hardenTypeVars(tp2)
532+
523533
res
524534

525535
case tp1: MatchType =>

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4507,8 +4507,6 @@ object Types {
45074507
final class TypeVar private(initOrigin: TypeParamRef, creatorState: TyperState | Null, val nestingLevel: Int) extends CachedProxyType with ValueType {
45084508
private var currentOrigin = initOrigin
45094509

4510-
var widenUnions = true
4511-
45124510
def origin: TypeParamRef = currentOrigin
45134511

45144512
/** Set origin to new parameter. Called if we merge two conflicting constraints.
@@ -4538,6 +4536,14 @@ object Types {
45384536
private[core] var owningState: WeakReference[TyperState] | Null =
45394537
if (creatorState == null) null else new WeakReference(creatorState)
45404538

4539+
private var myWidenUnions = true
4540+
4541+
/** If true, widen unions in lower bound before instantiating this variable to it.
4542+
* If false, convert unions in lower bound to hard unions instead
4543+
*/
4544+
private [core] def widenUnions = myWidenUnions
4545+
private[core] def widenUnions_=(x: Boolean): Unit = myWidenUnions = x
4546+
45414547
/** The instance type of this variable, or NoType if the variable is currently
45424548
* uninstantiated
45434549
*/

0 commit comments

Comments
 (0)