Skip to content

Commit 1466e88

Browse files
committed
Merge pull request #278 from dotty-staging/fix/#248-inherit-refinements
Fix #248: Class cannot inherit from refinement types
2 parents 7cdf3d0 + 9402783 commit 1466e88

File tree

5 files changed

+31
-14
lines changed

5 files changed

+31
-14
lines changed

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -700,15 +700,20 @@ object Types {
700700

701701
/** If this is a (possibly aliased, annotated, and/or parameterized) reference to
702702
* a class, the class type ref, otherwise NoType.
703+
* @param refinementOK If `true` we also skip non-parameter refinements.
703704
*/
704-
def underlyingClassRef(implicit ctx: Context): Type = dealias match {
705+
def underlyingClassRef(refinementOK: Boolean)(implicit ctx: Context): Type = dealias match {
705706
case tp: TypeRef =>
706707
if (tp.symbol.isClass) tp
707-
else if (tp.symbol.isAliasType) tp.underlying.underlyingClassRef
708+
else if (tp.symbol.isAliasType) tp.underlying.underlyingClassRef(refinementOK)
708709
else NoType
709-
case tp: TypeVar => tp.underlying.underlyingClassRef
710-
case tp: AnnotatedType => tp.underlying.underlyingClassRef
711-
case tp: RefinedType => tp.underlying.underlyingClassRef
710+
case tp: AnnotatedType => tp.underlying.underlyingClassRef(refinementOK)
711+
case tp: RefinedType =>
712+
if (refinementOK) tp.underlying.underlyingClassRef(refinementOK)
713+
else {
714+
val tycon = tp.withoutArgs(tp.argInfos)
715+
if (tycon eq tp) NoType else tycon.underlyingClassRef(refinementOK)
716+
}
712717
case _ => NoType
713718
}
714719

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ trait Checking {
248248
* @return `tp` itself if it is a class or trait ref, ObjectClass.typeRef if not.
249249
*/
250250
def checkClassTypeWithStablePrefix(tp: Type, pos: Position, traitReq: Boolean)(implicit ctx: Context): Type =
251-
tp.underlyingClassRef match {
251+
tp.underlyingClassRef(refinementOK = false) match {
252252
case tref: TypeRef =>
253253
if (ctx.phase <= ctx.refchecksPhase) checkStable(tref.prefix, pos)
254254
if (traitReq && !(tref.symbol is Trait)) ctx.error(d"$tref is not a trait", pos)

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,15 @@ trait Inferencing { this: Checking =>
106106
* class type reference where the class has a companion module, a reference to
107107
* that companion module. Otherwise NoType
108108
*/
109-
def companionRef(tp: Type)(implicit ctx: Context): Type = tp.underlyingClassRef match {
110-
case tp: TypeRef =>
111-
val companion = tp.classSymbol.companionModule
112-
if (companion.exists)
113-
companion.valRef.asSeenFrom(tp.prefix, companion.symbol.owner)
114-
else NoType
115-
case _ => NoType
116-
}
109+
def companionRef(tp: Type)(implicit ctx: Context): Type =
110+
tp.underlyingClassRef(refinementOK = true) match {
111+
case tp: TypeRef =>
112+
val companion = tp.classSymbol.companionModule
113+
if (companion.exists)
114+
companion.valRef.asSeenFrom(tp.prefix, companion.symbol.owner)
115+
else NoType
116+
case _ => NoType
117+
}
117118

118119
/** Ensure that the first type in a list of parent types Ps points to a non-trait class.
119120
* If that's not already the case, add one. The added class type CT is determined as follows.

test/dotc/tests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class tests extends CompilerTest {
107107
@Test def neg_cycles = compileFile(negDir, "cycles", xerrors = 8)
108108
@Test def neg_boundspropagation = compileFile(negDir, "boundspropagation", xerrors = 4)
109109
@Test def neg_refinedSubtyping = compileFile(negDir, "refinedSubtyping", xerrors = 2)
110+
@Test def neg_i0248_inherit_refined = compileFile(negDir, "i0248-inherit-refined", xerrors = 4)
110111

111112
@Test def dotc = compileDir(dotcDir + "tools/dotc", twice)(allowDeepSubtypes)
112113
@Test def dotc_ast = compileDir(dotcDir + "tools/dotc/ast", twice)

tests/neg/i0248-inherit-refined.scala

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
object test {
2+
class A { type T }
3+
type X = A { type T = Int }
4+
class B extends X
5+
type Y = A & B
6+
class C extends Y
7+
type Z = A | B
8+
class D extends Z
9+
abstract class E extends ({ val x: Int })
10+
}

0 commit comments

Comments
 (0)