Skip to content

Commit e959c7a

Browse files
committed
Store opaque info in annotation
An opaque type becomes an abstract type, with the alias stored in an OpaqueAlias annotation
1 parent 9eb6aa1 commit e959c7a

File tree

9 files changed

+39
-5
lines changed

9 files changed

+39
-5
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,18 @@ object Annotations {
173173
else None
174174
}
175175

176+
/** Extractor for opaque alias annotations */
177+
object OpaqueAlias {
178+
def apply(tp: Type)(implicit ctx: Context): Annotation =
179+
Annotation(TypeTree(defn.OpaqueAliasAnnotType.appliedTo(tp)))
180+
def unapply(ann: Annotation)(implicit ctx: Context) =
181+
if (ann.symbol == defn.OpaqueAliasAnnot) {
182+
val AppliedType(tycon, arg :: Nil) = ann.tree.tpe
183+
Some(arg)
184+
}
185+
else None
186+
}
187+
176188
def makeSourceFile(path: String)(implicit ctx: Context) =
177189
apply(defn.SourceFileAnnot, Literal(Constant(path)))
178190
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,6 +664,8 @@ class Definitions {
664664
def BodyAnnot(implicit ctx: Context) = BodyAnnotType.symbol.asClass
665665
lazy val ChildAnnotType = ctx.requiredClassRef("scala.annotation.internal.Child")
666666
def ChildAnnot(implicit ctx: Context) = ChildAnnotType.symbol.asClass
667+
lazy val OpaqueAliasAnnotType = ctx.requiredClassRef("scala.annotation.internal.OpaqueAlias")
668+
def OpaqueAliasAnnot(implicit ctx: Context) = OpaqueAliasAnnotType.symbol.asClass
667669
lazy val CovariantBetweenAnnotType = ctx.requiredClassRef("scala.annotation.internal.CovariantBetween")
668670
def CovariantBetweenAnnot(implicit ctx: Context) = CovariantBetweenAnnotType.symbol.asClass
669671
lazy val ContravariantBetweenAnnotType = ctx.requiredClassRef("scala.annotation.internal.ContravariantBetween")

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,14 @@ object SymDenotations {
380380
case _ => unforcedDecls.openForMutations
381381
}
382382

383+
final def normalizeOpaque()(implicit ctx: Context) = {
384+
if (is(Opaque)) {
385+
addAnnotation(Annotation.OpaqueAlias(info))
386+
setFlag(Deferred)
387+
info = TypeBounds.empty
388+
}
389+
}
390+
383391
// ------ Names ----------------------------------------------
384392

385393
/** The expanded name of this denotation. */

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -614,8 +614,8 @@ class TreePickler(pickler: TastyPickler) {
614614
// a different toplevel class, it is impossible to pickle a reference to it.
615615
// Such annotations will be reconstituted when unpickling the child class.
616616
// See tests/pickling/i3149.scala
617-
case _ => ann.symbol == defn.BodyAnnot
618-
// inline bodies are reconstituted automatically when unpickling
617+
case _ => ann.symbol == defn.BodyAnnot || ann.symbol == defn.OpaqueAliasAnnot
618+
// inline bodies and opaque aliases are reconstituted automatically when unpickling
619619
}
620620

621621
def pickleAnnotation(owner: Symbol, ann: Annotation)(implicit ctx: Context) =

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@ class TreeUnpickler(reader: TastyReader,
528528
// avoids space leaks by not capturing the current context
529529
forkAt(rhsStart).readTerm()
530530
})
531+
sym.normalizeOpaque()
531532
goto(start)
532533
sym
533534
}

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,7 @@ class SymUtils(val self: Symbol) extends AnyVal {
129129
def registerCompanionMethod(name: Name, target: Symbol)(implicit ctx: Context) = {
130130
if (!self.unforcedDecls.lookup(name).exists) {
131131
val companionMethod = ctx.synthesizeCompanionMethod(name, target, self)
132-
if (companionMethod.exists) {
133-
companionMethod.entered
134-
}
132+
if (companionMethod.exists) companionMethod.entered
135133
}
136134
}
137135

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,7 @@ object Checking {
378378
checkNoConflict(Lazy, Inline)
379379
if (sym.is(Inline)) checkApplicable(Inline, sym.isTerm && !sym.is(Mutable | Module))
380380
if (sym.is(Lazy)) checkApplicable(Lazy, !sym.is(Method | Mutable))
381+
if (sym.is(Opaque)) checkApplicable(Opaque, sym.isAliasType)
381382
if (sym.isType && !sym.is(Deferred))
382383
for (cls <- sym.allOverriddenSymbols.filter(_.isClass)) {
383384
fail(CannotHaveSameNameAs(sym, cls, CannotHaveSameNameAs.CannotBeOverridden))

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,7 @@ class Namer { typer: Typer =>
832832
addInlineInfo(denot)
833833
denot.info = typeSig(sym)
834834
Checking.checkWellFormed(sym)
835+
denot.normalizeOpaque()
835836
denot.info = avoidPrivateLeaks(sym, sym.pos)
836837
}
837838
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package scala.annotation.internal
2+
3+
import scala.annotation.Annotation
4+
5+
/** An annotation to record the right-hand side of an opaque type. Given
6+
*
7+
* opaque type T = U
8+
*
9+
* the info of `T` is `Nothing..Any`, but `T` carries the annotation `OpaqueAlias[U]`
10+
*/
11+
class OpaqueAlias[T] extends Annotation

0 commit comments

Comments
 (0)