Skip to content

Commit

Permalink
Inline -> Transparent
Browse files Browse the repository at this point in the history
 - Make all inlining during typer be transparent.
 - Drop inline modifier
 - Update reference docs

So far, this is just an update of the basic inline feature, with renamings everywhere.
Typelevel programming with `transparent` is still missing.
  • Loading branch information
odersky committed Jul 26, 2018
1 parent 632abc1 commit cbb7573
Show file tree
Hide file tree
Showing 213 changed files with 609 additions and 1,865 deletions.
2 changes: 1 addition & 1 deletion bench/tests/power-macro/PowerMacro.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import scala.quoted.Expr

object PowerMacro {

inline def power(inline n: Long, x: Double) = ~powerCode(n, '(x))
transparent def power(transparent n: Long, x: Double) = ~powerCode(n, '(x))

def powerCode(n: Long, x: Expr[Double]): Expr[Double] =
if (n == 0) '(1.0)
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
* Singleton type bounds (see SIP 23). Presumably
*
* object O1 { val x: Singleton = 42; println("43") }
* object O2 { inline val x = 42; println("43") }
* object O2 { transparent val x = 42; println("43") }
*
* should behave differently.
*
Expand All @@ -475,7 +475,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
* O2.x = 42
*
* Revisit this issue once we have implemented `inline`. Then we can demand
* purity of the prefix unless the selection goes to an inline val.
* purity of the prefix unless the selection goes to a transparent val.
*
* Note: This method should be applied to all term tree nodes that are not literals,
* that can be idempotent, and that can have constant types. So far, only nodes
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ object Trees {
case class Inlined[-T >: Untyped] private[ast] (call: tpd.Tree, bindings: List[MemberDef[T]], expansion: Tree[T])
extends Tree[T] {
type ThisTree[-T >: Untyped] = Inlined[T]
override def initialPos = call.pos
}

/** A type tree that represents an existing or inferred type */
Expand Down
2 changes: 0 additions & 2 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,6 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {

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

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

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

case class Enum() extends Mod(Flags.Enum)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Annotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ object Annotations {
}

/** An annotation indicating the body of a right-hand side,
* typically of an inline method. Treated specially in
* typically of a transparent method. Treated specially in
* pickling/unpickling and TypeTreeMaps
*/
abstract class BodyAnnotation extends Annotation {
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -730,8 +730,8 @@ class Definitions {
def ImplicitNotFoundAnnot(implicit ctx: Context) = ImplicitNotFoundAnnotType.symbol.asClass
lazy val ForceInlineAnnotType = ctx.requiredClassRef("scala.forceInline")
def ForceInlineAnnot(implicit ctx: Context) = ForceInlineAnnotType.symbol.asClass
lazy val InlineParamAnnotType = ctx.requiredClassRef("scala.annotation.internal.InlineParam")
def InlineParamAnnot(implicit ctx: Context) = InlineParamAnnotType.symbol.asClass
lazy val TransparentParamAnnotType = ctx.requiredClassRef("scala.annotation.internal.TransparentParam")
def TransparentParamAnnot(implicit ctx: Context) = TransparentParamAnnotType.symbol.asClass
lazy val InvariantBetweenAnnotType = ctx.requiredClassRef("scala.annotation.internal.InvariantBetween")
def InvariantBetweenAnnot(implicit ctx: Context) = InvariantBetweenAnnotType.symbol.asClass
lazy val MigrationAnnotType = ctx.requiredClassRef("scala.annotation.migration")
Expand Down
28 changes: 11 additions & 17 deletions compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,8 @@ object Flags {
/** A method that has default params */
final val DefaultParameterized = termFlag(27, "<defaultparam>")

/** Symbol is inlined */
final val Inline = commonFlag(29, "inline")
/** Labelled with `transparent` modifier */
final val Transparent = commonFlag(29, "transparent")

/** Symbol is defined by a Java class */
final val JavaDefined = commonFlag(30, "<java>")
Expand Down Expand Up @@ -363,9 +363,6 @@ object Flags {
/** Symbol is a Java default method */
final val DefaultMethod = termFlag(38, "<defaultmethod>")

/** Labelled with `transparent` modifier */
final val Transparent = termFlag(39, "transparent")

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

Expand Down Expand Up @@ -439,7 +436,7 @@ object Flags {

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

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

/** 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 @@ -551,23 +548,20 @@ object Flags {
/** Either method or lazy or deferred */
final val MethodOrLazyOrDeferred = Method | Lazy | Deferred

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

/** A private method */
final val PrivateMethod = allOf(Private, Method)

/** A private accessor */
final val PrivateAccessor = allOf(Private, Accessor)

/** An inline method */
final val InlineMethod = allOf(Inline, Method)

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

/** An inline parameter */
final val InlineParam = allOf(Inline, Param)
/** A transparent parameter */
final val TransparentParam = allOf(Transparent, Param)

/** An enum case */
final val EnumCase = allOf(Enum, Case)
Expand All @@ -593,8 +587,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, inline, or transparent */
final val FinalOrInlineOrTransparent = Final | Inline | Transparent.toCommonFlags
/** value that's final or transparent */
final val FinalOrTransparent = Final | Transparent

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

def isSkolem: Boolean = name == nme.SKOLEM

def isInlinedMethod(implicit ctx: Context): Boolean =
is(InlineMethod, butNot = Accessor)

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

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,
* because the Scala library does not always follow the right conventions.
Expand Down
10 changes: 5 additions & 5 deletions compiler/src/dotty/tools/dotc/core/Types.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2969,18 +2969,18 @@ object Types {
abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { self =>

/** Produce method type from parameter symbols, with special mappings for repeated
* and inline parameters:
* and transparent parameters:
* - replace @repeated annotations on Seq or Array types by <repeated> types
* - add @inlineParam to inline call-by-value parameters
* - add @inlineParam to transparent call-by-value parameters
*/
def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = {
def translateInline(tp: Type): Type = tp match {
def translateTransparent(tp: Type): Type = tp match {
case _: ExprType => tp
case _ => AnnotatedType(tp, Annotation(defn.InlineParamAnnot))
case _ => AnnotatedType(tp, Annotation(defn.TransparentParamAnnot))
}
def paramInfo(param: Symbol) = {
val paramType = param.info.annotatedToRepeated
if (param.is(Inline)) translateInline(paramType) else paramType
if (param.is(Transparent)) translateTransparent(paramType) else paramType
}

apply(params.map(_.name.asTermName))(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import collection.mutable
import TastyBuffer._
import util.Positions._

class PositionPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr]) {
class PositionPickler(pickler: TastyPickler, addrOfTree: untpd.Tree => Option[Addr]) {
val buf = new TastyBuffer(5000)
pickler.newSection("Positions", buf)
import buf._
Expand Down Expand Up @@ -62,8 +62,8 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr
}

def traverse(x: Any): Unit = x match {
case x: Tree @unchecked =>
val pos = if (x.isInstanceOf[MemberDef]) x.pos else x.pos.toSynthetic
case x: untpd.Tree =>
val pos = if (x.isInstanceOf[untpd.MemberDef]) x.pos else x.pos.toSynthetic
if (pos.exists && (pos != x.initialPos.toSynthetic || alwaysNeedsPos(x))) {
addrOfTree(x) match {
case Some(addr) if !pickledIndices.contains(addr.index) =>
Expand All @@ -75,7 +75,7 @@ class PositionPickler(pickler: TastyPickler, addrOfTree: tpd.Tree => Option[Addr
}
//else if (x.pos.exists) println(i"skipping $x")
x match {
case x: MemberDef @unchecked =>
case x: untpd.MemberDef @unchecked =>
for (ann <- x.symbol.annotations) traverse(ann.tree)
case _ =>
}
Expand Down
7 changes: 2 additions & 5 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,8 @@ Standard-Section: "ASTs" TopLevelStat*
ERASED
LAZY
OVERRIDE
INLINE
TRANSPARENT
MACRO // inline method containing toplevel splices
MACRO // transparent method containing toplevel splices
STATIC // mapped to static Java member
OBJECT // an object or its class
TRAIT // a trait
Expand Down Expand Up @@ -296,7 +295,7 @@ object TastyFormat {
final val IMPLICIT = 13
final val LAZY = 14
final val OVERRIDE = 15
final val INLINE = 16

final val TRANSPARENT = 17
final val STATIC = 18
final val OBJECT = 19
Expand Down Expand Up @@ -473,7 +472,6 @@ object TastyFormat {
| ERASED
| LAZY
| OVERRIDE
| INLINE
| TRANSPARENT
| MACRO
| STATIC
Expand Down Expand Up @@ -530,7 +528,6 @@ object TastyFormat {
case ERASED => "ERASED"
case LAZY => "LAZY"
case OVERRIDE => "OVERRIDE"
case INLINE => "INLINE"
case TRANSPARENT => "TRANSPARENT"
case MACRO => "MACRO"
case STATIC => "STATIC"
Expand Down
4 changes: 1 addition & 3 deletions compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,6 @@ class TreePickler(pickler: TastyPickler) {
if (flags.is(Final, butNot = Module)) writeByte(FINAL)
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)
Expand Down Expand Up @@ -637,8 +636,7 @@ class TreePickler(pickler: TastyPickler) {
// a different toplevel class, it is impossible to pickle a reference to it.
// Such annotations will be reconstituted when unpickling the child class.
// See tests/pickling/i3149.scala
case _ => ann.symbol == defn.BodyAnnot && owner.isInlinedMethod
// bodies of inlined (but not transparent) methods are reconstituted automatically when unpickling
case _ => false
}

def pickleAnnotation(owner: Symbol, ann: Annotation)(implicit ctx: Context) =
Expand Down
12 changes: 0 additions & 12 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -549,12 +549,6 @@ class TreeUnpickler(reader: TastyReader,
sym.completer.withDecls(newScope)
forkAt(templateStart).indexTemplateParams()(localContext(sym))
}
else if (sym.isInlinedMethod)
sym.addAnnotation(LazyBodyAnnotation { ctx0 =>
implicit val ctx: Context = localContext(sym)(ctx0).addMode(Mode.ReadPositions)
// avoids space leaks by not capturing the current context
forkAt(rhsStart).readTerm()
})
goto(start)
sym
}
Expand Down Expand Up @@ -590,7 +584,6 @@ class TreeUnpickler(reader: TastyReader,
case ERASED => addFlag(Erased)
case LAZY => addFlag(Lazy)
case OVERRIDE => addFlag(Override)
case INLINE => addFlag(Inline)
case TRANSPARENT => addFlag(Transparent)
case MACRO => addFlag(Macro)
case STATIC => addFlag(JavaStatic)
Expand Down Expand Up @@ -741,11 +734,6 @@ class TreeUnpickler(reader: TastyReader,
def readRhs(implicit ctx: Context) =
if (nothingButMods(end))
EmptyTree
else if (sym.isInlinedMethod)
// The body of an inline method is stored in an annotation, so no need to unpickle it again
new Trees.Lazy[Tree] {
def complete(implicit ctx: Context) = typer.Inliner.bodyToInline(sym)
}
else
readLater(end, rdr => ctx => rdr.readTerm()(ctx.retractMode(Mode.InSuperCall)))

Expand Down
6 changes: 2 additions & 4 deletions compiler/src/dotty/tools/dotc/parsing/Parsers.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1679,7 +1679,6 @@ object Parsers {
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()
Expand Down Expand Up @@ -1791,7 +1790,6 @@ object Parsers {
*/
def annot() =
adjustStart(accept(AT)) {
if (in.token == INLINE) in.token = BACKQUOTED_IDENT // allow for now
ensureApplied(parArgumentExprss(wrapNew(simpleType())))
}

Expand Down Expand Up @@ -1888,15 +1886,15 @@ object Parsers {
addMod(mods, mod)
}
else {
if (!(mods.flags &~ (ParamAccessor | Inline)).isEmpty)
if (!(mods.flags &~ (ParamAccessor | Transparent)).isEmpty)
syntaxError("`val' or `var' expected")
if (firstClauseOfCaseClass) mods
else mods | PrivateLocal
}
}
}
else {
if (in.token == INLINE) mods = addModifier(mods)
if (in.token == TRANSPARENT) mods = addModifier(mods)
mods = atPos(start) { mods | Param }
}
atPos(start, nameStart) {
Expand Down
4 changes: 3 additions & 1 deletion compiler/src/dotty/tools/dotc/parsing/Scanners.scala
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,9 @@ object Scanners {

private def handleMigration(keyword: Token): Token =
if (!isScala2Mode) keyword
else if (keyword == INLINE) treatAsIdent()
else if ( keyword == ENUM
|| keyword == ERASED
|| keyword == TRANSPARENT) treatAsIdent()
else keyword


Expand Down
14 changes: 7 additions & 7 deletions compiler/src/dotty/tools/dotc/parsing/Tokens.scala
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,9 @@ abstract class TokensCommon {
//final val LAZY = 59; enter(LAZY, "lazy")
//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 TRANSPARENT = 62; enter(TRANSPARENT, "transparent")
//final val ENUM = 63; enter(ENUM, "enum")
//final val ERASED = 64; enter(ERASED, "erased")

/** special symbols */
final val COMMA = 70; enter(COMMA, "','")
Expand Down Expand Up @@ -175,10 +176,9 @@ object Tokens extends TokensCommon {
final val LAZY = 59; enter(LAZY, "lazy")
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 TRANSPARENT = 63; enter(TRANSPARENT, "transparent")
final val ENUM = 64; enter(ENUM, "enum")
final val ERASED = 65; enter(ERASED, "erased")
final val TRANSPARENT = 62; enter(TRANSPARENT, "transparent")
final val ENUM = 63; enter(ENUM, "enum")
final val ERASED = 64; enter(ERASED, "erased")

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

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

final val accessModifierTokens = BitSet(
PRIVATE, PROTECTED)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/quoted/Toolbox.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ object Toolbox {
case expr: LiftedExpr[T] =>
expr.value
case expr: TastyTreeExpr[Tree] @unchecked =>
throw new Exception("Cannot call `Expr.run` on an `Expr` that comes from an inline macro argument.")
throw new Exception("Cannot call `Expr.run` on an `Expr` that comes from a transparent macro argument.")
case _ =>
synchronized(driver.run(expr, settings))
}
Expand Down
Loading

0 comments on commit cbb7573

Please sign in to comment.