Skip to content

Commit f5d5435

Browse files
authored
Merge pull request scala#6155 from milessabin/topic/any-nothing-tests
More precise check for Any/Nothing, ruling out singleton types
2 parents e4a684f + ca8f97f commit f5d5435

File tree

3 files changed

+38
-12
lines changed

3 files changed

+38
-12
lines changed

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

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3252,12 +3252,14 @@ trait Types
32523252
* }}}
32533253
*/
32543254
def unifySimple = {
3255-
val sym = tp.typeSymbol
3256-
if (sym == NothingClass || sym == AnyClass) { // kind-polymorphic
3257-
// scala/bug#7126 if we register some type alias `T=Any`, we can later end
3258-
// with malformed types like `T[T]` during type inference in
3259-
// `handlePolymorphicCall`. No such problem if we register `Any`.
3260-
addBound(sym.tpe)
3255+
// scala/bug#7126 if we register some type alias `T=Any`, we can later end
3256+
// with malformed types like `T[T]` during type inference in
3257+
// `handlePolymorphicCall`. No such problem if we register `Any`.
3258+
if (typeIsNothing(tp)) { // kind-polymorphic
3259+
addBound(NothingTpe)
3260+
true
3261+
} else if(typeIsAny(tp)) { // kind-polymorphic
3262+
addBound(AnyTpe)
32613263
true
32623264
} else if (params.isEmpty) {
32633265
addBound(tp)
@@ -4852,8 +4854,23 @@ trait Types
48524854
private[scala] val boundsContainType = (bounds: TypeBounds, tp: Type) => bounds containsType tp
48534855
private[scala] val typeListIsEmpty = (ts: List[Type]) => ts.isEmpty
48544856
private[scala] val typeIsSubTypeOfSerializable = (tp: Type) => tp <:< SerializableTpe
4855-
private[scala] val typeIsNothing = (tp: Type) => tp.typeSymbolDirect eq NothingClass
4856-
private[scala] val typeIsAny = (tp: Type) => tp.typeSymbolDirect eq AnyClass
4857+
4858+
@tailrec
4859+
private[scala] final def typeIsNothing(tp: Type): Boolean =
4860+
tp.dealias match {
4861+
case PolyType(_, tp) => typeIsNothing(tp)
4862+
case TypeRef(_, NothingClass, _) => true
4863+
case _ => false
4864+
}
4865+
4866+
@tailrec
4867+
private[scala] final def typeIsAny(tp: Type): Boolean =
4868+
tp.dealias match {
4869+
case PolyType(_, tp) => typeIsAny(tp)
4870+
case TypeRef(_, AnyClass, _) => true
4871+
case _ => false
4872+
}
4873+
48574874
private[scala] val typeIsHigherKinded = (tp: Type) => tp.isHigherKinded
48584875

48594876
/** The maximum depth of type `tp` */

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,7 @@ private[internal] trait TypeConstraints {
127127
def addHiBound(tp: Type, isNumericBound: Boolean = false) {
128128
// My current test case only demonstrates the need to let Nothing through as
129129
// a lower bound, but I suspect the situation is symmetrical.
130-
val mustConsider = tp.typeSymbol match {
131-
case AnyClass => true
132-
case _ => !(hibounds contains tp)
133-
}
130+
val mustConsider = typeIsAny(tp) || !(hibounds contains tp)
134131
if (mustConsider) {
135132
checkWidening(tp)
136133
if (isNumericBound && isNumericValueType(tp)) {

test/junit/scala/reflect/internal/TypesTest.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,4 +313,16 @@ class TypesTest {
313313
assert(polyType(A => Bar(Int, A)) <:< _F && _F <:< polyType(A => Bar(Any, A)))
314314
}
315315
}
316+
317+
@Test
318+
def testAnyNothing(): Unit = {
319+
object Foo { val a: Any = 23 ; val n: Nothing = ??? }
320+
val aSym = typeOf[Foo.type].member(TermName("a"))
321+
val nSym = typeOf[Foo.type].member(TermName("n"))
322+
323+
assert(typeIsAny(AnyTpe))
324+
assert(typeIsNothing(NothingTpe))
325+
assert(!typeIsAny(SingleType(NoPrefix, aSym)))
326+
assert(!typeIsNothing(SingleType(NoPrefix, nSym)))
327+
}
316328
}

0 commit comments

Comments
 (0)