From 9e11e8bf3bfafd01e16e438c34352640cfdf3770 Mon Sep 17 00:00:00 2001 From: Guillaume Martres Date: Fri, 25 Nov 2022 18:15:32 +0100 Subject: [PATCH] Fix widening logic to keep instantiation within bounds 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. --- .../dotty/tools/dotc/core/ConstraintHandling.scala | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index 4ed01a5fbe0d..1d355daab25e 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -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`. @@ -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) = @@ -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