Skip to content

Commit c2175ec

Browse files
committed
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.
1 parent 70e785f commit c2175ec

File tree

3 files changed

+75
-1
lines changed

3 files changed

+75
-1
lines changed

src/dotty/tools/dotc/core/SymDenotations.scala

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,9 @@ object SymDenotations {
321321
final def isAnonymousClass(implicit ctx: Context): Boolean =
322322
initial.asSymDenotation.name startsWith tpnme.ANON_CLASS
323323

324+
final def isRefinementClass(implicit ctx: Context): Boolean =
325+
name.decode == tpnme.REFINE_CLASS
326+
324327
/** Is this symbol a package object or its module class? */
325328
def isPackageObject(implicit ctx: Context): Boolean = {
326329
val poName = if (isType) nme.PACKAGE_CLS else nme.PACKAGE
@@ -701,6 +704,54 @@ object SymDenotations {
701704
else
702705
Iterator.empty
703706

707+
/** The symbol overriding this symbol in given subclass `ofclazz`.
708+
*
709+
* @param ofclazz is a subclass of this symbol's owner
710+
*/
711+
final def overridingSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol =
712+
if (canMatchInheritedSymbols) matchingSymbol(inClass, inClass.thisType)
713+
else NoSymbol
714+
715+
/** If false, this symbol cannot possibly participate in an override,
716+
* either as overrider or overridee. For internal use; you should consult
717+
* with isOverridingSymbol. This is used by isOverridingSymbol to escape
718+
* the recursive knot.
719+
*/
720+
private def canMatchInheritedSymbols = (
721+
owner.isClass
722+
&& !this.isClass
723+
&& !this.isConstructor
724+
)
725+
726+
/** The symbol accessed by a super in the definition of this symbol when
727+
* seen from class `base`. This symbol is always concrete.
728+
* pre: `this.owner` is in the base class sequence of `base`.
729+
*/
730+
final def superSymbolIn(base: Symbol)(implicit ctx: Context): Symbol = {
731+
def loop(bcs: List[ClassSymbol]): Symbol = bcs match {
732+
case bc :: bcs1 =>
733+
val sym = matchingSymbol(bcs.head, base.thisType)
734+
.suchThat(alt => !(alt is Deferred)).symbol
735+
if (sym.exists) sym else loop(bcs.tail)
736+
case _ =>
737+
NoSymbol
738+
}
739+
loop(base.info.baseClasses.dropWhile(owner != _).tail)
740+
}
741+
742+
743+
/** A a member of class `base` is incomplete if
744+
* (1) it is declared deferred or
745+
* (2) it is abstract override and its super symbol in `base` is
746+
* nonexistent or incomplete.
747+
*/
748+
final def isIncompleteIn(base: Symbol)(implicit ctx: Context): Boolean =
749+
(this is Deferred) ||
750+
(this is AbsOverride) && {
751+
val supersym = superSymbolIn(base)
752+
supersym == NoSymbol || supersym.isIncompleteIn(base)
753+
}
754+
704755
/** The class or term symbol up to which this symbol is accessible,
705756
* or RootClass if it is public. As java protected statics are
706757
* otherwise completely inaccessible in scala, they are treated

src/dotty/tools/dotc/typer/Namer.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,8 @@ class Namer { typer: Typer =>
459459

460460
def checkedParentType(parent: untpd.Tree): Type = {
461461
val ptype = parentType(parent)(ctx.fresh addMode Mode.InSuperCall)
462-
checkClassTypeWithStablePrefix(ptype, parent.pos, traitReq = parent ne parents.head)
462+
if (cls.isRefinementClass) ptype
463+
else checkClassTypeWithStablePrefix(ptype, parent.pos, traitReq = parent ne parents.head)
463464
}
464465

465466
val selfInfo =

tests/pos/tycons.scala

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
class TypeConstructor {
2+
type TypeArg
3+
}
4+
5+
trait List[+T] extends TypeConstructor { type TypeArg <: T }
6+
7+
trait Set[T] extends TypeConstructor { type TypeArg <: T }
8+
9+
object obj extends List[Number] with Set[Exception] {
10+
val x: TypeArg = ???
11+
val n: Number = x
12+
val e: Exception = x
13+
}
14+
15+
class Functor[F <: TypeConstructor] {
16+
def map[A, B](f: F { type TypeArg <: A }): F { type TypeArg <: B }
17+
}
18+
19+
implicit object ListFunctor extends Functor[List] {
20+
def map[A, B](f: List[A]): List[B] = ???
21+
}
22+

0 commit comments

Comments
 (0)