Skip to content

Commit 454e301

Browse files
committed
Replace useNecessaryEither by necessaryConstraintsOnly
The name was misleading since it was also used in approximateWildcards, the new getter also returns true in GADT mode instead of having `either` manually check both the mode and the variable (this does not affect the behavior of approximateWildcards since GADT constraints never involve wildcards).
1 parent eb69870 commit 454e301

File tree

1 file changed

+26
-18
lines changed

1 file changed

+26
-18
lines changed

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

Lines changed: 26 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,23 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
6363
private var myInstance: TypeComparer = this
6464
def currentInstance: TypeComparer = myInstance
6565

66-
private var useNecessaryEither = false
66+
private var myNecessaryConstraintsOnly = false
67+
/** When collecting the constraints needed for a particular subtyping
68+
* judgment to be true, we sometimes need to approximate the constraint
69+
* set (see `TypeComparer#either` for example).
70+
*
71+
* Normally, this means adding extra constraints which may not be necessary
72+
* for the subtyping judgment to be true, but if this variable is set to true
73+
* we will instead under-approximate and keep only the constraints that must
74+
* always be present for the subtyping judgment to hold.
75+
*
76+
* This is needed for GADT bounds inference to be sound, but it is also used
77+
* when constraining a method call based on its expected type to avoid adding
78+
* constraints that would later prevent us from typechecking method
79+
* arguments, see or-inf.scala and and-inf.scala for examples.
80+
*/
81+
protected def necessaryConstraintsOnly(using Context) =
82+
ctx.mode.is(Mode.GadtConstraintInference) || myNecessaryConstraintsOnly
6783

6884
/** Is a subtype check in progress? In that case we may not
6985
* permanently instantiate type variables, because the corresponding
@@ -134,20 +150,20 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
134150
}
135151

136152
def necessarySubType(tp1: Type, tp2: Type): Boolean =
137-
val saved = useNecessaryEither
138-
useNecessaryEither = true
153+
val saved = myNecessaryConstraintsOnly
154+
myNecessaryConstraintsOnly = true
139155
try topLevelSubType(tp1, tp2)
140-
finally useNecessaryEither = saved
156+
finally myNecessaryConstraintsOnly = saved
141157

142158
/** Use avoidance to get rid of wildcards in constraint bounds if
143159
* we are doing a necessary comparison, or the mode is TypeVarsMissContext.
144160
* The idea is that under either of these conditions we are not interested
145161
* in creating a fresh type variable to replace the wildcard. I verified
146162
* that several tests break if one or the other part of the disjunction is dropped.
147-
* (for instance, i12677.scala demands `useNecessaryEither` in the condition)
163+
* (for instance, i12677.scala demands `necessaryConstraintsOnly` in the condition)
148164
*/
149165
override protected def approximateWildcards: Boolean =
150-
useNecessaryEither || ctx.mode.is(Mode.TypevarsMissContext)
166+
necessaryConstraintsOnly || ctx.mode.is(Mode.TypevarsMissContext)
151167

152168
def testSubType(tp1: Type, tp2: Type): CompareResult =
153169
GADTused = false
@@ -1580,24 +1596,16 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
15801596

15811597
/** Returns true iff the result of evaluating either `op1` or `op2` is true and approximates resulting constraints.
15821598
*
1583-
* If we're inferring GADT bounds or constraining a method based on its
1584-
* expected type, we infer only the _necessary_ constraints, this means we
1585-
* keep the smaller constraint if any, or no constraint at all. This is
1586-
* necessary for GADT bounds inference to be sound. When constraining a
1587-
* method, this avoid committing of constraints that would later prevent us
1588-
* from typechecking method arguments, see or-inf.scala and and-inf.scala for
1589-
* examples.
1599+
* If `necessaryConstraintsOnly` is true, we keep the smaller constraint if
1600+
* any, or no constraint at all.
15901601
*
15911602
* Otherwise, we infer _sufficient_ constraints: we try to keep the smaller of
15921603
* the two constraints, but if never is smaller than the other, we just pick
15931604
* the first one.
1594-
*
1595-
* @see [[necessaryEither]] for the GADT / result type case
1596-
* @see [[sufficientEither]] for the normal case
15971605
*/
15981606
protected def either(op1: => Boolean, op2: => Boolean): Boolean =
15991607
Stats.record("TypeComparer.either")
1600-
if ctx.mode.is(Mode.GadtConstraintInference) || useNecessaryEither then
1608+
if necessaryConstraintsOnly then
16011609
necessaryEither(op1, op2)
16021610
else
16031611
sufficientEither(op1, op2)
@@ -1673,7 +1681,7 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
16731681
* T1 & T2 <:< T3
16741682
* T1 <:< T2 | T3
16751683
*
1676-
* Unlike [[sufficientEither]], this method is used in GADTConstraintInference mode, when we are attempting
1684+
* But this method is used when `useNecessaryEither` is true, like when we are attempting
16771685
* to infer GADT constraints that necessarily follow from the subtyping relationship. For instance, if we have
16781686
*
16791687
* enum Expr[T] {

0 commit comments

Comments
 (0)