Skip to content

Commit 1b3a52c

Browse files
authored
Fix widening logic to keep instantiation within bounds (#16417)
Before this commit, if `Config.checkConstraintsSatisfiable` was set to `true`, then tests/pos/cls.scala would fail on `val b1` with: Y is constrained to be >: Matchable but attempted to instantiate it to Int | String This happens because when `widenInferred` widens a union, it constrains the upper-bound of the parameter being instantiated to be a subtype of that union (`tpw <:< bound`). This is usually fine, but if `isTransparent` is true, we'll return the original unwidened type, which is now out of bounds. To avoid this inconsistency, the `isTransparent` check is now moved before the subtype check that updates the bounds.
2 parents beb17fd + 9e11e8b commit 1b3a52c

File tree

1 file changed

+5
-8
lines changed

1 file changed

+5
-8
lines changed

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

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -624,8 +624,9 @@ trait ConstraintHandling {
624624

625625
/** Widen inferred type `inst` with upper `bound`, according to the following rules:
626626
* 1. If `inst` is a singleton type, or a union containing some singleton types,
627-
* widen (all) the singleton type(s), provided the result is a subtype of `bound`.
628-
* (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint)
627+
* widen (all) the singleton type(s), provided the result is a subtype of `bound`
628+
* (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint) and
629+
* is not transparent according to `isTransparent`.
629630
* 2a. If `inst` is a union type and `widenUnions` is true, approximate the union type
630631
* from above by an intersection of all common base types, provided the result
631632
* is a subtype of `bound`.
@@ -647,7 +648,7 @@ trait ConstraintHandling {
647648
def widenOr(tp: Type) =
648649
if widenUnions then
649650
val tpw = tp.widenUnion
650-
if (tpw ne tp) && (tpw <:< bound) then tpw else tp
651+
if (tpw ne tp) && !isTransparent(tpw, traitOnly = false) && (tpw <:< bound) then tpw else tp
651652
else tp.hardenUnions
652653

653654
def widenSingle(tp: Type) =
@@ -663,11 +664,7 @@ trait ConstraintHandling {
663664
else
664665
val widenedFromSingle = widenSingle(inst)
665666
val widenedFromUnion = widenOr(widenedFromSingle)
666-
val widened =
667-
if (widenedFromUnion ne widenedFromSingle) && isTransparent(widenedFromUnion, traitOnly = false) then
668-
widenedFromSingle
669-
else
670-
dropTransparentTraits(widenedFromUnion, bound)
667+
val widened = dropTransparentTraits(widenedFromUnion, bound)
671668
widenIrreducible(widened)
672669

673670
wideInst match

0 commit comments

Comments
 (0)