Skip to content

Commit ee5b81e

Browse files
committed
WIP SI-5103 avoid widening TypeVar <: Singleton
Deriving this from type param upper bound in addition (as before) to constraints that we encounter scala> def stable[T <: 1](x: T): T = x stable: [T <: 1](x: T)T scala> stable(1) res0: 1 = 1 scala> stable(2) <console>:9: error: inferred type arguments [2] do not conform to method stable's type parameter bounds [T <: 1] stable(2) ^ <console>:9: error: type mismatch; found : Int(2) required: T stable(2) ^ scala> def stable[T <: Singleton](x: T): T = x stable: [T <: Singleton](x: T)T scala> val x: Int = 2 x: Int = 2 scala> val y: x.type = x y: x.type = 2 scala> stable(y) res3: x.type = 2
1 parent 1fca48c commit ee5b81e

File tree

2 files changed

+17
-8
lines changed

2 files changed

+17
-8
lines changed

src/reflect/scala/reflect/internal/Types.scala

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2799,6 +2799,8 @@ trait Types
27992799
value
28002800
}
28012801

2802+
def precludesWidening(tp: Type) = tp.isStable || tp.contains(SingletonClass)
2803+
28022804
/** Create a new TypeConstraint based on the given symbol.
28032805
*/
28042806
private def deriveConstraint(tparam: Symbol): TypeConstraint = {
@@ -2807,18 +2809,24 @@ trait Types
28072809
* See SI-5359.
28082810
*/
28092811
val bounds = tparam.info.bounds
2812+
28102813
/* We can seed the type constraint with the type parameter
28112814
* bounds as long as the types are concrete. This should lower
28122815
* the complexity of the search even if it doesn't improve
28132816
* any results.
28142817
*/
2815-
if (propagateParameterBoundsToTypeVars) {
2816-
val exclude = bounds.isEmptyBounds || (bounds exists typeIsNonClassType)
2818+
val constr =
2819+
if (propagateParameterBoundsToTypeVars) {
2820+
val exclude = bounds.isEmptyBounds || (bounds exists typeIsNonClassType)
28172821

2818-
if (exclude) new TypeConstraint
2819-
else TypeVar.trace("constraint", "For " + tparam.fullLocationString)(new TypeConstraint(bounds))
2820-
}
2821-
else new TypeConstraint
2822+
if (exclude) new TypeConstraint
2823+
else TypeVar.trace("constraint", "For " + tparam.fullLocationString)(new TypeConstraint(bounds))
2824+
}
2825+
else new TypeConstraint
2826+
2827+
if (precludesWidening(bounds.hi)) constr.stopWidening()
2828+
2829+
constr
28222830
}
28232831
def untouchable(tparam: Symbol): TypeVar = createTypeVar(tparam, untouchable = true)
28242832
def apply(tparam: Symbol): TypeVar = createTypeVar(tparam, untouchable = false)

src/reflect/scala/reflect/internal/tpe/TypeConstraints.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ private[internal] trait TypeConstraints {
9393
def loBounds: List[Type] = if (numlo == NoType) lobounds else numlo :: lobounds
9494
def hiBounds: List[Type] = if (numhi == NoType) hibounds else numhi :: hibounds
9595
def avoidWiden: Boolean = avoidWidening
96+
def stopWidening(): Unit = avoidWidening = true
9697

9798
def addLoBound(tp: Type, isNumericBound: Boolean = false) {
9899
// For some reason which is still a bit fuzzy, we must let Nothing through as
@@ -117,9 +118,9 @@ private[internal] trait TypeConstraints {
117118
}
118119

119120
def checkWidening(tp: Type) {
120-
if(tp.isStable) avoidWidening = true
121+
if (TypeVar.precludesWidening(tp)) stopWidening()
121122
else tp match {
122-
case HasTypeMember(_, _) => avoidWidening = true
123+
case HasTypeMember(_, _) => stopWidening()
123124
case _ =>
124125
}
125126
}

0 commit comments

Comments
 (0)