Skip to content

Commit

Permalink
Fix widening logic to keep instantiation within bounds
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
smarter committed Nov 25, 2022
1 parent c896c46 commit 9be9c62
Showing 1 changed file with 5 additions and 8 deletions.
13 changes: 5 additions & 8 deletions compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala
Original file line number Diff line number Diff line change
Expand Up @@ -624,8 +624,9 @@ trait ConstraintHandling {

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

def widenSingle(tp: Type) =
Expand All @@ -663,11 +664,7 @@ trait ConstraintHandling {
else
val widenedFromSingle = widenSingle(inst)
val widenedFromUnion = widenOr(widenedFromSingle)
val widened =
if (widenedFromUnion ne widenedFromSingle) && isTransparent(widenedFromUnion, traitOnly = false) then
widenedFromSingle
else
dropTransparentTraits(widenedFromUnion, bound)
val widened = dropTransparentTraits(widenedFromUnion, bound)
widenIrreducible(widened)

wideInst match
Expand Down

0 comments on commit 9be9c62

Please sign in to comment.