From e9b50e72d5d21c9a5ed0917dbeebed150c602537 Mon Sep 17 00:00:00 2001 From: Abel Nieto Date: Fri, 31 Aug 2018 15:31:27 -0400 Subject: [PATCH] Make reference types nullable again after erasure Before erasure, reference types are non-nullable, but after it they should be nullable again, because JVM types are nullable. This fixes tests/pos/i536 by changing the notion of a nullable type to take into consideration the current phase id. A similar thing is already done in TypeComparer in a different case: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/TypeComparer.scala#L676 --- compiler/src/dotty/tools/dotc/core/Definitions.scala | 12 ++++++++++-- .../src/dotty/tools/dotc/core/SymDenotations.scala | 8 ++++++-- tests/pos/i536.scala | 4 ++-- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala index c2547e5d3d15..7d859756b2c5 100644 --- a/compiler/src/dotty/tools/dotc/core/Definitions.scala +++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala @@ -967,8 +967,16 @@ class Definitions { name.length > prefix.length && name.drop(prefix.length).forall(_.isDigit)) - def isBottomClass(cls: Symbol) = cls == NothingClass - def isBottomType(tp: Type) = tp.derivesFrom(NothingClass) + def isBottomClass(cls: Symbol) = { + // After erasure, reference types become nullable again. + if (ctx.phaseId <= ctx.erasurePhase.id) cls == NothingClass + else cls == NothingClass || cls == NullClass + } + def isBottomType(tp: Type) = { + // After erasure, reference types become nullable again. + if (ctx.phaseId <= ctx.erasurePhase.id) tp.derivesFrom(NothingClass) + else tp.derivesFrom(NothingClass) || tp.derivesFrom(NullClass) + } /** Is a function class. * - FunctionN for N >= 0 diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index 4c08b7047005..3ab51c9099e5 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -681,8 +681,12 @@ object SymDenotations { } /** Is this symbol a class with nullable values? */ - final def isNullableClass(implicit ctx: Context): Boolean = - symbol == defn.NullClass || symbol == defn.AnyRefAlias || symbol == defn.AnyClass + final def isNullableClass(implicit ctx: Context): Boolean = { + // After erasure, reference types become nullable again. + if (ctx.phaseId <= ctx.erasurePhase.id) symbol == defn.NullClass || symbol == defn.AnyRefAlias || symbol == defn.AnyClass + else isClass && !isValueClass && !is(ModuleClass) && symbol != defn.NothingClass + } + /** Is this definition accessible as a member of tree with type `pre`? * @param pre The type of the tree from which the selection is made diff --git a/tests/pos/i536.scala b/tests/pos/i536.scala index 49d8f6058be3..1ea41d9e9da9 100644 --- a/tests/pos/i536.scala +++ b/tests/pos/i536.scala @@ -2,11 +2,11 @@ trait Comp[T] trait Coll[T] class C extends Comp[C] object Max { - def max[M <: Comp[_ >: M]](x: Coll[_ <: M] | Null): M = ??? + def max[M <: Comp[_ >: M]](x: Coll[_ <: M]): M = ??? def max[M](x: Coll[_ <: M], cmp: Object): M = ??? val xs: Coll[C] = ??? val m1 = max(xs) - val m2 = max(null) + val m2 = max(???) java.util.Collections.max(null) }