Skip to content

Commit f032a88

Browse files
authored
Merge pull request #9223 from dotty-staging/fix-#8874
Fix #8874: Strip opaque types when checking self type conformance
2 parents 9c16e7a + a63f92c commit f032a88

File tree

4 files changed

+23
-14
lines changed

4 files changed

+23
-14
lines changed

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,15 @@ class SymUtils(val self: Symbol) extends AnyVal {
233233
&& self.owner.is(Module)
234234
&& self.owner.linkedClass.is(Case)
235235
&& self.owner.linkedClass.isDeclaredInfix
236+
237+
/** The declared self type of this class, as seen from `site`, stripping
238+
* all refinements for opaque types.
239+
*/
240+
def declaredSelfTypeAsSeenFrom(site: Type)(using Context) =
241+
def (tp: Type).stripOpaques: Type = tp match
242+
case RefinedType(parent, name, _) if self.info.decl(name).symbol.isOpaqueAlias =>
243+
parent.stripOpaques
244+
case _ =>
245+
tp
246+
self.asClass.givenSelfType.stripOpaques.asSeenFrom(site, self)
236247
}

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

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -169,27 +169,19 @@ object Checking {
169169
* and that the instance conforms to the self type of the created class.
170170
*/
171171
def checkInstantiable(tp: Type, posd: Positioned)(using Context): Unit =
172-
tp.underlyingClassRef(refinementOK = false) match {
172+
tp.underlyingClassRef(refinementOK = false) match
173173
case tref: TypeRef =>
174174
val cls = tref.symbol
175175
if (cls.isOneOf(AbstractOrTrait))
176176
ctx.error(CantInstantiateAbstractClassOrTrait(cls, isTrait = cls.is(Trait)), posd.sourcePos)
177-
if (!cls.is(Module)) {
178-
def (tp: Type).stripOpaques: Type = tp match
179-
case RefinedType(parent, name, _) if cls.info.decl(name).symbol.isOpaqueAlias =>
180-
parent.stripOpaques
181-
case _ =>
182-
tp
177+
if !cls.is(Module) then
183178
// Create a synthetic singleton type instance, and check whether
184179
// it conforms to the self type of the class as seen from that instance.
185180
val stp = SkolemType(tp)
186-
val selfType =
187-
cls.asClass.givenSelfType.stripOpaques.asSeenFrom(stp, cls)
188-
if (selfType.exists && !(stp <:< selfType))
181+
val selfType = cls.declaredSelfTypeAsSeenFrom(stp)
182+
if selfType.exists && !(stp <:< selfType) then
189183
ctx.error(DoesNotConformToSelfTypeCantBeInstantiated(tp, selfType), posd.sourcePos)
190-
}
191184
case _ =>
192-
}
193185

194186
/** Check that type `tp` is realizable. */
195187
def checkRealizable(tp: Type, posd: Positioned, what: String = "path")(using Context): Unit = {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,8 @@ object RefChecks {
9595
private def checkParents(cls: Symbol)(using Context): Unit = cls.info match {
9696
case cinfo: ClassInfo =>
9797
def checkSelfConforms(other: ClassSymbol, category: String, relation: String) = {
98-
val otherSelf = other.givenSelfType.asSeenFrom(cls.thisType, other.classSymbol)
99-
if (otherSelf.exists && !(cinfo.selfType <:< otherSelf))
98+
val otherSelf = other.declaredSelfTypeAsSeenFrom(cls.thisType)
99+
if otherSelf.exists && !(cinfo.selfType <:< otherSelf) then
100100
ctx.error(DoesNotConformToSelfType(category, cinfo.selfType, cls, otherSelf, relation, other.classSymbol),
101101
cls.sourcePos)
102102
}

tests/pos/i8874.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
trait Abc:
2+
opaque type Log = Double
3+
4+
class AbcClass extends Abc
5+
6+
val v = new AbcClass

0 commit comments

Comments
 (0)