Skip to content

Commit 9e02a61

Browse files
committed
Fix realizability checking and test
1 parent a354ff5 commit 9e02a61

File tree

4 files changed

+16
-11
lines changed

4 files changed

+16
-11
lines changed

compiler/src/dotty/tools/dotc/core/CheckRealizable.scala

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ class CheckRealizable(implicit ctx: Context) {
105105
/** `Realizable` if `tp` has good bounds, a `HasProblem...` instance
106106
* pointing to a bad bounds member otherwise. "Has good bounds" means:
107107
*
108-
* - all type members have good bounds
108+
* - all type members have good bounds (except for opaque helpers)
109+
* - all refinements of the underlying type have good bounds (except for opaque companions)
109110
* - all base types are class types, and if their arguments are wildcards
110111
* they have good bounds.
111112
* - base types do not appear in multiple instances with different arguments.
@@ -114,10 +115,15 @@ class CheckRealizable(implicit ctx: Context) {
114115
*/
115116
private def boundsRealizability(tp: Type) = {
116117

118+
def isOpaqueCompanionThis = tp match {
119+
case tp: ThisType => tp.cls.isOpaqueCompanion
120+
case _ => false
121+
}
122+
117123
val memberProblems =
118124
for {
119125
mbr <- tp.nonClassTypeMembers
120-
if !(mbr.info.loBound <:< mbr.info.hiBound)
126+
if !(mbr.info.loBound <:< mbr.info.hiBound) && !mbr.symbol.isOpaqueHelper
121127
}
122128
yield new HasProblemBounds(mbr.name, mbr.info)
123129

@@ -126,7 +132,7 @@ class CheckRealizable(implicit ctx: Context) {
126132
name <- refinedNames(tp)
127133
if (name.isTypeName)
128134
mbr <- tp.member(name).alternatives
129-
if !(mbr.info.loBound <:< mbr.info.hiBound)
135+
if !(mbr.info.loBound <:< mbr.info.hiBound) && !isOpaqueCompanionThis
130136
}
131137
yield new HasProblemBounds(name, mbr.info)
132138

compiler/src/dotty/tools/dotc/transform/ElimOpaque.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class ElimOpaque extends MiniPhase with SymTransformer {
3535
override def runsAfterGroupsOf: Set[String] = Set(typer.RefChecks.name)
3636

3737
// base types of opaque aliases change
38-
def changesBaseTypes = true
38+
override def changesBaseTypes = true
3939

4040
def transformSym(sym: SymDenotation)(implicit ctx: Context): SymDenotation =
4141
if (sym.isOpaqueHelper) {

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

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -582,12 +582,11 @@ trait Checking {
582582
if (!tp.isStable) ctx.error(ex"$tp is not stable", pos)
583583

584584
/** Check that all type members of `tp` have realizable bounds */
585-
def checkRealizableBounds(cls: Symbol, pos: Position)(implicit ctx: Context): Unit =
586-
if (!cls.is(Module)) { // module's have system generated self types, which are assumed to be good
587-
val rstatus = boundsRealizability(cls.thisType)
588-
if (rstatus ne Realizable)
589-
ctx.error(ex"$cls cannot be instantiated since it${rstatus.msg}", pos)
590-
}
585+
def checkRealizableBounds(cls: Symbol, pos: Position)(implicit ctx: Context): Unit = {
586+
val rstatus = boundsRealizability(cls.thisType)
587+
if (rstatus ne Realizable)
588+
ctx.error(ex"$cls cannot be instantiated since it${rstatus.msg}", pos)
589+
}
591590

592591
/** Check that `tp` is a class type.
593592
* Also, if `traitReq` is true, check that `tp` is a trait.

tests/neg/aliasing-subtypes.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ object Test {
44
type A
55
}
66

7-
class C extends T { this: m.type =>
7+
class C extends T { this: m.type => // error: cannot instantiate
88
type A >: Int | Test.A <: Int & Test.A
99

1010
def reveal(x: A): Int = x

0 commit comments

Comments
 (0)