Skip to content

Add transparent methods #4622

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

Merged
merged 7 commits into from
Jun 7, 2018
Merged
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
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
/** An extractor for def of a closure contained the block of the closure. */
object closureDef {
def unapply(tree: Tree): Option[DefDef] = tree match {
case Block(Nil, expr) => unapply(expr)
case Block((meth @ DefDef(nme.ANON_FUN, _, _, _, _)) :: Nil, closure: Closure) =>
Some(meth)
case _ => None
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 @@ -132,6 +132,8 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {

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

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

case class Enum() extends Mod(Flags.Enum)
}

Expand Down
25 changes: 17 additions & 8 deletions compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,10 @@ object Flags {
/** Symbol is a Java default method */
final val DefaultMethod = termFlag(38, "<defaultmethod>")

/** Symbol is a Java enum */
/** Labelled with `transparent` modifier */
final val Transparent = termFlag(39, "transparent")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not make transparent a commonFlag, if we use it that way below anyways?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there are no transparent types, it should not apply to them.


/** Symbol is an enum class or enum case (if used with case) */
final val Enum = commonFlag(40, "<enum>")

/** Labeled with `erased` modifier (erased value) */
Expand Down Expand Up @@ -436,7 +439,7 @@ object Flags {

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

/** Flags representing modifiers that can appear in trees */
Expand All @@ -457,7 +460,7 @@ object Flags {
Scala2ExistentialCommon | Mutable.toCommonFlags | Touched | JavaStatic |
CovariantOrOuter | ContravariantOrLabel | CaseAccessor.toCommonFlags |
NonMember | ImplicitCommon | Permanent | Synthetic |
SuperAccessorOrScala2x | Inline
SuperAccessorOrScala2x | Inline | Transparent.toCommonFlags

/** Flags that are not (re)set when completing the denotation, or, if symbol is
* a top-level class or object, when completing the denotation once the class
Expand Down Expand Up @@ -513,7 +516,7 @@ object Flags {
/** Flags that can apply to a module val */
final val RetainedModuleValFlags: FlagSet = RetainedModuleValAndClassFlags |
Override | Final | Method | Implicit | Lazy |
Accessor | AbsOverride | Stable | Captured | Synchronized | Inline | Erased
Accessor | AbsOverride | Stable | Captured | Synchronized | Erased

/** Flags that can apply to a module class */
final val RetainedModuleClassFlags: FlagSet = RetainedModuleValAndClassFlags | ImplClass | Enum
Expand Down Expand Up @@ -548,8 +551,8 @@ object Flags {
/** Either method or lazy or deferred */
final val MethodOrLazyOrDeferred = Method | Lazy | Deferred

/** Labeled `private`, `final`, or `inline` */
final val PrivateOrFinalOrInline = Private | Final | Inline
/** Labeled `private`, `final`, `inline`, or `transparent` */
final val EffectivelyFinal = Private | Final | Inline | Transparent.toCommonFlags

/** A private method */
final val PrivateMethod = allOf(Private, Method)
Expand All @@ -560,6 +563,9 @@ object Flags {
/** An inline method */
final val InlineMethod = allOf(Inline, Method)

/** An transparent method */
final val TransparentMethod = allOf(Transparent, Method)

/** An inline parameter */
final val InlineParam = allOf(Inline, Param)

Expand All @@ -575,6 +581,9 @@ object Flags {
/** An accessor or label */
final val AccessorOrLabel = Accessor | Label

/** An accessor or a synthetic symbol */
final val AccessorOrSynthetic = Accessor | Synthetic

/** A synthetic or private definition */
final val SyntheticOrPrivate = Synthetic | Private

Expand All @@ -584,8 +593,8 @@ object Flags {
/** A deferred type member or parameter (these don't have right hand sides) */
final val DeferredOrTypeParam = Deferred | TypeParam

/** value that's final or inline */
final val FinalOrInline = Final | Inline
/** value that's final, inline, or transparent */
final val FinalOrInlineOrTransparent = Final | Inline | Transparent.toCommonFlags

/** A covariant type parameter instance */
final val LocalCovariant = allOf(Local, Covariant)
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/core/Mode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,4 @@ object Mode {

/** We are in the IDE */
val Interactive = newMode(20, "Interactive")

}
10 changes: 8 additions & 2 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -779,7 +779,13 @@ object SymDenotations {

def isSkolem: Boolean = name == nme.SKOLEM

def isInlineMethod(implicit ctx: Context): Boolean = is(InlineMethod, butNot = Accessor)
def isInlinedMethod(implicit ctx: Context): Boolean =
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the method's and the flag's name should match (so probably isInlineMethod, i.e. minus the d).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking if we keep something like inline as a modifier we should rename it to inlined instead. Then we don't have a clash with the @inline annotation, and it's a bit cleaner. transparent and inlined are both adjectives, whereas it's a stretch to call inline an adjective.

is(InlineMethod, butNot = Accessor)

def isTransparentMethod(implicit ctx: Context): Boolean =
is(TransparentMethod, butNot = Accessor)

def isInlineableMethod(implicit ctx: Context) = isInlinedMethod || isTransparentMethod

/** ()T and => T types should be treated as equivalent for this symbol.
* Note: For the moment, we treat Scala-2 compiled symbols as loose matching,
Expand Down Expand Up @@ -905,7 +911,7 @@ object SymDenotations {

/** A symbol is effectively final if it cannot be overridden in a subclass */
final def isEffectivelyFinal(implicit ctx: Context): Boolean =
is(PrivateOrFinalOrInline) || !owner.isClass || owner.is(ModuleOrFinal) || owner.isAnonymousClass
is(EffectivelyFinal) || !owner.isClass || owner.is(ModuleOrFinal) || owner.isAnonymousClass

/** The class containing this denotation which has the given effective name. */
final def enclosingClassNamed(name: Name)(implicit ctx: Context): Symbol = {
Expand Down
44 changes: 24 additions & 20 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,8 @@ Standard-Section: "ASTs" TopLevelStat*
ERASED
LAZY
OVERRIDE
INLINE // inline method
INLINE
TRANSPARENT
MACRO // inline method containing toplevel splices
STATIC // mapped to static Java member
OBJECT // an object or its class
Expand Down Expand Up @@ -280,25 +281,26 @@ object TastyFormat {
final val LAZY = 14
final val OVERRIDE = 15
final val INLINE = 16
final val STATIC = 17
final val OBJECT = 18
final val TRAIT = 19
final val ENUM = 20
final val LOCAL = 21
final val SYNTHETIC = 22
final val ARTIFACT = 23
final val MUTABLE = 24
final val LABEL = 25
final val FIELDaccessor = 26
final val CASEaccessor = 27
final val COVARIANT = 28
final val CONTRAVARIANT = 29
final val SCALA2X = 30
final val DEFAULTparameterized = 31
final val STABLE = 32
final val MACRO = 33
final val ERASED = 34
final val PARAMsetter = 35
final val TRANSPARENT = 17
final val STATIC = 18
final val OBJECT = 19
final val TRAIT = 20
final val ENUM = 21
final val LOCAL = 22
final val SYNTHETIC = 23
final val ARTIFACT = 24
final val MUTABLE = 25
final val LABEL = 26
final val FIELDaccessor = 27
final val CASEaccessor = 28
final val COVARIANT = 29
final val CONTRAVARIANT = 30
final val SCALA2X = 31
final val DEFAULTparameterized = 32
final val STABLE = 33
final val MACRO = 34
final val ERASED = 35
final val PARAMsetter = 36

// Cat. 2: tag Nat

Expand Down Expand Up @@ -446,6 +448,7 @@ object TastyFormat {
| LAZY
| OVERRIDE
| INLINE
| TRANSPARENT
| MACRO
| STATIC
| OBJECT
Expand Down Expand Up @@ -502,6 +505,7 @@ object TastyFormat {
case LAZY => "LAZY"
case OVERRIDE => "OVERRIDE"
case INLINE => "INLINE"
case TRANSPARENT => "TRANSPARENT"
case MACRO => "MACRO"
case STATIC => "STATIC"
case OBJECT => "OBJECT"
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ class TreePickler(pickler: TastyPickler) {
if (flags is Case) writeByte(CASE)
if (flags is Override) writeByte(OVERRIDE)
if (flags is Inline) writeByte(INLINE)
if (flags is Transparent) writeByte(TRANSPARENT)
if (flags is Macro) writeByte(MACRO)
if (flags is JavaStatic) writeByte(STATIC)
if (flags is Module) writeByte(OBJECT)
Expand Down
35 changes: 20 additions & 15 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -513,7 +513,7 @@ class TreeUnpickler(reader: TastyReader,
val rhsStart = currentAddr
val rhsIsEmpty = nothingButMods(end)
if (!rhsIsEmpty) skipTree()
val (givenFlags, annots, privateWithin) = readModifiers(end)
val (givenFlags, annotFns, privateWithin) = readModifiers(end)
pickling.println(i"creating symbol $name at $start with flags $givenFlags")
val flags = normalizeFlags(tag, givenFlags, name, isAbsType, rhsIsEmpty)
def adjustIfModule(completer: LazyType) =
Expand All @@ -532,13 +532,12 @@ class TreeUnpickler(reader: TastyReader,
rootd.symbol
case _ =>
val completer = adjustIfModule(new Completer(ctx.owner, subReader(start, end)))

if (isClass)
ctx.newClassSymbol(ctx.owner, name.asTypeName, flags, completer, privateWithin, coord)
else
ctx.newSymbol(ctx.owner, name, flags, completer, privateWithin, coord)
}
sym.annotations = annots
sym.annotations = annotFns.map(_(sym))
ctx.owner match {
case cls: ClassSymbol => cls.enter(sym)
case _ =>
Expand All @@ -548,7 +547,7 @@ class TreeUnpickler(reader: TastyReader,
sym.completer.withDecls(newScope)
forkAt(templateStart).indexTemplateParams()(localContext(sym))
}
else if (sym.isInlineMethod)
else if (sym.isInlineableMethod)
sym.addAnnotation(LazyBodyAnnotation { ctx0 =>
implicit val ctx: Context = localContext(sym)(ctx0).addMode(Mode.ReadPositions)
// avoids space leaks by not capturing the current context
Expand All @@ -561,9 +560,9 @@ class TreeUnpickler(reader: TastyReader,
/** Read modifier list into triplet of flags, annotations and a privateWithin
* boundary symbol.
*/
def readModifiers(end: Addr)(implicit ctx: Context): (FlagSet, List[Annotation], Symbol) = {
def readModifiers(end: Addr)(implicit ctx: Context): (FlagSet, List[Symbol => Annotation], Symbol) = {
var flags: FlagSet = EmptyFlags
var annots: List[Annotation] = Nil
var annotFns: List[Symbol => Annotation] = Nil
var privateWithin: Symbol = NoSymbol
while (currentAddr.index != end.index) {
def addFlag(flag: FlagSet) = {
Expand All @@ -588,6 +587,7 @@ class TreeUnpickler(reader: TastyReader,
case LAZY => addFlag(Lazy)
case OVERRIDE => addFlag(Override)
case INLINE => addFlag(Inline)
case TRANSPARENT => addFlag(Transparent)
case MACRO => addFlag(Macro)
case STATIC => addFlag(JavaStatic)
case OBJECT => addFlag(Module)
Expand All @@ -614,23 +614,25 @@ class TreeUnpickler(reader: TastyReader,
addFlag(Protected)
privateWithin = readType().typeSymbol
case ANNOTATION =>
annots = readAnnot(ctx) :: annots
annotFns = readAnnot(ctx) :: annotFns
case tag =>
assert(false, s"illegal modifier tag $tag at $currentAddr, end = $end")
}
}
(flags, annots.reverse, privateWithin)
(flags, annotFns.reverse, privateWithin)
}

private val readAnnot: Context => Annotation = {
private val readAnnot: Context => Symbol => Annotation = {
implicit ctx =>
readByte()
val end = readEnd()
val tp = readType()
val lazyAnnotTree = readLater(end, rdr => ctx => rdr.readTerm()(ctx))
Annotation.deferredSymAndTree(
implicit ctx => tp.typeSymbol,
implicit ctx => lazyAnnotTree.complete)
val lazyAnnotTree = readLaterWithOwner(end, rdr => ctx => rdr.readTerm()(ctx))

owner =>
Annotation.deferredSymAndTree(
implicit ctx => tp.typeSymbol,
implicit ctx => lazyAnnotTree(owner).complete)
}

/** Create symbols for the definitions in the statement sequence between
Expand Down Expand Up @@ -1153,10 +1155,13 @@ class TreeUnpickler(reader: TastyReader,
setPos(start, CaseDef(pat, guard, rhs))
}

def readLater[T <: AnyRef](end: Addr, op: TreeReader => Context => T)(implicit ctx: Context): Trees.Lazy[T] = {
def readLater[T <: AnyRef](end: Addr, op: TreeReader => Context => T)(implicit ctx: Context): Trees.Lazy[T] =
readLaterWithOwner(end, op)(ctx)(ctx.owner)

def readLaterWithOwner[T <: AnyRef](end: Addr, op: TreeReader => Context => T)(implicit ctx: Context): Symbol => Trees.Lazy[T] = {
val localReader = fork
goto(end)
new LazyReader(localReader, ctx.owner, ctx.mode, op)
owner => new LazyReader(localReader, owner, ctx.mode, op)
}

def readHole(end: Addr, isType: Boolean)(implicit ctx: Context): Tree = {
Expand Down
21 changes: 11 additions & 10 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1675,16 +1675,17 @@ object Parsers {
/* -------- MODIFIERS and ANNOTATIONS ------------------------------------------- */

private def modOfToken(tok: Int): Mod = tok match {
case ABSTRACT => Mod.Abstract()
case FINAL => Mod.Final()
case IMPLICIT => Mod.Implicit()
case ERASED => Mod.Erased()
case INLINE => Mod.Inline()
case LAZY => Mod.Lazy()
case OVERRIDE => Mod.Override()
case PRIVATE => Mod.Private()
case PROTECTED => Mod.Protected()
case SEALED => Mod.Sealed()
case ABSTRACT => Mod.Abstract()
case FINAL => Mod.Final()
case IMPLICIT => Mod.Implicit()
case ERASED => Mod.Erased()
case INLINE => Mod.Inline()
case TRANSPARENT => Mod.Transparent()
case LAZY => Mod.Lazy()
case OVERRIDE => Mod.Override()
case PRIVATE => Mod.Private()
case PROTECTED => Mod.Protected()
case SEALED => Mod.Sealed()
}

/** Drop `private' modifier when followed by a qualifier.
Expand Down
7 changes: 4 additions & 3 deletions compiler/src/dotty/tools/dotc/parsing/Tokens.scala
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,9 @@ object Tokens extends TokensCommon {
final val THEN = 60; enter(THEN, "then")
final val FORSOME = 61; enter(FORSOME, "forSome") // TODO: deprecate
final val INLINE = 62; enter(INLINE, "inline")
final val ENUM = 63; enter(ENUM, "enum")
final val ERASED = 64; enter(ERASED, "erased")
final val TRANSPARENT = 63; enter(TRANSPARENT, "transparent")
final val ENUM = 64; enter(ENUM, "enum")
final val ERASED = 65; enter(ERASED, "erased")

/** special symbols */
final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line")
Expand Down Expand Up @@ -226,7 +227,7 @@ object Tokens extends TokensCommon {
final val defIntroTokens = templateIntroTokens | dclIntroTokens

final val localModifierTokens = BitSet(
ABSTRACT, FINAL, SEALED, IMPLICIT, INLINE, LAZY, ERASED)
ABSTRACT, FINAL, SEALED, IMPLICIT, INLINE, TRANSPARENT, LAZY, ERASED)

final val accessModifierTokens = BitSet(
PRIVATE, PROTECTED)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
}

private def toTextOwner(tree: Tree[_]) =
"[owner = " ~ tree.symbol.owner.show ~ "]" provided ctx.settings.YprintDebugOwners.value
"[owner = " ~ tree.symbol.maybeOwner.show ~ "]" provided ctx.settings.YprintDebugOwners.value

protected def dclTextOr[T >: Untyped](tree: Tree[T])(treeText: => Text) =
toTextOwner(tree) ~ {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1575,7 +1575,7 @@ object messages {
private val varNote =
if (sym.is(Mutable)) "Note that variables need to be initialized to be defined."
else ""
val msg = hl"""only classes can have declared but undefined members"""
val msg = hl"""declaration of $sym not allowed here: only classes can have declared but undefined members"""
val kind = "Syntax"
val explanation = s"$varNote"
}
Expand Down
6 changes: 1 addition & 5 deletions compiler/src/dotty/tools/dotc/transform/PostTyper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase

def markAsMacro(c: Context): Unit =
if (c.owner eq c.outer.owner) markAsMacro(c.outer)
else if (c.owner.isInlineMethod) c.owner.setFlag(Macro)
else if (c.owner.isInlineableMethod) c.owner.setFlag(Macro)
else if (!c.outer.owner.is(Package)) markAsMacro(c.outer)

if (sym.isSplice || sym.isQuote) {
Expand All @@ -192,10 +192,6 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisPhase
}
else
transformSelect(tree, Nil)
case tree: Super =>
if (ctx.owner.enclosingMethod.isInlineMethod)
ctx.error(SuperCallsNotAllowedInline(ctx.owner), tree.pos)
super.transform(tree)
case tree: Apply =>
methPart(tree) match {
case Select(nu: New, nme.CONSTRUCTOR) if isCheckable(nu) =>
Expand Down
Loading