From 322bcfef33834eb1e57c874c5a745faf65e1b8bc Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 30 Jan 2016 20:22:41 +0100 Subject: Move realizability logic from Types to TypeOps. Types is already big enough. --- src/dotty/tools/dotc/core/SymDenotations.scala | 2 +- src/dotty/tools/dotc/core/TypeOps.scala | 44 ++++++++++++++++++++++++-- src/dotty/tools/dotc/core/Types.scala | 39 ----------------------- src/dotty/tools/dotc/typer/Checking.scala | 4 +-- 4 files changed, 45 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index fa199ab53..ba8dde62d 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -525,7 +525,7 @@ object SymDenotations { /** 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 + val isRealizable = !is(Lazy, butNot = Module) || ctx.realizability(info) == TypeOps.Realizable isRealizable && { setFlag(Stable); true } } diff --git a/src/dotty/tools/dotc/core/TypeOps.scala b/src/dotty/tools/dotc/core/TypeOps.scala index 34febf3be..26ce4ebf8 100644 --- a/src/dotty/tools/dotc/core/TypeOps.scala +++ b/src/dotty/tools/dotc/core/TypeOps.scala @@ -3,7 +3,7 @@ package dotc package core import Contexts._, Types._, Symbols._, Names._, Flags._, Scopes._ -import SymDenotations._, Denotations.Denotation +import SymDenotations._, Denotations.SingleDenotation import config.Printers._ import util.Positions._ import Decorators._ @@ -14,6 +14,7 @@ import collection.mutable import ast.tpd._ trait TypeOps { this: Context => // TODO: Make standalone object. + import TypeOps._ /** The type `tp` as seen from prefix `pre` and owner `cls`. See the spec * for what this means. Called very often, so the code is optimized heavily. @@ -427,10 +428,36 @@ trait TypeOps { this: Context => // TODO: Make standalone object. case OrType(l, r) => DNF(l) | DNF(r) case tp => - TypeOps.emptyDNF + emptyDNF } } + /** The realizability status of given type `tp`*/ + def realizability(tp: Type): Realizability = tp.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 + case tp: TypeProxy => isConcrete(tp.underlying) + case tp: AndOrType => isConcrete(tp.tp1) && isConcrete(tp.tp2) + case _ => false + } + 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 + } + } + } + private def enterArgBinding(formal: Symbol, info: Type, cls: ClassSymbol, decls: Scope) = { val lazyInfo = new LazyType { // needed so we do not force `formal`. def complete(denot: SymDenotation)(implicit ctx: Context): Unit = { @@ -650,4 +677,17 @@ trait TypeOps { this: Context => // TODO: Make standalone object. object TypeOps { val emptyDNF = (Nil, Set[Name]()) :: Nil @sharable var track = false // !!!DEBUG + + // ----- 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}") } diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index 0a5050148..8595da640 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -127,32 +127,6 @@ object Types { false } - /** 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 - case tp: TypeProxy => isConcrete(tp.underlying) - case tp: AndOrType => isConcrete(tp.tp1) && isConcrete(tp.tp2) - case _ => false - } - 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`? * Implemented like `isRef`, but follows more types: all type proxies as well as and- and or-types */ @@ -3436,19 +3410,6 @@ 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) diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index 3a55352fd..d333efa33 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -324,8 +324,8 @@ trait Checking { /** Check that type `tp` is realizable. */ def checkRealizable(tp: Type, pos: Position)(implicit ctx: Context): Unit = { - val rstatus = tp.realizability - if (rstatus ne Realizable) { + val rstatus = ctx.realizability(tp) + if (rstatus ne TypeOps.Realizable) { def msg = d"$tp is not a legal path since it ${rstatus.msg}" if (ctx.scala2Mode) ctx.migrationWarning(msg, pos) else ctx.error(msg, pos) } -- cgit v1.2.3