Skip to content

Commit 73eb00b

Browse files
committed
Combine new widenInferred scheme with singleton unions
1 parent d95a239 commit 73eb00b

File tree

3 files changed

+27
-38
lines changed

3 files changed

+27
-38
lines changed

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

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -272,50 +272,24 @@ trait ConstraintHandling[AbstractContext] {
272272
}
273273
}
274274

275-
/** Widen inferred type `tp` with upper bound `bound`, according to the following rules:
276-
* 1. If `tp` is a singleton type, yet `bound` is not a singleton type, nor a subtype
277-
* of `scala.Singleton`, widen `tp`.
278-
* 2. If `tp` is a union type, yet upper bound is not a union type,
279-
* approximate the union type from above by an intersection of all common base types.
275+
/** Widen inferred type `inst` with upper `bound`, according to the following rules:
276+
* 1. If `inst` is a singleton type, or a union containing some singleton types,
277+
* widen (all) the singleton type(s), provied the result is a subtype of `bound`
278+
* (i.e. `inst.widenSingletons <:< bound` succeeds with satisfiable constraint).
279+
* 2. If `inst` is a union type, approximate the union type from above by an intersection
280+
* of all common base types, provied the result is a subtype of `bound`.
280281
*
281282
* At this point we also drop the @Repeated annotation to avoid inferring type arguments with it,
282283
* as those could leak the annotation to users (see run/inferred-repeated-result).
283284
*/
284-
def widenInferred(tp: Type, bound: Type)(implicit actx: AbstractContext): Type = {
285-
def isMultiSingleton(tp: Type): Boolean = tp.stripAnnots match {
286-
case tp: SingletonType => true
287-
case AndType(tp1, tp2) => isMultiSingleton(tp1) | isMultiSingleton(tp2)
288-
case OrType(tp1, tp2) => isMultiSingleton(tp1) & isMultiSingleton(tp2)
289-
case tp: TypeRef => isMultiSingleton(tp.info.hiBound)
290-
case tp: TypeVar => isMultiSingleton(tp.underlying)
291-
case tp: TypeParamRef => isMultiSingleton(bounds(tp).hi)
292-
case _ => false
293-
}
294-
def isOrType(tp: Type): Boolean = tp.dealias match {
295-
case tp: OrType => true
296-
case tp: RefinedOrRecType => isOrType(tp.parent)
297-
case AndType(tp1, tp2) => isOrType(tp1) | isOrType(tp2)
298-
case WildcardType(bounds: TypeBounds) => isOrType(bounds.hi)
299-
case _ => false
300-
}
301-
def widenOr(tp: Type) =
302-
if (isOrType(tp) && !isOrType(bound)) tp.widenUnion
303-
else tp
304-
def widenSingle(tp: Type) =
305-
if (isMultiSingleton(tp) && !isMultiSingleton(bound) &&
306-
!isSubTypeWhenFrozen(bound, defn.SingletonType)) tp.widen
307-
else tp
308-
widenOr(widenSingle(tp)).dropRepeatedAnnot
309-
}
310-
311-
def widenInferred2(inst: Type, param: TypeParamRef)(implicit actx: AbstractContext): Type = {
285+
def widenInferred(inst: Type, bound: Type)(implicit actx: AbstractContext): Type = {
312286
def widenSingle(tp: Type) = {
313-
val tpw = tp.widen
314-
if ((tpw ne tp) && tpw <:< param) tpw else tp
287+
val tpw = tp.widenSingletons
288+
if ((tpw ne tp) && tpw <:< bound) tpw else tp
315289
}
316290
def widenOr(tp: Type) = {
317291
val tpw = tp.widenUnion
318-
if ((tpw ne tp) && tpw <:< param) tpw else tp
292+
if ((tpw ne tp) && tpw <:< bound) tpw else tp
319293
}
320294
widenOr(widenSingle(inst)).dropRepeatedAnnot
321295
}
@@ -328,7 +302,7 @@ trait ConstraintHandling[AbstractContext] {
328302
*/
329303
def instanceType(param: TypeParamRef, fromBelow: Boolean)(implicit actx: AbstractContext): Type = {
330304
val inst = approximation(param, fromBelow).simplified
331-
if (fromBelow) widenInferred2(inst, /*constraint.fullUpperBound*/(param)) else inst
305+
if (fromBelow) widenInferred(inst, param) else inst
332306
}
333307

334308
/** Constraint `c1` subsumes constraint `c2`, if under `c2` as constraint we have

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1525,7 +1525,7 @@ class TypeComparer(initctx: Context) extends ConstraintHandling[AbsentContext] {
15251525
/** The greatest lower bound of a list types */
15261526
final def glb(tps: List[Type]): Type = ((AnyType: Type) /: tps)(glb)
15271527

1528-
def widenInUnions(implicit ctx: Context): Boolean = ctx.scala2Mode || ctx.erasedTypes || true
1528+
def widenInUnions(implicit ctx: Context): Boolean = ctx.scala2Mode || ctx.erasedTypes
15291529

15301530
/** The least upper bound of two types
15311531
* @param canConstrain If true, new constraints might be added to simplify the lub.

tests/pos/i6288.scala

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
object A {
2+
opaque type T = 3
3+
object T {
4+
val x: T = 3
5+
}
6+
}
7+
8+
object O {
9+
val x = 3
10+
opaque type T = x.type
11+
object T {
12+
def wrap(a: x.type): T = a // Error
13+
def unwrap(a: T): x.type = a // OK
14+
}
15+
}

0 commit comments

Comments
 (0)