aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-01-30 20:01:14 +0100
committerMartin Odersky <odersky@gmail.com>2016-02-09 09:40:52 +0100
commit7ccd02c2cd23e4187f3e3a378973704cecd6459a (patch)
treec1efbbb4b0f73cc94b83c011bbcdc1b34e34ff9b /src/dotty/tools/dotc/core
parent1b7745e5f9c0e251436b33247133f3810838cf12 (diff)
downloaddotty-7ccd02c2cd23e4187f3e3a378973704cecd6459a.tar.gz
dotty-7ccd02c2cd23e4187f3e3a378973704cecd6459a.tar.bz2
dotty-7ccd02c2cd23e4187f3e3a378973704cecd6459a.zip
Realizability refactoring
Distinguish between isStable and isRealizable. Issue migration warnings for realizibility failures. Provide error diagnostics why something is not realizable.
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala2
-rw-r--r--src/dotty/tools/dotc/core/SymDenotations.scala16
-rw-r--r--src/dotty/tools/dotc/core/Types.scala40
3 files changed, 39 insertions, 19 deletions
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 42d06c2ab..8c9db3a5c 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -300,7 +300,7 @@ object Flags {
*/
final val Abstract = commonFlag(23, "abstract")
- /** Method is assumed to be stable */
+ /** Lazy val or method is known or assumed to be stable and realizable */
final val Stable = termFlag(24, "<stable>")
/** A case parameter accessor */
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala
index 3a66e10d4..fa199ab53 100644
--- a/src/dotty/tools/dotc/core/SymDenotations.scala
+++ b/src/dotty/tools/dotc/core/SymDenotations.scala
@@ -519,15 +519,15 @@ object SymDenotations {
)
/** Is this a denotation of a stable term (or an arbitrary type)? */
- final def isStable(implicit ctx: Context) = {
- val isUnstable =
- (this is UnstableValue) ||
- is(Lazy, butNot = Module) && !info.isRealizable && !hasAnnotation(defn.UncheckedStableAnnot)
- (this is Stable) || isType || {
- if (isUnstable) false
- else { setFlag(Stable); true }
+ final def isStable(implicit ctx: Context) =
+ isType || !is(UnstableValue, butNot = Stable)
+
+ /** Is this a denotation of a realizable term (or an arbitrary type)? */
+ final def isRealizable(implicit ctx: Context) =
+ is(Stable) || isType || {
+ val isRealizable = !is(Lazy, butNot = Module) || info.realizability == Realizable
+ isRealizable && { setFlag(Stable); true }
}
- }
/** Is this a "real" method? A real method is a method which is:
* - not an accessor
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 7e8a11e5b..0a5050148 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -127,10 +127,12 @@ object Types {
false
}
- /** Is this type realizable in all contexts? */
- def isRealizable(implicit ctx: Context): Boolean = dealias match {
- case tp: TermRef => tp.symbol.isStable
- case tp: SingletonType => true
+ /** The realizibility status of this type */
+ def realizability(implicit ctx: Context): Realizability = dealias match {
+ case tp: TermRef =>
+ if (tp.symbol.isRealizable) Realizable else NotStable
+ case _: SingletonType | NoPrefix =>
+ Realizable
case tp =>
def isConcrete(tp: Type): Boolean = tp.dealias match {
case tp: TypeRef => tp.symbol.isClass
@@ -138,12 +140,17 @@ object Types {
case tp: AndOrType => isConcrete(tp.tp1) && isConcrete(tp.tp2)
case _ => false
}
- isConcrete(tp) &&
- tp.nonClassTypeMembers.forall { m =>
- val bounds = m.info.bounds
- bounds.lo <:< bounds.hi
- } ||
- ctx.scala2Mode
+ if (!isConcrete(tp)) NotConcrete
+ else {
+ def hasBadBounds(mbr: SingleDenotation) = {
+ val bounds = mbr.info.bounds
+ !(bounds.lo <:< bounds.hi)
+ }
+ tp.nonClassTypeMembers.find(hasBadBounds) match {
+ case Some(mbr) => new HasProblemBounds(mbr)
+ case _ => Realizable
+ }
+ }
}
/** Does this type refer exactly to class symbol `sym`, instead of to a subclass of `sym`?
@@ -3429,6 +3436,19 @@ object Types {
def apply(pre: Type, name: Name)(implicit ctx: Context): Boolean = true
}
+ // ----- Realizibility Status -----------------------------------------------------
+
+ abstract class Realizability(val msg: String)
+
+ object Realizable extends Realizability("")
+
+ object NotConcrete extends Realizability("is not a concrete type")
+
+ object NotStable extends Realizability("is not a stable reference")
+
+ class HasProblemBounds(mbr: SingleDenotation)(implicit ctx: Context)
+ extends Realizability(i"has a member $mbr with possibly empty bounds ${mbr.info.bounds.lo} .. ${mbr.info.bounds.hi}")
+
// ----- Exceptions -------------------------------------------------------------
class TypeError(msg: String) extends Exception(msg)