Skip to content

Add opaque types #4028

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1316,6 +1316,7 @@ object Trees {
Stats.record("TreeAccumulator.foldOver total")
def localCtx =
if (tree.hasType && tree.symbol.exists) ctx.withOwner(tree.symbol) else ctx
def templateCtx = ctx.maybeInOpaqueCompanionContext(ctx.owner)
tree match {
case Ident(name) =>
x
Expand Down Expand Up @@ -1398,6 +1399,7 @@ object Trees {
implicit val ctx = localCtx
this(x, rhs)
case tree @ Template(constr, parents, self, _) =>
implicit val ctx = templateCtx
this(this(this(this(x, constr), parents), self), tree.body)
case Import(expr, selectors) =>
this(x, expr)
Expand Down
12 changes: 7 additions & 5 deletions compiler/src/dotty/tools/dotc/ast/tpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1089,9 +1089,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
private val InlinedCalls = new Property.Key[List[Tree]]

/** Record an enclosing inlined call.
* EmptyTree calls (for parameters) cancel the next-enclosing call in the list instead of being added to it.
* We assume parameters are never nested inside parameters.
*/
* EmptyTree calls (for parameters) cancel the next-enclosing call in the list instead of being added to it.
* We assume parameters are never nested inside parameters.
*/
override def inlineContext(call: Tree)(implicit ctx: Context): Context = {
// We assume enclosingInlineds is already normalized, and only process the new call with the head.
val oldIC = enclosingInlineds
Expand All @@ -1101,11 +1101,13 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
ts2
case _ => call :: oldIC
}
ctx.fresh.setProperty(InlinedCalls, newIC)
ctx.fresh
.setProperty(InlinedCalls, newIC)
.inOpaqueCompanionsAround(call.symbol)
}

/** All enclosing calls that are currently inlined, from innermost to outermost.
*/
*/
def enclosingInlineds(implicit ctx: Context): List[Tree] =
ctx.property(InlinedCalls).getOrElse(Nil)

Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {

case class Sealed() extends Mod(Flags.Sealed)

case class Opaque() extends Mod(Flags.Opaque)

case class Override() extends Mod(Flags.Override)

case class Abstract() extends Mod(Flags.Abstract)
Expand Down
18 changes: 18 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,24 @@ object Contexts {
ctx.fresh.setImportInfo(new ImportInfo(implicit ctx => sym, imp.selectors, impNameOpt))
}

/** If `owner` is a companion object of an opaque type, record the alias in the GADT bounds */
def maybeInOpaqueCompanionContext(owner: Symbol): Context = {
if (owner.is(Flags.Module, butNot = Flags.Package)) {
val opaq = owner.companionOpaqueType
val alias = opaq.opaqueAlias
if (alias.exists) {
val result = fresh.setFreshGADTBounds
result.gadt.setBounds(opaq, TypeAlias(alias))
result
}
else this
}
else this
}

def inOpaqueCompanionsAround(sym: Symbol) =
(this /: sym.ownersIterator.takeWhile(!_.is(Flags.Package)))(_.maybeInOpaqueCompanionContext(_))

/** The current source file; will be derived from current
* compilation unit.
*/
Expand Down
2 changes: 2 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,7 @@ class Definitions {
lazy val EqualsPatternClass: ClassSymbol = enterSpecialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, Seq(AnyType))

lazy val RepeatedParamClass: ClassSymbol = enterSpecialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, Seq(ObjectType, SeqType))
lazy val OpaqueAliasAnnot: ClassSymbol = enterSpecialPolyClass(tpnme.OPAQUE_ALIAS, EmptyFlags, Seq(AnyType))

// fundamental classes
lazy val StringClass: ClassSymbol = ctx.requiredClass("java.lang.String")
Expand Down Expand Up @@ -1246,6 +1247,7 @@ class Definitions {
AnyKindClass,
RepeatedParamClass,
ByNameParamClass2x,
OpaqueAliasAnnot,
AnyValClass,
NullClass,
NothingClass,
Expand Down
28 changes: 19 additions & 9 deletions compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -250,9 +250,14 @@ object Flags {

final val AccessorOrSealed: FlagSet = Accessor.toCommonFlags

/** A mutable var */
/** A mutable var */
final val Mutable: FlagSet = termFlag(12, "mutable")

/** An opqaue type */
final val Opaque: FlagSet = typeFlag(12, "opaque")

final val MutableOrOpaque: FlagSet = Mutable.toCommonFlags

/** Symbol is local to current class (i.e. private[this] or protected[this]
* pre: Private or Protected are also set
*/
Expand All @@ -263,7 +268,7 @@ object Flags {
*/
final val ParamAccessor: FlagSet = termFlag(14, "<paramaccessor>")

/** A value or class implementing a module */
/** A value or class implementing a module */
final val Module: FlagSet = commonFlag(15, "module")
final val ModuleVal: FlagSet = Module.toTermFlags
final val ModuleClass: FlagSet = Module.toTypeFlags
Expand Down Expand Up @@ -435,15 +440,20 @@ object Flags {
// --------- Combined Flag Sets and Conjunctions ----------------------

/** Flags representing source modifiers */
final val SourceModifierFlags: FlagSet =
commonFlags(Private, Protected, Abstract, Final, Inline,
Sealed, Case, Implicit, Override, AbsOverride, Lazy, JavaStatic, Erased)
private val CommonSourceModifierFlags: FlagSet =
commonFlags(Private, Protected, Final, Case, Implicit, Override, JavaStatic)

final val TypeSourceModifierFlags: FlagSet =
CommonSourceModifierFlags.toTypeFlags | Abstract | Sealed | Opaque

final val TermSourceModifierFlags: FlagSet =
CommonSourceModifierFlags.toTermFlags | Inline | AbsOverride | Lazy | Erased

/** Flags representing modifiers that can appear in trees */
final val ModifierFlags: FlagSet =
SourceModifierFlags | Module | Param | Synthetic | Package | Local |
commonFlags(Mutable)
// | Trait is subsumed by commonFlags(Lazy) from SourceModifierFlags
TypeSourceModifierFlags.toCommonFlags |
TermSourceModifierFlags.toCommonFlags |
commonFlags(Module, Param, Synthetic, Package, Local, Mutable, Trait)

assert(ModifierFlags.isTermFlags && ModifierFlags.isTypeFlags)

Expand All @@ -454,7 +464,7 @@ object Flags {
final val FromStartFlags: FlagSet =
Module | Package | Deferred | Method.toCommonFlags |
HigherKinded.toCommonFlags | Param | ParamAccessor.toCommonFlags |
Scala2ExistentialCommon | Mutable.toCommonFlags | Touched | JavaStatic |
Scala2ExistentialCommon | MutableOrOpaque | Touched | JavaStatic |
CovariantOrOuter | ContravariantOrLabel | CaseAccessor.toCommonFlags |
NonMember | ImplicitCommon | Permanent | Synthetic |
SuperAccessorOrScala2x | Inline
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Periods.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ abstract class Periods { self: Context =>
val period = this.period
period == p ||
period.runId == p.runId &&
this.phases(period.phaseId).sameParentsStartId ==
this.phases(p.phaseId).sameParentsStartId
this.phases(period.phaseId).sameBaseTypesStartId ==
this.phases(p.phaseId).sameBaseTypesStartId
}
}

Expand Down
13 changes: 10 additions & 3 deletions compiler/src/dotty/tools/dotc/core/Phases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,9 @@ object Phases {
/** Can this transform change the parents of a class? */
def changesParents: Boolean = false

/** Can this transform change the base types of a type? */
def changesBaseTypes: Boolean = changesParents

def exists: Boolean = true

def initContext(ctx: FreshContext): Unit = ()
Expand All @@ -333,6 +336,7 @@ object Phases {

private[this] var mySameMembersStartId = NoPhaseId
private[this] var mySameParentsStartId = NoPhaseId
private[this] var mySameBaseTypesStartId = NoPhaseId

/** The sequence position of this phase in the given context where 0
* is reserved for NoPhase and the first real phase is at position 1.
Expand All @@ -353,19 +357,22 @@ object Phases {
// id of first phase where all symbols are guaranteed to have the same members as in this phase
final def sameParentsStartId: Int = mySameParentsStartId
// id of first phase where all symbols are guaranteed to have the same parents as in this phase
final def sameBaseTypesStartId: Int = mySameBaseTypesStartId
// id of first phase where all symbols are guaranteed to have the same base tpyes as in this phase

protected[Phases] def init(base: ContextBase, start: Int, end: Int): Unit = {
if (start >= FirstPhaseId)
assert(myPeriod == Periods.InvalidPeriod, s"phase $this has already been used once; cannot be reused")
assert(start <= Periods.MaxPossiblePhaseId, s"Too many phases, Period bits overflow")
myBase = base
myPeriod = Period(NoRunId, start, end)
myErasedTypes = prev.getClass == classOf[Erasure] || prev.erasedTypes
myFlatClasses = prev.getClass == classOf[Flatten] || prev.flatClasses
myRefChecked = prev.getClass == classOf[RefChecks] || prev.refChecked
myErasedTypes = prev.getClass == classOf[Erasure] || prev.erasedTypes
myFlatClasses = prev.getClass == classOf[Flatten] || prev.flatClasses
myRefChecked = prev.getClass == classOf[RefChecks] || prev.refChecked
myLabelsReordered = prev.getClass == classOf[LabelDefs] || prev.labelsReordered
mySameMembersStartId = if (changesMembers) id else prev.sameMembersStartId
mySameParentsStartId = if (changesParents) id else prev.sameParentsStartId
mySameBaseTypesStartId = if (changesBaseTypes) id else prev.sameBaseTypesStartId
}

protected[Phases] def init(base: ContextBase, id: Int): Unit = init(base, id, id)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/StdNames.scala
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,6 @@ object StdNames {
val WHILE_PREFIX: N = "while$"
val DEFAULT_EXCEPTION_NAME: N = "ex$"
val INITIALIZER_PREFIX: N = "initial$"
val COMPANION_MODULE_METHOD: N = "companion$module"
val COMPANION_CLASS_METHOD: N = "companion$class"
val BOUNDTYPE_ANNOT: N = "$boundType$"
val QUOTE: N = "'"
val TYPE_QUOTE: N = "type_'"
Expand Down Expand Up @@ -188,6 +186,7 @@ object StdNames {
final val EQUALS_PATTERN: N = "<equals>"
final val LOCAL_CHILD: N = "<local child>"
final val REPEATED_PARAM_CLASS: N = "<repeated>"
final val OPAQUE_ALIAS: N = "<opaque>"
final val WILDCARD_STAR: N = "_*"
final val REIFY_TREECREATOR_PREFIX: N = "$treecreator"
final val REIFY_TYPECREATOR_PREFIX: N = "$typecreator"
Expand Down Expand Up @@ -245,6 +244,7 @@ object StdNames {

// Compiler-internal
val ANYname: N = "<anyname>"
val COMPANION: N = "<companion>"
val CONSTRUCTOR: N = "<init>"
val STATIC_CONSTRUCTOR: N = "<clinit>"
val DEFAULT_CASE: N = "defaultCase$"
Expand Down
Loading