Skip to content

Back to the future: rewrite to inline #5109

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 6 commits into from
Sep 21, 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
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 {

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

def powerCode(n: Long, x: Expr[Double]): Expr[Double] =
if (n == 0) '(1.0)
Expand Down
8 changes: 4 additions & 4 deletions compiler/src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -464,11 +464,11 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
* Strictly speaking we can't replace `O.x` with `42`. But this would make
* most expressions non-constant. Maybe we can change the spec to accept this
* kind of eliding behavior. Or else enforce true purity in the compiler.
* The choice will be affected by what we will do with `transparent` and with
* The choice will be affected by what we will do with `inline` and with
* Singleton type bounds (see SIP 23). Presumably
*
* object O1 { val x: Singleton = 42; println("43") }
* object O2 { transparent val x = 42; println("43") }
* object O2 { inline val x = 42; println("43") }
*
* should behave differently.
*
Expand All @@ -478,8 +478,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
*
* O2.x = 42
*
* Revisit this issue once we have standardized on `transparent`. Then we can demand
* purity of the prefix unless the selection goes to a transparent val.
* Revisit this issue once we have standardized on `inline`. Then we can demand
* purity of the prefix unless the selection goes to a inline 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
20 changes: 10 additions & 10 deletions compiler/src/dotty/tools/dotc/ast/Trees.scala
Original file line number Diff line number Diff line change
Expand Up @@ -497,9 +497,9 @@ object Trees {
extends TermTree[T] {
type ThisTree[-T >: Untyped] = If[T]
}
class RewriteIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])
class InlineIf[T >: Untyped] private[ast] (cond: Tree[T], thenp: Tree[T], elsep: Tree[T])
extends If(cond, thenp, elsep) {
override def toString = s"RewriteIf($cond, $thenp, $elsep)"
override def toString = s"InlineIf($cond, $thenp, $elsep)"
}

