diff options
author | Martin Odersky <odersky@gmail.com> | 2014-05-28 11:27:11 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2014-05-30 15:43:02 +0200 |
commit | c2175ec910165308e81c48bd8ca8910c50862be4 (patch) | |
tree | 82af4c43d1167cc0d897d31b1afa855c068f856e /src/dotty/tools/dotc/core/SymDenotations.scala | |
parent | 70e785f5d8a583dae127dadf4d9add70bdea71f7 (diff) | |
download | dotty-c2175ec910165308e81c48bd8ca8910c50862be4.tar.gz dotty-c2175ec910165308e81c48bd8ca8910c50862be4.tar.bz2 dotty-c2175ec910165308e81c48bd8ca8910c50862be4.zip |
Avoid classtype checking for refinements.
In a refinement type T { R } we do not need T to be a class. But analyzing the refeinement
type will create a temporary class type. This refinement class has to be treated specially in
what concerns parent types.
Diffstat (limited to 'src/dotty/tools/dotc/core/SymDenotations.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 498f912f9..606966be9 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -321,6 +321,9 @@ object SymDenotations { final def isAnonymousClass(implicit ctx: Context): Boolean = initial.asSymDenotation.name startsWith tpnme.ANON_CLASS + final def isRefinementClass(implicit ctx: Context): Boolean = + name.decode == tpnme.REFINE_CLASS + /** Is this symbol a package object or its module class? */ def isPackageObject(implicit ctx: Context): Boolean = { val poName = if (isType) nme.PACKAGE_CLS else nme.PACKAGE @@ -701,6 +704,54 @@ object SymDenotations { else Iterator.empty + /** The symbol overriding this symbol in given subclass `ofclazz`. + * + * @param ofclazz is a subclass of this symbol's owner + */ + final def overridingSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol = + if (canMatchInheritedSymbols) matchingSymbol(inClass, inClass.thisType) + else NoSymbol + + /** If false, this symbol cannot possibly participate in an override, + * either as overrider or overridee. For internal use; you should consult + * with isOverridingSymbol. This is used by isOverridingSymbol to escape + * the recursive knot. + */ + private def canMatchInheritedSymbols = ( + owner.isClass + && !this.isClass + && !this.isConstructor + ) + + /** The symbol accessed by a super in the definition of this symbol when + * seen from class `base`. This symbol is always concrete. + * pre: `this.owner` is in the base class sequence of `base`. + */ + final def superSymbolIn(base: Symbol)(implicit ctx: Context): Symbol = { + def loop(bcs: List[ClassSymbol]): Symbol = bcs match { + case bc :: bcs1 => + val sym = matchingSymbol(bcs.head, base.thisType) + .suchThat(alt => !(alt is Deferred)).symbol + if (sym.exists) sym else loop(bcs.tail) + case _ => + NoSymbol + } + loop(base.info.baseClasses.dropWhile(owner != _).tail) + } + + + /** A a member of class `base` is incomplete if + * (1) it is declared deferred or + * (2) it is abstract override and its super symbol in `base` is + * nonexistent or incomplete. + */ + final def isIncompleteIn(base: Symbol)(implicit ctx: Context): Boolean = + (this is Deferred) || + (this is AbsOverride) && { + val supersym = superSymbolIn(base) + supersym == NoSymbol || supersym.isIncompleteIn(base) + } + /** The class or term symbol up to which this symbol is accessible, * or RootClass if it is public. As java protected statics are * otherwise completely inaccessible in scala, they are treated |