Skip to content

Commit 2adc617

Browse files
committed
Change opaque scope
The scope where an opaque alias is transparent is now the enclosing class of the opaque definition. The notion of opaque companion object has been dropped.
1 parent 56c7306 commit 2adc617

28 files changed

+154
-249
lines changed

compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -818,47 +818,6 @@ object desugar {
818818
}
819819
}
820820

821-
/** Expand
822-
*
823-
* <mods> opaque type T = [Xs] =>> R
824-
*
825-
* to
826-
*
827-
* <mods> opaque type T = T.T
828-
* synthetic object T {
829-
* synthetic opaque type T >: [Xs] =>> R
830-
* }
831-
*
832-
* The generated companion object will later (in Namer) be merged with the user-defined
833-
* companion object, and the synthetic opaque type member will go into the self type.
834-
*/
835-
def opaqueAlias(tdef: TypeDef)(implicit ctx: Context): Tree =
836-
if (lacksDefinition(tdef)) {
837-
ctx.error(em"opaque type ${tdef.name} must be an alias type", tdef.sourcePos)
838-
tdef.withFlags(tdef.mods.flags &~ Opaque)
839-
}
840-
else {
841-
def completeForwarder(fwd: Tree) = tdef.rhs match {
842-
case LambdaTypeTree(tparams, tpt) =>
843-
val tparams1 =
844-
for (tparam <- tparams)
845-
yield tparam.withMods(tparam.mods | Synthetic)
846-
lambdaAbstract(tparams1,
847-
AppliedTypeTree(fwd, tparams.map(tparam => Ident(tparam.name))))
848-
case _ =>
849-
fwd
850-
}
851-
val moduleName = tdef.name.toTermName
852-
val localRef = Select(Ident(moduleName), tdef.name).withAttachment(SuppressAccessCheck, ())
853-
val aliasType = cpy.TypeDef(tdef)(rhs = completeForwarder(localRef)).withSpan(tdef.span.startPos)
854-
val localType = tdef.withMods(Modifiers(Synthetic | Opaque).withPrivateWithin(tdef.name))
855-
856-
val companions = moduleDef(ModuleDef(
857-
moduleName, Template(emptyConstructor, Nil, Nil, EmptyValDef, localType :: Nil))
858-
.withFlags(Synthetic | Opaque))
859-
Thicket(aliasType :: companions.toList)
860-
}
861-
862821
/** The normalized name of `mdef`. This means
863822
* 1. Check that the name does not redefine a Scala core class.
864823
* If it does redefine, issue an error and return a mangled name instead of the original one.

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,11 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
198198
if (this.flags == flags) this
199199
else copy(flags = flags)
200200

201+
def withoutFlags(flags: FlagSet): Modifiers =
202+
if (this.is(flags))
203+
Modifiers(this.flags &~ flags, this.privateWithin, this.annotations, this.mods.filterNot(_.flags.is(flags)))
204+
else this
205+
201206
def withAddedMod(mod: Mod): Modifiers =
202207
if (mods.exists(_ eq mod)) this
203208
else withMods(mods :+ mod)

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

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -145,25 +145,16 @@ class CheckRealizable(implicit ctx: Context) {
145145
*/
146146
private def boundsRealizability(tp: Type) = {
147147

148-
def isOpaqueCompanionThis = tp match {
149-
case tp: ThisType => tp.cls.isOpaqueCompanion
150-
case _ => false
151-
}
152-
153148
val memberProblems =
154-
for {
155-
mbr <- tp.nonClassTypeMembers
156-
if !(mbr.info.loBound <:< mbr.info.hiBound) && !mbr.symbol.isOpaqueHelper
157-
}
149+
for mbr <- tp.nonClassTypeMembers if !(mbr.info.loBound <:< mbr.info.hiBound)
158150
yield new HasProblemBounds(mbr.name, mbr.info)
159151

160152
val refinementProblems =
161-
for {
153+
for
162154
name <- refinedNames(tp)
163155
if (name.isTypeName)
164156
mbr <- tp.member(name).alternatives
165-
if !(mbr.info.loBound <:< mbr.info.hiBound) && !isOpaqueCompanionThis
166-
}
157+
if !(mbr.info.loBound <:< mbr.info.hiBound)
167158
yield new HasProblemBounds(name, mbr.info)
168159

169160
def baseTypeProblems(base: Type) = base match {

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

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ object Flags {
268268
/** A mutable var */
269269
final val Mutable: FlagSet = termFlag(12, "mutable")
270270

271-
/** An opqaue type */
271+
/** An opaque type or a class containing one */
272272
final val Opaque: FlagSet = typeFlag(12, "opaque")
273273

274274
final val MutableOrOpaque: FlagSet = Mutable.toCommonFlags
@@ -550,13 +550,7 @@ object Flags {
550550
Accessor | AbsOverride | StableRealizable | Captured | Synchronized | Erased
551551

552552
/** Flags that can apply to a module class */
553-
final val RetainedModuleClassFlags: FlagSet = RetainedModuleValAndClassFlags |
554-
Enum | Opaque
555-
556-
/** Flags that are copied from a synthetic companion to a user-defined one
557-
* when the two are merged. See: Namer.mergeCompanionDefs
558-
*/
559-
final val RetainedSyntheticCompanionFlags: FlagSet = Opaque
553+
final val RetainedModuleClassFlags: FlagSet = RetainedModuleValAndClassFlags | Enum
560554

561555
/** Packages and package classes always have these flags set */
562556
final val PackageCreationFlags: FlagSet =
@@ -687,9 +681,6 @@ object Flags {
687681
/** A Java companion object */
688682
final val JavaModule: FlagConjunction = allOf(JavaDefined, Module)
689683

690-
/** An opaque companion object */
691-
final val OpaqueModule: FlagConjunction = allOf(Opaque, Module)
692-
693684
/** A Java companion object */
694685
final val JavaProtected: FlagConjunction = allOf(JavaDefined, Protected)
695686

@@ -739,7 +730,6 @@ object Flags {
739730
final val SyntheticTermParam: FlagConjunction = allOf(Synthetic, TermParam)
740731
final val SyntheticTypeParam: FlagConjunction = allOf(Synthetic, TypeParam)
741732
final val SyntheticCase: FlagConjunction = allOf(Synthetic, Case)
742-
final val SyntheticOpaque: FlagConjunction = allOf(Synthetic, Opaque)
743733

744734
implicit def conjToFlagSet(conj: FlagConjunction): FlagSet =
745735
FlagSet(conj.bits)

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

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -372,17 +372,30 @@ object SymDenotations {
372372
case _ => unforcedDecls.openForMutations
373373
}
374374

375-
/** If this is a synthetic opaque type alias, mark it as Deferred with empty bounds
375+
/** If this is a synthetic opaque type alias, mark it as Deferred with empty bounds.
376+
* At the same time, integrate the original alias as a refinement of the
377+
* self type of the enclosing class.
376378
*/
377379
final def normalizeOpaque()(implicit ctx: Context) = {
378380
def abstractRHS(tp: Type): Type = tp match {
379381
case tp: HKTypeLambda => tp.derivedLambdaType(resType = abstractRHS(tp.resType))
380382
case _ => defn.AnyType
381383
}
382-
if (isOpaqueHelper) {
384+
if (isOpaqueAlias) {
383385
info match {
384386
case TypeAlias(alias) =>
385387
info = TypeBounds(defn.NothingType, abstractRHS(alias))
388+
389+
def refineSelfType(selfType: Type) =
390+
RefinedType(selfType, name, TypeAlias(alias))
391+
val enclClassInfo = owner.asClass.classInfo
392+
enclClassInfo.selfInfo match {
393+
case self: Type =>
394+
owner.info = enclClassInfo.derivedClassInfo(selfInfo = refineSelfType(self))
395+
case self: Symbol =>
396+
self.info = refineSelfType(self.info)
397+
}
398+
386399
setFlag(Deferred)
387400
case _ =>
388401
}
@@ -553,18 +566,14 @@ object SymDenotations {
553566
final def isAbstractOrParamType(implicit ctx: Context): Boolean = this is DeferredOrTypeParam
554567

555568
/** Is this symbol a user-defined opaque alias type? */
556-
def isOpaqueAlias(implicit ctx: Context): Boolean = is(Opaque, butNot = Synthetic)
569+
def isOpaqueAlias(implicit ctx: Context): Boolean = is(Opaque) && !isClass
557570

558-
/** Is this symbol the companion of an opaque alias type? */
559-
def isOpaqueCompanion(implicit ctx: Context): Boolean = is(OpaqueModule)
571+
/** Is this symbol a module that contains of an opaque aliases? */
572+
def containsOpaques(implicit ctx: Context): Boolean = is(Opaque) && isClass
560573

561-
/** Is this symbol a synthetic opaque type inside an opaque companion object? */
562-
def isOpaqueHelper(implicit ctx: Context): Boolean = is(SyntheticOpaque, butNot = Module)
563-
564-
/** Can this symbol have a companion module?
565-
* This is the case if it is a class or an opaque type alias.
566-
*/
567-
final def canHaveCompanion(implicit ctx: Context) = isClass || isOpaqueAlias
574+
def seesOpaques(implicit ctx: Context): Boolean =
575+
containsOpaques ||
576+
is(Module, butNot = Package) && owner.containsOpaques
568577

569578
/** Is this the denotation of a self symbol of some class?
570579
* This is the case if one of two conditions holds:
@@ -789,7 +798,7 @@ object SymDenotations {
789798
*/
790799
def membersNeedAsSeenFrom(pre: Type)(implicit ctx: Context): Boolean =
791800
!( this.isTerm
792-
|| this.isStaticOwner && !this.isOpaqueCompanion
801+
|| this.isStaticOwner && !this.seesOpaques
793802
|| ctx.erasedTypes
794803
|| (pre eq NoPrefix)
795804
|| (pre eq thisType)
@@ -1029,16 +1038,6 @@ object SymDenotations {
10291038
*/
10301039
final def companionModule(implicit ctx: Context): Symbol =
10311040
if (is(Module)) sourceModule
1032-
else if (isOpaqueAlias) {
1033-
def reference(tp: Type): Symbol = tp match {
1034-
case TypeRef(prefix: TermRef, _) => prefix.termSymbol
1035-
case tp: HKTypeLambda => reference(tp.resType)
1036-
case tp: AppliedType => reference(tp.tycon)
1037-
case tp: ErrorType => registeredCompanion.sourceModule
1038-
}
1039-
val TypeAlias(alias) = info
1040-
reference(alias)
1041-
}
10421041
else registeredCompanion.sourceModule
10431042

10441043
private def companionType(implicit ctx: Context): Symbol =
@@ -1053,13 +1052,6 @@ object SymDenotations {
10531052
final def companionClass(implicit ctx: Context): Symbol =
10541053
companionType.suchThat(_.isClass).symbol
10551054

1056-
/** The opaque type with the same (type-) name as this module or module class,
1057-
* and which is also defined in the same scope and compilation unit.
1058-
* NoSymbol if this type does not exist.
1059-
*/
1060-
final def companionOpaqueType(implicit ctx: Context): Symbol =
1061-
companionType.suchThat(_.isOpaqueAlias).symbol
1062-
10631055
final def scalacLinkedClass(implicit ctx: Context): Symbol =
10641056
if (this is ModuleClass) companionNamed(effectiveName.toTypeName)
10651057
else if (this.isClass) companionNamed(effectiveName.moduleClassName).sourceModule.moduleClass
@@ -1109,15 +1101,17 @@ object SymDenotations {
11091101
final def enclosingSubClass(implicit ctx: Context): Symbol =
11101102
ctx.owner.ownersIterator.findSymbol(_.isSubClass(symbol))
11111103

1112-
/** The alias of a synthetic opaque type that's stored in the self type of the
1104+
/** The alias of an opaque type alias that's stored in the self type of the
11131105
* containing object.
11141106
*/
11151107
def opaqueAlias(implicit ctx: Context): Type = {
1116-
if (isOpaqueHelper)
1117-
owner.asClass.classInfo.selfType match {
1118-
case RefinedType(_, _, bounds) => bounds.extractOpaqueAlias
1119-
}
1120-
else NoType
1108+
def recur(tp: Type): Type = tp match {
1109+
case RefinedType(parent, rname, TypeAlias(alias)) =>
1110+
if (rname == name) alias else recur(parent)
1111+
case _ =>
1112+
NoType
1113+
}
1114+
recur(owner.asClass.classInfo.selfType)
11211115
}
11221116

11231117
/** The non-private symbol whose name and type matches the type of this symbol
@@ -1974,7 +1968,7 @@ object SymDenotations {
19741968

19751969
/** Register companion class */
19761970
override def registerCompanion(companion: Symbol)(implicit ctx: Context) =
1977-
if (companion.canHaveCompanion && !unforcedIsAbsent && !companion.unforcedIsAbsent)
1971+
if (companion.isClass && !unforcedIsAbsent && !companion.unforcedIsAbsent)
19781972
myCompanion = companion
19791973

19801974
override def registeredCompanion(implicit ctx: Context) = { ensureCompleted(); myCompanion }

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ object TypeErasure {
236236
* erased to `Object` instead of `Object[]`.
237237
*/
238238
def isUnboundedGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias match {
239-
case tp: TypeRef if !tp.symbol.isOpaqueHelper =>
239+
case tp: TypeRef if !tp.symbol.isOpaqueAlias =>
240240
!tp.symbol.isClass &&
241241
!classify(tp).derivesFrom(defn.ObjectClass) &&
242242
!tp.symbol.is(JavaDefined)
@@ -253,7 +253,7 @@ object TypeErasure {
253253

254254
/** Is `tp` an abstract type or polymorphic type parameter, or another unbounded generic type? */
255255
def isGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias match {
256-
case tp: TypeRef if !tp.symbol.isOpaqueHelper => !tp.symbol.isClass
256+
case tp: TypeRef if !tp.symbol.isOpaqueAlias => !tp.symbol.isClass
257257
case tp: TypeParamRef => true
258258
case tp: TypeProxy => isGeneric(tp.translucentSuperType)
259259
case tp: AndType => isGeneric(tp.tp1) || isGeneric(tp.tp2)
@@ -365,7 +365,7 @@ object TypeErasure {
365365
* possible instantiations?
366366
*/
367367
def hasStableErasure(tp: Type)(implicit ctx: Context): Boolean = tp match {
368-
case tp: TypeRef if !tp.symbol.isOpaqueHelper =>
368+
case tp: TypeRef if !tp.symbol.isOpaqueAlias =>
369369
tp.info match {
370370
case TypeAlias(alias) => hasStableErasure(alias)
371371
case _: ClassInfo => true

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
9595
tp match {
9696
case tp: NamedType =>
9797
val sym = tp.symbol
98-
if (sym.isStatic && !sym.maybeOwner.isOpaqueCompanion || (tp.prefix `eq` NoPrefix)) tp
98+
if (sym.isStatic && !sym.maybeOwner.seesOpaques || (tp.prefix `eq` NoPrefix)) tp
9999
else derivedSelect(tp, atVariance(variance max 0)(this(tp.prefix)))
100100
case tp: ThisType =>
101101
toPrefix(pre, cls, tp.cls)

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

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1140,18 +1140,6 @@ object Types {
11401140
/** Like `dealiasKeepAnnots`, but keeps only refining annotations */
11411141
final def dealiasKeepRefiningAnnots(implicit ctx: Context): Type = dealias1(keepIfRefining)
11421142

1143-
/** If this is a synthetic opaque type seen from inside the opaque companion object,
1144-
* its opaque alias, otherwise the type itself.
1145-
*/
1146-
final def followSyntheticOpaque(implicit ctx: Context): Type = this match {
1147-
case tp: TypeProxy if tp.typeSymbol.is(SyntheticOpaque) =>
1148-
tp.superType match {
1149-
case AndType(alias, _) => alias // in this case we are inside the companion object
1150-
case _ => this
1151-
}
1152-
case _ => this
1153-
}
1154-
11551143
/** The result of normalization using `tryNormalize`, or the type itself if
11561144
* tryNormlize yields NoType
11571145
*/
@@ -2323,7 +2311,7 @@ object Types {
23232311
override def translucentSuperType(implicit ctx: Context) = info match {
23242312
case TypeAlias(aliased) => aliased
23252313
case TypeBounds(_, hi) =>
2326-
if (symbol.isOpaqueHelper) symbol.opaqueAlias.asSeenFrom(prefix, symbol.owner)
2314+
if (symbol.isOpaqueAlias) symbol.opaqueAlias.asSeenFrom(prefix, symbol.owner)
23272315
else hi
23282316
case _ => underlying
23292317
}
@@ -3521,7 +3509,7 @@ object Types {
35213509
}
35223510

35233511
override def translucentSuperType(implicit ctx: Context): Type = tycon match {
3524-
case tycon: TypeRef if tycon.symbol.isOpaqueHelper =>
3512+
case tycon: TypeRef if tycon.symbol.isOpaqueAlias =>
35253513
tycon.translucentSuperType.applyIfParameterized(args)
35263514
case _ =>
35273515
superType

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -419,7 +419,8 @@ class TreeUnpickler(reader: TastyReader,
419419
val prefix = readType()
420420
val res = NamedType(prefix, sym)
421421
prefix match {
422-
case prefix: ThisType if prefix.cls eq sym.owner => res.withDenot(sym.denot)
422+
case prefix: ThisType if (prefix.cls eq sym.owner) && !sym.is(Opaque) =>
423+
res.withDenot(sym.denot)
423424
// without this precaution we get an infinite cycle when unpickling pos/extmethods.scala
424425
// the problem arises when a self type of a trait is a type parameter of the same trait.
425426
case _ => res

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

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,21 @@ class ElimOpaque extends MiniPhase with DenotTransformer {
3131
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = {
3232
val sym = ref.symbol
3333
ref match {
34-
case ref: SymDenotation if sym.isOpaqueHelper =>
34+
case ref: SymDenotation if sym.isOpaqueAlias =>
3535
ref.copySymDenotation(
3636
info = TypeAlias(ref.opaqueAlias),
3737
initFlags = ref.flags &~ (Opaque | Deferred))
38-
case ref: SymDenotation if sym.isOpaqueCompanion =>
38+
case ref: SymDenotation if sym.containsOpaques =>
39+
def stripOpaqueRefinements(tp: Type): Type = tp match {
40+
case RefinedType(parent, rname, TypeAlias(_))
41+
if ref.info.decl(rname).symbol.isOpaqueAlias => stripOpaqueRefinements(parent)
42+
case _ => tp
43+
}
3944
val cinfo = sym.asClass.classInfo
40-
val RefinedType(sourceRef, _, _) = cinfo.selfInfo
41-
val ref1 = ref.copySymDenotation(
42-
info = cinfo.derivedClassInfo(selfInfo = sourceRef),
45+
val strippedSelfType = stripOpaqueRefinements(cinfo.selfType)
46+
ref.copySymDenotation(
47+
info = cinfo.derivedClassInfo(selfInfo = strippedSelfType),
4348
initFlags = ref.flags &~ Opaque)
44-
ref1.registeredCompanion = NoSymbol
45-
ref1
46-
case _ if sym.isOpaqueHelper =>
47-
ref.derivedSingleDenotation(sym, TypeAlias(ref.info.extractOpaqueAlias))
4849
case _ =>
4950
ref
5051
}

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -58,18 +58,6 @@ object TypeUtils {
5858
def toNestedPairs(implicit ctx: Context): Type =
5959
TypeOps.nestedPairs(tupleElementTypes)
6060

61-
/** Extract opaque alias from TypeBounds type that combines it with the reference
62-
* to the opaque type itself
63-
*/
64-
def extractOpaqueAlias(implicit ctx: Context): Type = self match {
65-
case TypeBounds(lo, _) =>
66-
def extractAlias(tp: Type): Type = tp match {
67-
case OrType(alias, _) => alias
68-
case self: HKTypeLambda => self.derivedLambdaType(resType = extractAlias(self.resType))
69-
}
70-
extractAlias(lo)
71-
}
72-
7361
def refinedWith(name: Name, info: Type)(implicit ctx: Context) = RefinedType(self, name, info)
7462

7563
/** The TermRef referring to the companion of the underlying class reference

0 commit comments

Comments
 (0)