/** A closure with an environment and a reference to a method.
Expand All @@ -521,9 +521,9 @@ object Trees {
extends TermTree[T] {
type ThisTree[-T >: Untyped] = Match[T]
}
class RewriteMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])
class InlineMatch[T >: Untyped] private[ast] (selector: Tree[T], cases: List[CaseDef[T]])
extends Match(selector, cases) {
override def toString = s"RewriteMatch($selector, $cases)"
override def toString = s"InlineMatch($selector, $cases)"
}

/** case pat if guard => body; only appears as child of a Match */
Expand Down Expand Up @@ -904,10 +904,10 @@ object Trees {
type Assign = Trees.Assign[T]
type Block = Trees.Block[T]
type If = Trees.If[T]
type RewriteIf = Trees.RewriteIf[T]
type InlineIf = Trees.InlineIf[T]
type Closure = Trees.Closure[T]
type Match = Trees.Match[T]
type RewriteMatch = Trees.RewriteMatch[T]
type InlineMatch = Trees.InlineMatch[T]
type CaseDef = Trees.CaseDef[T]
type Labeled = Trees.Labeled[T]
type Return = Trees.Return[T]
Expand Down Expand Up @@ -1038,9 +1038,9 @@ object Trees {
case _ => finalize(tree, untpd.Block(stats, expr))
}
def If(tree: Tree)(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If = tree match {
case tree: RewriteIf =>
case tree: InlineIf =>
if ((cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep)) tree
else finalize(tree, untpd.RewriteIf(cond, thenp, elsep))
else finalize(tree, untpd.InlineIf(cond, thenp, elsep))
case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree
case _ => finalize(tree, untpd.If(cond, thenp, elsep))
}
Expand All @@ -1049,9 +1049,9 @@ object Trees {
case _ => finalize(tree, untpd.Closure(env, meth, tpt))
}
def Match(tree: Tree)(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match = tree match {
case tree: RewriteMatch =>
case tree: InlineMatch =>
if ((selector eq tree.selector) && (cases eq tree.cases)) tree
else finalize(tree, untpd.RewriteMatch(selector, cases))
else finalize(tree, untpd.InlineMatch(selector, cases))
case tree: Match if (selector eq tree.selector) && (cases eq tree.cases) => tree
case _ => finalize(tree, untpd.Match(selector, cases))
}
Expand Down
8 changes: 3 additions & 5 deletions compiler/src/dotty/tools/dotc/ast/untpd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {

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

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

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

case class Enum() extends Mod(Flags.Enum)
}
Expand Down Expand Up @@ -275,10 +273,10 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def Assign(lhs: Tree, rhs: Tree): Assign = new Assign(lhs, rhs)
def Block(stats: List[Tree], expr: Tree): Block = new Block(stats, expr)
def If(cond: Tree, thenp: Tree, elsep: Tree): If = new If(cond, thenp, elsep)
def RewriteIf(cond: Tree, thenp: Tree, elsep: Tree): If = new RewriteIf(cond, thenp, elsep)
def InlineIf(cond: Tree, thenp: Tree, elsep: Tree): If = new InlineIf(cond, thenp, elsep)
def Closure(env: List[Tree], meth: Tree, tpt: Tree): Closure = new Closure(env, meth, tpt)
def Match(selector: Tree, cases: List[CaseDef]): Match = new Match(selector, cases)
def RewriteMatch(selector: Tree, cases: List[CaseDef]): Match = new RewriteMatch(selector, cases)
def InlineMatch(selector: Tree, cases: List[CaseDef]): Match = new InlineMatch(selector, cases)
def CaseDef(pat: Tree, guard: Tree, body: Tree): CaseDef = new CaseDef(pat, guard, body)
def Labeled(bind: Bind, expr: Tree): Labeled = new Labeled(bind, expr)
def Return(expr: Tree, from: Tree): Return = new Return(expr, from)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class ScalaSettings extends Settings.SettingGroup {
val pageWidth = IntSetting("-pagewidth", "Set page width", 80)
val strict = BooleanSetting("-strict", "Use strict type rules, which means some formerly legal code does not typecheck anymore.")
val language = MultiStringSetting("-language", "feature", "Enable one or more language features.")
val `rewrite` = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with -language:Scala2 rewrites sources to migrate to new syntax")
val rewrite = OptionSetting[Rewrites]("-rewrite", "When used in conjunction with -language:Scala2 rewrites sources to migrate to new syntax")
val silentWarnings = BooleanSetting("-nowarn", "Silence all warnings.")
val fromTasty = BooleanSetting("-from-tasty", "Compile classes from tasty in classpath. The arguments are used as class names.")

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 a rewrite or transparent method. Treated specially in
* typically of an inline 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 @@ -764,8 +764,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 TransparentParamAnnotType = ctx.requiredClassRef("scala.annotation.internal.TransparentParam")
def TransparentParamAnnot(implicit ctx: Context) = TransparentParamAnnotType.symbol.asClass
lazy val InlineParamAnnotType = ctx.requiredClassRef("scala.annotation.internal.InlineParam")
def InlineParamAnnot(implicit ctx: Context) = InlineParamAnnotType.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
34 changes: 14 additions & 20 deletions compiler/src/dotty/tools/dotc/core/Flags.scala
Original file line number Diff line number Diff line change
Expand Up @@ -283,8 +283,8 @@ object Flags {
*/
final val Synthetic = commonFlag(18, "<synthetic>")

/** Labelled with `rewrite` modifier */
final val Rewrite = commonFlag(19, "rewrite")
/** Labelled with `inline` modifier */
final val Inline = commonFlag(19, "inline")

/** A covariant type variable / an outer accessor */
final val CovariantOrOuter = commonFlag(20, "")
Expand Down Expand Up @@ -329,9 +329,6 @@ object Flags {
/** A method that has default params */
final val DefaultParameterized = termFlag(27, "<defaultparam>")

/** 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 @@ -436,7 +433,7 @@ object Flags {

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

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

/** 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,26 +548,23 @@ object Flags {
/** Assumed to be pure */
final val StableOrErased = Stable | Erased

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

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

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

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

/** A rewrite method */
final val RewriteMethod = allOf(Rewrite, Method)
/** An inline method */
final val InlineMethod = allOf(Inline, Method)

/** An implicit rewrite method */
final val ImplicitRewriteMethod = allOf(Rewrite, Implicit, Method)
/** An implicit inline method */
final val ImplicitInlineMethod = allOf(Inline, Implicit, Method)

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

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

/** A covariant type parameter instance */
final val LocalCovariant = allOf(Local, Covariant)
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Mode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ object Mode {
/** We are in the IDE */
val Interactive = newMode(20, "Interactive")

/** We are typing the body of a transparent or rewrite method */
/** We are typing the body of an inline method */
val InlineableBody = newMode(21, "InlineableBody")

/** Read comments from definitions when unpickling from TASTY */
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/NameKinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,8 @@ object NameKinds {
val SuperArgName = new UniqueNameKind("$superArg$")
val DocArtifactName = new UniqueNameKind("$doc")
val UniqueInlineName = new UniqueNameKind("$i")
val RewriteScrutineeName = new UniqueNameKind("$scrutinee")
val RewriteBinderName = new UniqueNameKind("$elem")
val InlineScrutineeName = new UniqueNameKind("$scrutinee")
val InlineBinderName = new UniqueNameKind("$elem")

/** A kind of unique extension methods; Unlike other unique names, these can be
* unmangled.
Expand Down
15 changes: 4 additions & 11 deletions compiler/src/dotty/tools/dotc/core/SymDenotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -779,17 +779,10 @@ object SymDenotations {

def isSkolem: Boolean = name == nme.SKOLEM

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

def isRewriteMethod(implicit ctx: Context): Boolean =
is(RewriteMethod, butNot = AccessorOrSynthetic)

/** A transparent or rewrite method */
def isInlineable(implicit ctx: Context): Boolean =
is(TransparentMethod) || is(RewriteMethod)

/** An erased value or a rewrite method, excluding @forceInline annotated methods.
/** An erased value or an inline method, excluding @forceInline annotated methods.
* The latter have to be kept around to get to parity with Scala.
* This is necessary at least until we have full bootstrap. Right now
* dotty-bootstrapped involves running the Dotty compiler compiled with Scala 2 with
Expand All @@ -799,7 +792,7 @@ object SymDenotations {
*/
def isEffectivelyErased(implicit ctx: Context): Boolean =
is(Erased) ||
isRewriteMethod && unforcedAnnotation(defn.ForceInlineAnnot).isEmpty
isInlineMethod && unforcedAnnotation(defn.ForceInlineAnnot).isEmpty

/** ()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
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/TypeOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,8 @@ trait TypeOps { this: Context => // TODO: Make standalone object.
violations.toList
}

/** Are we in a rewrite method body? */
def inRewriteMethod = owner.ownersIterator.exists(_.isRewriteMethod)
/** Are we in an inline method body? */
def inInlineMethod = owner.ownersIterator.exists(_.isInlineMethod)

/** Is `feature` enabled in class `owner`?
* This is the case if one of the following two alternatives holds:
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 @@ -3031,18 +3031,18 @@ object Types {
abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] { self =>

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

apply(params.map(_.name.asTermName))(
Expand Down
15 changes: 6 additions & 9 deletions compiler/src/dotty/tools/dotc/core/tasty/TastyFormat.scala
Original file line number Diff line number Diff line change
Expand Up @@ -183,9 +183,8 @@ Standard-Section: "ASTs" TopLevelStat*
ERASED
LAZY
OVERRIDE
TRANSPARENT
REWRITE
MACRO // rewrite method containing toplevel splices
INLINE
MACRO // inline method containing toplevel splices
STATIC // mapped to static Java member
OBJECT // an object or its class
TRAIT // a trait
Expand Down Expand Up @@ -299,8 +298,8 @@ object TastyFormat {
final val IMPLICIT = 13
final val LAZY = 14
final val OVERRIDE = 15
final val TRANSPARENT = 16
final val REWRITE = 17

final val INLINE = 17
final val STATIC = 18
final val OBJECT = 19
final val TRAIT = 20
Expand Down Expand Up @@ -481,8 +480,7 @@ object TastyFormat {
| ERASED
| LAZY
| OVERRIDE
| TRANSPARENT
| REWRITE
| INLINE
| MACRO
| STATIC
| OBJECT
Expand Down Expand Up @@ -539,8 +537,7 @@ object TastyFormat {
case ERASED => "ERASED"
case LAZY => "LAZY"
case OVERRIDE => "OVERRIDE"
case TRANSPARENT => "TRANSPARENT"
case REWRITE => "REWRITE"
case INLINE => "INLINE"
case MACRO => "MACRO"
case STATIC => "STATIC"
case OBJECT => "OBJECT"
Expand Down
7 changes: 3 additions & 4 deletions compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -616,8 +616,7 @@ 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 Transparent) writeByte(TRANSPARENT)
if (flags is Rewrite) writeByte(REWRITE)
if (flags is Inline) writeByte(INLINE)
if (flags is Macro) writeByte(MACRO)
if (flags is JavaStatic) writeByte(STATIC)
if (flags is Module) writeByte(OBJECT)
Expand Down Expand Up @@ -782,13 +781,13 @@ class TreePickler(pickler: TastyPickler) {
case If(cond, thenp, elsep) =>
writeByte(IF)
withLength {
if (tree.isInstanceOf[untpd.RewriteIf]) writeByte(REWRITE)
if (tree.isInstanceOf[untpd.InlineIf]) writeByte(INLINE)
pickleUntyped(cond); pickleUntyped(thenp); pickleUntyped(elsep)
}
case Match(selector, cases) =>
writeByte(MATCH)
withLength {
if (tree.isInstanceOf[untpd.RewriteMatch]) writeByte(REWRITE)
if (tree.isInstanceOf[untpd.InlineMatch]) writeByte(INLINE)
pickleUntyped(selector); cases.foreach(pickleUntyped)
}
case CaseDef(pat, guard, rhs) =>
Expand Down
Loading