Skip to content

Commit 5a6fa43

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 1963f3c commit 5a6fa43

28 files changed

+154
-250
lines changed

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

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -817,48 +817,6 @@ object desugar {
817817
}
818818
}
819819

820-
/** Expand
821-
*
822-
* <mods> opaque type T = [Xs] =>> R
823-
*
824-
* to
825-
*
826-
* <mods> opaque type T = T.T
827-
* synthetic object T {
828-
* synthetic opaque type T >: [Xs] =>> R
829-
* }
830-
*
831-
* The generated companion object will later (in Namer) be merged with the user-defined
832-
* companion object, and the synthetic opaque type member will go into the self type.
833-
*/
834-
def opaqueAlias(tdef: TypeDef)(implicit ctx: Context): Tree =
835-
if (lacksDefinition(tdef)) {
836-
ctx.error(em"opaque type ${tdef.name} must be an alias type", tdef.sourcePos)
837-
tdef.withFlags(tdef.mods.flags &~ Opaque)
838-
}
839-
else {
840-
def completeForwarder(fwd: Tree) = tdef.rhs match {
841-
case LambdaTypeTree(tparams, tpt) =>
842-
val tparams1 =
843-
for (tparam <- tparams)
844-
yield tparam.withMods(tparam.mods | Synthetic)
845-
lambdaAbstract(tparams1,
846-
AppliedTypeTree(fwd, tparams.map(tparam => Ident(tparam.name))))
847-
case _ =>
848-
fwd
849-
}
850-
val moduleName = tdef.name.toTermName
851-
val localRef = Select(Ident(moduleName), tdef.name)
852-
localRef.pushAttachment(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-
862820
/** The normalized name of `mdef`. This means
863821
* 1. Check that the name does not redefine a Scala core class.
864822
* 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
@@ -194,6 +194,11 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
194194
if (this.flags == flags) this
195195
else copy(flags = flags)
196196

197+
def withoutFlags(flags: FlagSet): Modifiers =
198+
if (this.is(flags))
199+
Modifiers(this.flags &~ flags, this.privateWithin, this.annotations, this.mods.filterNot(_.flags.is(flags)))
200+
else this
201+
197202
def withAddedMod(mod: Mod): Modifiers =
198203
if (mods.exists(_ eq mod)) this
199204
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
@@ -265,7 +265,7 @@ object Flags {
265265
/** A mutable var */
266266
final val Mutable: FlagSet = termFlag(12, "mutable")
267267

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

271271
final val MutableOrOpaque: FlagSet = Mutable.toCommonFlags
@@ -547,13 +547,7 @@ object Flags {
547547
Accessor | AbsOverride | StableRealizable | Captured | Synchronized | Erased
548548

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

558552
/** Packages and package classes always have these flags set */
559553
final val PackageCreationFlags: FlagSet =
@@ -678,9 +672,6 @@ object Flags {
678672
/** A Java companion object */
679673
final val JavaModule: FlagConjunction = allOf(JavaDefined, Module)
680674

681-
/** An opaque companion object */
682-
final val OpaqueModule: FlagConjunction = allOf(Opaque, Module)
683-
684675
/** A Java companion object */
685676
final val JavaProtected: FlagConjunction = allOf(JavaDefined, Protected)
686677

@@ -730,7 +721,6 @@ object Flags {
730721
final val SyntheticTermParam: FlagConjunction = allOf(Synthetic, TermParam)
731722
final val SyntheticTypeParam: FlagConjunction = allOf(Synthetic, TypeParam)
732723
final val SyntheticCase: FlagConjunction = allOf(Synthetic, Case)
733-
final val SyntheticOpaque: FlagConjunction = allOf(Synthetic, Opaque)
734724

735725
implicit def conjToFlagSet(conj: FlagConjunction): FlagSet =
736726
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
@@ -370,17 +370,30 @@ object SymDenotations {
370370
case _ => unforcedDecls.openForMutations
371371
}
372372

373-
/** If this is a synthetic opaque type alias, mark it as Deferred with empty bounds
373+
/** If this is a synthetic opaque type alias, mark it as Deferred with empty bounds.
374+
* At the same time, integrate the original alias as a refinement of the
375+
* self type of the enclosing class.
374376
*/
375377
final def normalizeOpaque()(implicit ctx: Context) = {
376378
def abstractRHS(tp: Type): Type = tp match {
377379
case tp: HKTypeLambda => tp.derivedLambdaType(resType = abstractRHS(tp.resType))
378380
case _ => defn.AnyType
379381
}
380-
if (isOpaqueHelper) {
382+
if (isOpaqueAlias) {
381383
info match {
382384
case TypeAlias(alias) =>
383385
info = TypeBounds(defn.NothingType, abstractRHS(alias))
386+
387+
def refineSelfType(selfType: Type) =
388+
RefinedType(selfType, name, TypeAlias(alias))
389+
val enclClassInfo = owner.asClass.classInfo
390+
enclClassInfo.selfInfo match {
391+
case self: Type =>
392+
owner.info = enclClassInfo.derivedClassInfo(selfInfo = refineSelfType(self))
393+
case self: Symbol =>
394+
self.info = refineSelfType(self.info)
395+
}
396+
384397
setFlag(Deferred)
385398
case _ =>
386399
}
@@ -539,18 +552,14 @@ object SymDenotations {
539552
final def isAbstractOrParamType(implicit ctx: Context): Boolean = this is DeferredOrTypeParam
540553

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

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

547-
/** Is this symbol a synthetic opaque type inside an opaque companion object? */
548-
def isOpaqueHelper(implicit ctx: Context): Boolean = is(SyntheticOpaque, butNot = Module)
549-
550-
/** Can this symbol have a companion module?
551-
* This is the case if it is a class or an opaque type alias.
552-
*/
553-
final def canHaveCompanion(implicit ctx: Context) = isClass || isOpaqueAlias
560+
def seesOpaques(implicit ctx: Context): Boolean =
561+
containsOpaques ||
562+
is(Module, butNot = Package) && owner.containsOpaques
554563

555564
/** Is this the denotation of a self symbol of some class?
556565
* This is the case if one of two conditions holds:
@@ -775,7 +784,7 @@ object SymDenotations {
775784
*/
776785
def membersNeedAsSeenFrom(pre: Type)(implicit ctx: Context): Boolean =
777786
!( this.isTerm
778-
|| this.isStaticOwner && !this.isOpaqueCompanion
787+
|| this.isStaticOwner && !this.seesOpaques
779788
|| ctx.erasedTypes
780789
|| (pre eq NoPrefix)
781790
|| (pre eq thisType)
@@ -1015,16 +1024,6 @@ object SymDenotations {
10151024
*/
10161025
final def companionModule(implicit ctx: Context): Symbol =
10171026
if (is(Module)) sourceModule
1018-
else if (isOpaqueAlias) {
1019-
def reference(tp: Type): Symbol = tp match {
1020-
case TypeRef(prefix: TermRef, _) => prefix.termSymbol
1021-
case tp: HKTypeLambda => reference(tp.resType)
1022-
case tp: AppliedType => reference(tp.tycon)
1023-
case tp: ErrorType => registeredCompanion.sourceModule
1024-
}
1025-
val TypeAlias(alias) = info
1026-
reference(alias)
1027-
}
10281027
else registeredCompanion.sourceModule
10291028

10301029
private def companionType(implicit ctx: Context): Symbol =
@@ -1039,13 +1038,6 @@ object SymDenotations {
10391038
final def companionClass(implicit ctx: Context): Symbol =
10401039
companionType.suchThat(_.isClass).symbol
10411040

1042-
/** The opaque type with the same (type-) name as this module or module class,
1043-
* and which is also defined in the same scope and compilation unit.
1044-
* NoSymbol if this type does not exist.
1045-
*/
1046-
final def companionOpaqueType(implicit ctx: Context): Symbol =
1047-
companionType.suchThat(_.isOpaqueAlias).symbol
1048-
10491041
final def scalacLinkedClass(implicit ctx: Context): Symbol =
10501042
if (this is ModuleClass) companionNamed(effectiveName.toTypeName)
10511043
else if (this.isClass) companionNamed(effectiveName.moduleClassName).sourceModule.moduleClass
@@ -1095,15 +1087,17 @@ object SymDenotations {
10951087
final def enclosingSubClass(implicit ctx: Context): Symbol =
10961088
ctx.owner.ownersIterator.findSymbol(_.isSubClass(symbol))
10971089

1098-
/** The alias of a synthetic opaque type that's stored in the self type of the
1090+
/** The alias of an opaque type alias that's stored in the self type of the
10991091
* containing object.
11001092
*/
11011093
def opaqueAlias(implicit ctx: Context): Type = {
1102-
if (isOpaqueHelper)
1103-
owner.asClass.classInfo.selfType match {
1104-
case RefinedType(_, _, bounds) => bounds.extractOpaqueAlias
1105-
}
1106-
else NoType
1094+
def recur(tp: Type): Type = tp match {
1095+
case RefinedType(parent, rname, TypeAlias(alias)) =>
1096+
if (rname == name) alias else recur(parent)
1097+
case _ =>
1098+
NoType
1099+
}
1100+
recur(owner.asClass.classInfo.selfType)
11071101
}
11081102

11091103
/** The non-private symbol whose name and type matches the type of this symbol
@@ -1960,7 +1954,7 @@ object SymDenotations {
19601954

19611955
/** Register companion class */
19621956
override def registerCompanion(companion: Symbol)(implicit ctx: Context) =
1963-
if (companion.canHaveCompanion && !unforcedIsAbsent && !companion.unforcedIsAbsent)
1957+
if (companion.isClass && !unforcedIsAbsent && !companion.unforcedIsAbsent)
19641958
myCompanion = companion
19651959

19661960
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
@@ -219,7 +219,7 @@ object TypeErasure {
219219
* erased to `Object` instead of `Object[]`.
220220
*/
221221
def isUnboundedGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias match {
222-
case tp: TypeRef if !tp.symbol.isOpaqueHelper =>
222+
case tp: TypeRef if !tp.symbol.isOpaqueAlias =>
223223
!tp.symbol.isClass &&
224224
!classify(tp).derivesFrom(defn.ObjectClass) &&
225225
!tp.symbol.is(JavaDefined)
@@ -236,7 +236,7 @@ object TypeErasure {
236236

237237
/** Is `tp` an abstract type or polymorphic type parameter, or another unbounded generic type? */
238238
def isGeneric(tp: Type)(implicit ctx: Context): Boolean = tp.dealias match {
239-
case tp: TypeRef if !tp.symbol.isOpaqueHelper => !tp.symbol.isClass
239+
case tp: TypeRef if !tp.symbol.isOpaqueAlias => !tp.symbol.isClass
240240
case tp: TypeParamRef => true
241241
case tp: TypeProxy => isGeneric(tp.translucentSuperType)
242242
case tp: AndType => isGeneric(tp.tp1) || isGeneric(tp.tp2)
@@ -348,7 +348,7 @@ object TypeErasure {
348348
* possible instantiations?
349349
*/
350350
def hasStableErasure(tp: Type)(implicit ctx: Context): Boolean = tp match {
351-
case tp: TypeRef if !tp.symbol.isOpaqueHelper =>
351+
case tp: TypeRef if !tp.symbol.isOpaqueAlias =>
352352
tp.info match {
353353
case TypeAlias(alias) => hasStableErasure(alias)
354354
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
@@ -1139,18 +1139,6 @@ object Types {
11391139
/** Like `dealiasKeepAnnots`, but keeps only refining annotations */
11401140
final def dealiasKeepRefiningAnnots(implicit ctx: Context): Type = dealias1(keepIfRefining)
11411141

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

35213509
override def translucentSuperType(implicit ctx: Context): Type = tycon match {
3522-
case tycon: TypeRef if tycon.symbol.isOpaqueHelper =>
3510+
case tycon: TypeRef if tycon.symbol.isOpaqueAlias =>
35233511
tycon.translucentSuperType.applyIfParameterized(args)
35243512
case _ =>
35253513
superType

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,8 @@ class TreeUnpickler(reader: TastyReader,
420420
val prefix = readType()
421421
val res = NamedType(prefix, sym)
422422
prefix match {
423-
case prefix: ThisType if prefix.cls eq sym.owner => res.withDenot(sym.denot)
423+
case prefix: ThisType if (prefix.cls eq sym.owner) && !sym.is(Opaque) =>
424+
res.withDenot(sym.denot)
424425
// without this precaution we get an infinite cycle when unpickling pos/extmethods.scala
425426
// the problem arises when a self type of a trait is a type parameter of the same trait.
426427
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
@@ -51,17 +51,5 @@ object TypeUtils {
5151
/** The `*:` equivalent of an instance of a Tuple class */
5252
def toNestedPairs(implicit ctx: Context): Type =
5353
TypeOps.nestedPairs(tupleElementTypes)
54-
55-
/** Extract opaque alias from TypeBounds type that combines it with the reference
56-
* to the opaque type itself
57-
*/
58-
def extractOpaqueAlias(implicit ctx: Context): Type = self match {
59-
case TypeBounds(lo, _) =>
60-
def extractAlias(tp: Type): Type = tp match {
61-
case OrType(alias, _) => alias
62-
case self: HKTypeLambda => self.derivedLambdaType(resType = extractAlias(self.resType))
63-
}
64-
extractAlias(lo)
65-
}
6654
}
6755
}

0 commit comments

Comments
 (0)