diff options
-rw-r--r-- | src/dotty/tools/dotc/config/ScalaSettings.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Flags.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/StdNames.scala | 1 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/Parsers.scala | 19 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/Scanners.scala | 29 | ||||
-rw-r--r-- | src/dotty/tools/dotc/parsing/Tokens.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/SyntaxHighlighting.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Namer.scala | 15 | ||||
-rw-r--r-- | tests/neg/inlineAccess/C_1.scala | 3 | ||||
-rw-r--r-- | tests/pos/rbtree.scala | 10 | ||||
-rw-r--r-- | tests/run/inline/inlines_1.scala | 12 | ||||
-rw-r--r-- | tests/run/inlineLazy.scala | 6 | ||||
-rw-r--r-- | tests/run/inlinePower/power_1.scala | 3 | ||||
-rw-r--r-- | tests/run/inlinePrivates.scala | 32 | ||||
-rw-r--r-- | tests/run/inlinedAssign.scala | 6 |
15 files changed, 80 insertions, 70 deletions
diff --git a/src/dotty/tools/dotc/config/ScalaSettings.scala b/src/dotty/tools/dotc/config/ScalaSettings.scala index 42e761c2e..ff17a9939 100644 --- a/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -121,7 +121,6 @@ class ScalaSettings extends Settings.SettingGroup { val debugOwners = BooleanSetting("-Ydebug-owners", "Print all owners of definitions (requires -Yprint-syms)") //val doc = BooleanSetting ("-Ydoc", "Generate documentation") val termConflict = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error") - val inline = BooleanSetting("-Yinline", "Perform inlining when possible.") val inlineHandlers = BooleanSetting("-Yinline-handlers", "Perform exception handler inlining when possible.") val YinlinerWarnings = BooleanSetting("-Yinline-warnings", "Emit inlining warnings. (Normally surpressed due to high volume)") val Ylinearizer = ChoiceSetting("-Ylinearizer", "which", "Linearizer to use", List("normal", "dfs", "rpo", "dump"), "rpo") diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala index 0cdae6b98..bc5953a2c 100644 --- a/src/dotty/tools/dotc/core/Flags.scala +++ b/src/dotty/tools/dotc/core/Flags.scala @@ -450,7 +450,7 @@ object Flags { AccessFlags | Module | Package | Deferred | Final | MethodOrHKCommon | Param | ParamAccessor | Scala2ExistentialCommon | Mutable.toCommonFlags | InSuperCall | Touched | JavaStatic | CovariantOrOuter | ContravariantOrLabel | ExpandedName | AccessorOrSealed | CaseAccessorOrBaseTypeArg | Fresh | Frozen | Erroneous | ImplicitCommon | Permanent | Synthetic | - LazyOrTrait | SuperAccessorOrScala2x | SelfNameOrImplClass + Inline | LazyOrTrait | SuperAccessorOrScala2x | SelfNameOrImplClass assert(FromStartFlags.isTermFlags && FromStartFlags.isTypeFlags) // TODO: Should check that FromStartFlags do not change in completion @@ -541,6 +541,9 @@ object Flags { /** A type parameter with synthesized name */ final val ExpandedTypeParam = allOf(ExpandedName, TypeParam) + /** An inline method */ + final val InlineMethod = allOf(Inline, Method) + /** A parameter or parameter accessor */ final val ParamOrAccessor = Param | ParamAccessor diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala index 9ef7caa68..c52264637 100644 --- a/src/dotty/tools/dotc/core/StdNames.scala +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -46,6 +46,7 @@ object StdNames { final val IFkw: N = kw("if") final val IMPLICITkw: N = kw("implicit") final val IMPORTkw: N = kw("import") + final val INLINEkw: N = kw("inline") final val LAZYkw: N = kw("lazy") final val MACROkw: N = kw("macro") final val MATCHkw: N = kw("match") diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 86330f3ab..2fd79f999 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -275,21 +275,12 @@ object Parsers { } finally inFunReturnType = saved } - private val isScala2Mode = - ctx.settings.language.value.contains(nme.Scala2.toString) - def migrationWarningOrError(msg: String, offset: Int = in.offset) = - if (isScala2Mode) + if (in.isScala2Mode) ctx.migrationWarning(msg, source atPos Position(offset)) else syntaxError(msg, offset) - /** Cannot use ctx.featureEnabled because accessing the context would force too much */ - private def testScala2Mode(msg: String, pos: Position = Position(in.offset)) = { - if (isScala2Mode) ctx.migrationWarning(msg, source atPos pos) - isScala2Mode - } - /* ---------- TREE CONSTRUCTION ------------------------------------------- */ /** Convert tree to formal parameter list @@ -1467,6 +1458,7 @@ object Parsers { case ABSTRACT => Abstract case FINAL => Final case IMPLICIT => ImplicitCommon + case INLINE => Inline case LAZY => Lazy case OVERRIDE => Override case PRIVATE => Private @@ -1570,7 +1562,10 @@ object Parsers { /** Annotation ::= `@' SimpleType {ParArgumentExprs} */ def annot() = - adjustStart(accept(AT)) { ensureApplied(parArgumentExprss(wrapNew(simpleType()))) } + adjustStart(accept(AT)) { + if (in.token == INLINE) in.token = BACKQUOTED_IDENT // allow for now + ensureApplied(parArgumentExprss(wrapNew(simpleType()))) + } def annotations(skipNewLines: Boolean = false): List[Tree] = { if (skipNewLines) newLineOptWhenFollowedBy(AT) @@ -1856,7 +1851,7 @@ object Parsers { val toInsert = if (in.token == LBRACE) s"$resultTypeStr =" else ": Unit " // trailing space ensures that `def f()def g()` works. - testScala2Mode(s"Procedure syntax no longer supported; `$toInsert' should be inserted here") && { + in.testScala2Mode(s"Procedure syntax no longer supported; `$toInsert' should be inserted here") && { patch(source, Position(in.lastOffset), toInsert) true } diff --git a/src/dotty/tools/dotc/parsing/Scanners.scala b/src/dotty/tools/dotc/parsing/Scanners.scala index b46ab6348..a1a21583c 100644 --- a/src/dotty/tools/dotc/parsing/Scanners.scala +++ b/src/dotty/tools/dotc/parsing/Scanners.scala @@ -12,7 +12,7 @@ import scala.annotation.{ switch, tailrec } import scala.collection.mutable import mutable.ListBuffer import Utility.isNameStart - +import rewrite.Rewrites.patch object Scanners { @@ -108,6 +108,7 @@ object Scanners { target.token = toToken(idx) } } + def toToken(idx: Int): Token /** Clear buffer and set string */ @@ -212,8 +213,22 @@ object Scanners { /** A buffer for comments */ val commentBuf = new StringBuilder + private def handleMigration(keyword: Token): Token = + if (!isScala2Mode) keyword + else if (keyword == INLINE) treatAsIdent() + else keyword + + + private def treatAsIdent() = { + testScala2Mode(i"$name is now a keyword, put in `...` to keep as an identifier") + patch(source, Position(offset), "`") + patch(source, Position(offset + name.length), "`") + IDENTIFIER + } + def toToken(idx: Int): Token = - if (idx >= 0 && idx <= lastKeywordStart) kwArray(idx) else IDENTIFIER + if (idx >= 0 && idx <= lastKeywordStart) handleMigration(kwArray(idx)) + else IDENTIFIER private class TokenData0 extends TokenData @@ -235,6 +250,16 @@ object Scanners { */ var sepRegions: List[Token] = List() +// Scala 2 compatibility + + val isScala2Mode = ctx.settings.language.value.contains(nme.Scala2.toString) + + /** Cannot use ctx.featureEnabled because accessing the context would force too much */ + def testScala2Mode(msg: String, pos: Position = Position(offset)) = { + if (isScala2Mode) ctx.migrationWarning(msg, source atPos pos) + isScala2Mode + } + // Get next token ------------------------------------------------------------ /** Are we directly in a string interpolation expression? diff --git a/src/dotty/tools/dotc/parsing/Tokens.scala b/src/dotty/tools/dotc/parsing/Tokens.scala index b490cd133..5324207db 100644 --- a/src/dotty/tools/dotc/parsing/Tokens.scala +++ b/src/dotty/tools/dotc/parsing/Tokens.scala @@ -91,6 +91,7 @@ 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") /** special symbols */ final val COMMA = 70; enter(COMMA, "','") @@ -171,6 +172,7 @@ 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") /** special symbols */ final val NEWLINE = 78; enter(NEWLINE, "end of statement", "new line") @@ -188,7 +190,7 @@ object Tokens extends TokensCommon { /** XML mode */ final val XMLSTART = 96; enter(XMLSTART, "$XMLSTART$<") // TODO: deprecate - final val alphaKeywords = tokenRange(IF, FORSOME) + final val alphaKeywords = tokenRange(IF, INLINE) final val symbolicKeywords = tokenRange(USCORE, VIEWBOUND) final val symbolicTokens = tokenRange(COMMA, VIEWBOUND) final val keywords = alphaKeywords | symbolicKeywords @@ -214,7 +216,7 @@ object Tokens extends TokensCommon { final val defIntroTokens = templateIntroTokens | dclIntroTokens final val localModifierTokens = BitSet( - ABSTRACT, FINAL, SEALED, IMPLICIT, LAZY) + ABSTRACT, FINAL, SEALED, IMPLICIT, INLINE, LAZY) final val accessModifierTokens = BitSet( PRIVATE, PROTECTED) diff --git a/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala b/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala index 67aa24243..83c428976 100644 --- a/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala +++ b/src/dotty/tools/dotc/printing/SyntaxHighlighting.scala @@ -22,7 +22,7 @@ object SyntaxHighlighting { private def annotation(str: String) = AnnotationColor + str + NoColor private val keywords: Seq[String] = for { - index <- IF to FORSOME // All alpha keywords + index <- IF to INLINE // All alpha keywords } yield tokenString(index) private val interpolationPrefixes = diff --git a/src/dotty/tools/dotc/typer/Namer.scala b/src/dotty/tools/dotc/typer/Namer.scala index 5e2ff4164..a33061453 100644 --- a/src/dotty/tools/dotc/typer/Namer.scala +++ b/src/dotty/tools/dotc/typer/Namer.scala @@ -562,11 +562,24 @@ class Namer { typer: Typer => protected def addAnnotations(denot: SymDenotation): Unit = original match { case original: untpd.MemberDef => + var hasInlineAnnot = false for (annotTree <- untpd.modsDeco(original).mods.annotations) { val cls = typedAheadAnnotation(annotTree) val ann = Annotation.deferred(cls, implicit ctx => typedAnnotation(annotTree)) denot.addAnnotation(ann) - if (cls == defn.InlineAnnot) addInlineInfo(denot, original) + if (cls == defn.InlineAnnot) { + hasInlineAnnot = true + addInlineInfo(denot, original) + } + } + if (!hasInlineAnnot && denot.is(InlineMethod)) { + // create a @inline annotation. Currently, the inlining trigger + // is really the annotation, not the flag. This is done so that + // we can still compile inline methods from Scala2x. Once we stop + // being compatible with Scala2 we should revise the logic to + // be based on the flag. Then creating a separate annotation becomes unnecessary. + denot.addAnnotation(Annotation(defn.InlineAnnot)) + addInlineInfo(denot, original) } case _ => } diff --git a/tests/neg/inlineAccess/C_1.scala b/tests/neg/inlineAccess/C_1.scala index 6db1ea787..349f5b150 100644 --- a/tests/neg/inlineAccess/C_1.scala +++ b/tests/neg/inlineAccess/C_1.scala @@ -2,7 +2,6 @@ package p { class C { protected def f(): Unit = () - @inline - def inl() = f() // error (when inlined): not accessible + inline def inl() = f() // error (when inlined): not accessible } } diff --git a/tests/pos/rbtree.scala b/tests/pos/rbtree.scala index 1401a1231..04c084596 100644 --- a/tests/pos/rbtree.scala +++ b/tests/pos/rbtree.scala @@ -430,12 +430,12 @@ object RedBlackTree { * An alternative is to implement the these classes using plain old Java code... */ sealed abstract class Tree[A, +B]( - @(inline @getter) final val key: A, - @(inline @getter) final val value: B, - @(inline @getter) final val left: Tree[A, B], - @(inline @getter) final val right: Tree[A, B]) + @(`inline` @getter) final val key: A, + @(`inline` @getter) final val value: B, + @(`inline` @getter) final val left: Tree[A, B], + @(`inline` @getter) final val right: Tree[A, B]) extends Serializable { - @(inline @getter) final val count: Int = 1 + RedBlackTree.count(left) + RedBlackTree.count(right) + @(`inline` @getter) final val count: Int = 1 + RedBlackTree.count(left) + RedBlackTree.count(right) def black: Tree[A, B] def red: Tree[A, B] } diff --git a/tests/run/inline/inlines_1.scala b/tests/run/inline/inlines_1.scala index 8189e6805..24f1c78fe 100644 --- a/tests/run/inline/inlines_1.scala +++ b/tests/run/inline/inlines_1.scala @@ -5,8 +5,7 @@ object inlines { final val monitored = false - @inline - def f(x: Int): Int = x * x + inline def f(x: Int): Int = x * x val hits = new mutable.HashMap[String, Int] { override def default(key: String): Int = 0 @@ -21,8 +20,7 @@ object inlines { @volatile private var stack: List[String] = Nil - @inline - def track[T](fn: String)(op: => T) = + inline def track[T](fn: String)(op: => T) = if (monitored) { stack = fn :: stack record(fn) @@ -34,9 +32,9 @@ object inlines { def f = "Outer.f" class Inner { val msg = " Inner" - @inline def m = msg - @inline def g = f - @inline def h = f ++ m + inline def m = msg + inline def g = f + inline def h = f ++ m } val inner = new Inner } diff --git a/tests/run/inlineLazy.scala b/tests/run/inlineLazy.scala deleted file mode 100644 index a8aa92498..000000000 --- a/tests/run/inlineLazy.scala +++ /dev/null @@ -1,6 +0,0 @@ -class Test { - - lazy val x: Int = 33 - - println(x) -} diff --git a/tests/run/inlinePower/power_1.scala b/tests/run/inlinePower/power_1.scala index 23da6009a..4e96d7caa 100644 --- a/tests/run/inlinePower/power_1.scala +++ b/tests/run/inlinePower/power_1.scala @@ -2,8 +2,7 @@ package p object pow { - @inline - def power(x: Double, n: Int): Double = + inline def power(x: Double, n: Int): Double = if (n == 0) 1.0 else if (n == 1) x else { diff --git a/tests/run/inlinePrivates.scala b/tests/run/inlinePrivates.scala index ade4592df..ce438ae8d 100644 --- a/tests/run/inlinePrivates.scala +++ b/tests/run/inlinePrivates.scala @@ -6,19 +6,19 @@ object Test { private var y: T = _ - @inline def get1 = x - @inline def get2[U](c: C[U]) = c.x + inline def get1 = x + inline def get2[U](c: C[U]) = c.x - @inline def foo1(x: Int) = foo(x) - @inline def foo2[U](c: C[U]) = c.foo(x) + inline def foo1(x: Int) = foo(x) + inline def foo2[U](c: C[U]) = c.foo(x) - @inline def set1(z: T) = { y = z; y } - @inline def set2[U](c: C[U]) = { c.y = c.x; c.y } + inline def set1(z: T) = { y = z; y } + inline def set2[U](c: C[U]) = { c.y = c.x; c.y } } object CC { private val x = 3 - @inline def get1 = x + inline def get1 = x } def main(args: Array[String]) = { @@ -29,24 +29,6 @@ object Test { assert(cc.foo2(cc) == 2) assert(cc.set1(3) == 3) assert(cc.set2(cc) == 2) -object Test { - - @inline - def swap[T](x: T, x_= : T => Unit, y: T, y_= : T => Unit) = { - val t = x - x_=(y) - y_=(t) - } - - def main(args: Array[String]) = { - var x = 1 - var y = 2 - @inline def setX(z: Int) = x = z - @inline def setY(z: Int) = y = z - swap[Int](x, setX, y, setY) - assert(x == 2 && y == 1) - } -} assert(CC.get1 == 3) } diff --git a/tests/run/inlinedAssign.scala b/tests/run/inlinedAssign.scala index b9a5d287d..bb81aea26 100644 --- a/tests/run/inlinedAssign.scala +++ b/tests/run/inlinedAssign.scala @@ -1,6 +1,6 @@ object Test { - @inline + @`inline` def swap[T](x: T, x_= : T => Unit, y: T, y_= : T => Unit) = { val t = x x_=(y) @@ -10,8 +10,8 @@ object Test { def main(args: Array[String]) = { var x = 1 var y = 2 - @inline def setX(z: Int) = x = z - @inline def setY(z: Int) = y = z + @`inline` def setX(z: Int) = x = z + @`inline` def setY(z: Int) = y = z swap[Int](x, setX, y, setY) assert(x == 2 && y == 1) } |