Skip to content

Commit d2a6201

Browse files
committed
Replace GadtConstraint#isEmpty by isNarrowing
isEmpty is pointless since it is always false if we are inside a polymorphic method. isNarrowing computes whether the constraint actually has tigher bounds for a type variable than the original bounds.
1 parent 80ec523 commit d2a6201

File tree

2 files changed

+29
-21
lines changed

2 files changed

+29
-21
lines changed

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

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ sealed abstract class GadtConstraint extends Showable {
4343
*/
4444
def contains(sym: Symbol)(using Context): Boolean
4545

46-
def isEmpty: Boolean
47-
final def nonEmpty: Boolean = !isEmpty
46+
/** GADT constraint narrows bounds of at least one variable */
47+
def isNarrowing: Boolean
4848

4949
/** See [[ConstraintHandling.approximation]] */
5050
def approximation(sym: Symbol, fromBelow: Boolean)(using Context): Type
@@ -61,13 +61,15 @@ final class ProperGadtConstraint private(
6161
private var myConstraint: Constraint,
6262
private var mapping: SimpleIdentityMap[Symbol, TypeVar],
6363
private var reverseMapping: SimpleIdentityMap[TypeParamRef, Symbol],
64+
private var wasConstrained: Boolean
6465
) extends GadtConstraint with ConstraintHandling {
6566
import dotty.tools.dotc.config.Printers.{gadts, gadtsConstr}
6667

6768
def this() = this(
6869
myConstraint = new OrderingConstraint(SimpleIdentityMap.empty, SimpleIdentityMap.empty, SimpleIdentityMap.empty),
6970
mapping = SimpleIdentityMap.empty,
70-
reverseMapping = SimpleIdentityMap.empty
71+
reverseMapping = SimpleIdentityMap.empty,
72+
wasConstrained = false
7173
)
7274

7375
/** Exposes ConstraintHandling.subsumes */
@@ -149,20 +151,24 @@ final class ProperGadtConstraint private(
149151
if (ntTvar ne null) stripInternalTypeVar(ntTvar) else bound
150152
case _ => bound
151153
}
152-
(
153-
internalizedBound match {
154-
case boundTvar: TypeVar =>
155-
if (boundTvar eq symTvar) true
156-
else if (isUpper) addLess(symTvar.origin, boundTvar.origin)
157-
else addLess(boundTvar.origin, symTvar.origin)
158-
case bound =>
159-
addBoundTransitively(symTvar.origin, bound, isUpper)
160-
}
161-
).showing({
154+
155+
val saved = constraint
156+
val result = internalizedBound match
157+
case boundTvar: TypeVar =>
158+
if (boundTvar eq symTvar) true
159+
else if (isUpper) addLess(symTvar.origin, boundTvar.origin)
160+
else addLess(boundTvar.origin, symTvar.origin)
161+
case bound =>
162+
addBoundTransitively(symTvar.origin, bound, isUpper)
163+
164+
gadts.println {
162165
val descr = if (isUpper) "upper" else "lower"
163166
val op = if (isUpper) "<:" else ">:"
164167
i"adding $descr bound $sym $op $bound = $result"
165-
}, gadts)
168+
}
169+
170+
if constraint ne saved then wasConstrained = true
171+
result
166172
}
167173

168174
override def isLess(sym1: Symbol, sym2: Symbol)(using Context): Boolean =
@@ -193,6 +199,8 @@ final class ProperGadtConstraint private(
193199

194200
override def contains(sym: Symbol)(using Context): Boolean = mapping(sym) ne null
195201

202+
def isNarrowing: Boolean = wasConstrained
203+
196204
override def approximation(sym: Symbol, fromBelow: Boolean)(using Context): Type = {
197205
val res = approximation(tvarOrError(sym).origin, fromBelow = fromBelow)
198206
gadts.println(i"approximating $sym ~> $res")
@@ -202,19 +210,19 @@ final class ProperGadtConstraint private(
202210
override def fresh: GadtConstraint = new ProperGadtConstraint(
203211
myConstraint,
204212
mapping,
205-
reverseMapping
213+
reverseMapping,
214+
wasConstrained
206215
)
207216

208217
def restore(other: GadtConstraint): Unit = other match {
209218
case other: ProperGadtConstraint =>
210219
this.myConstraint = other.myConstraint
211220
this.mapping = other.mapping
212221
this.reverseMapping = other.reverseMapping
222+
this.wasConstrained = other.wasConstrained
213223
case _ => ;
214224
}
215225

216-
override def isEmpty: Boolean = mapping.size == 0
217-
218226
// ---- Protected/internal -----------------------------------------------
219227

220228
override protected def constraint = myConstraint
@@ -293,7 +301,7 @@ final class ProperGadtConstraint private(
293301

294302
override def isLess(sym1: Symbol, sym2: Symbol)(using Context): Boolean = unsupported("EmptyGadtConstraint.isLess")
295303

296-
override def isEmpty: Boolean = true
304+
override def isNarrowing: Boolean = false
297305

298306
override def contains(sym: Symbol)(using Context) = false
299307

@@ -304,7 +312,7 @@ final class ProperGadtConstraint private(
304312

305313
override def fresh = new ProperGadtConstraint
306314
override def restore(other: GadtConstraint): Unit =
307-
if (!other.isEmpty) sys.error("cannot restore a non-empty GADTMap")
315+
assert(!other.isNarrowing, "cannot restore a non-empty GADTMap")
308316

309317
override def debugBoundsDescription(using Context): String = "EmptyGadtConstraint"
310318

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,7 +1662,7 @@ class Typer extends Namer
16621662
val pat1 = indexPattern(tree).transform(pat)
16631663
val guard1 = typedExpr(tree.guard, defn.BooleanType)
16641664
var body1 = ensureNoLocalRefs(typedExpr(tree.body, pt1), pt1, ctx.scope.toList)
1665-
if ctx.gadt.nonEmpty then
1665+
if ctx.gadt.isNarrowing then
16661666
// Store GADT constraint to later retrieve it (in PostTyper, for now).
16671667
// GADT constraints are necessary to correctly check bounds of type app,
16681668
// see tests/pos/i12226 and issue #12226. It might be possible that this
@@ -3824,7 +3824,7 @@ class Typer extends Namer
38243824

38253825
pt match
38263826
case pt: SelectionProto =>
3827-
if ctx.gadt.nonEmpty then
3827+
if ctx.gadt.isNarrowing then
38283828
// try GADT approximation if we're trying to select a member
38293829
// Member lookup cannot take GADTs into account b/c of cache, so we
38303830
// approximate types based on GADT constraints instead. For an example,

0 commit comments

Comments
 (0)