summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbuild.xml59
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala8
-rw-r--r--src/compiler/scala/tools/nsc/backend/icode/GenICode.scala19
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala29
-rw-r--r--src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala8
-rw-r--r--src/interactive/scala/tools/nsc/interactive/Response.scala10
-rw-r--r--src/library/scala/concurrent/Future.scala7
-rw-r--r--src/library/scala/concurrent/Promise.scala11
-rw-r--r--src/library/scala/sys/process/ProcessBuilder.scala2
-rw-r--r--src/reflect/scala/reflect/api/BuildUtils.scala7
-rw-r--r--src/reflect/scala/reflect/internal/BuildUtils.scala12
-rw-r--r--src/reflect/scala/reflect/internal/StdNames.scala1
-rw-r--r--src/reflect/scala/reflect/internal/TreeGen.scala8
-rw-r--r--test/files/neg/forgot-interpolator.check21
-rw-r--r--test/files/neg/forgot-interpolator.scala32
-rw-r--r--test/files/neg/macro-quasiquotes.check2
-rw-r--r--test/files/neg/t7848-interp-warn.check9
-rw-r--r--test/files/neg/t7848-interp-warn.flags1
-rw-r--r--test/files/neg/t7848-interp-warn.scala13
-rw-r--r--test/files/pos/t7864.flags1
-rw-r--r--test/files/pos/t7864.scala5
-rw-r--r--test/files/run/t6719.check1
-rw-r--r--test/files/run/t6719.scala8
-rw-r--r--test/files/run/t7852.check0
-rw-r--r--test/files/run/t7852.flags1
-rw-r--r--test/files/run/t7852.scala39
-rw-r--r--test/files/scalacheck/quasiquotes/TermConstructionProps.scala24
-rw-r--r--test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala20
-rw-r--r--versions.properties10
30 files changed, 326 insertions, 44 deletions
diff --git a/build.xml b/build.xml
index bd0642be33..b5e77832df 100755
--- a/build.xml
+++ b/build.xml
@@ -211,6 +211,11 @@ TODO:
<!-- Set up Ant contrib tasks so we can use <if><then><else> instead of the clunky `unless` attribute -->
<taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib-ant.dir}/ant-contrib.jar"/>
+ <property name="scala.ant.min.version" value="1.8.2"/>
+ <if><not><antversion atleast="${scala.ant.min.version}"/></not>
+ <then><fail message="Ant version ${scala.ant.min.version} is required. You are running ${ant.version}"/></then>
+ </if>
+
<!-- Add our maven ant tasks -->
<path id="maven-ant-tasks.classpath" path="${lib-ant.dir}/maven-ant-tasks-2.1.1.jar" />
<typedef resource="org/apache/maven/artifact/ant/antlib.xml" uri="urn:maven-artifact-ant" classpathref="maven-ant-tasks.classpath" />
@@ -1961,6 +1966,30 @@ TODO:
</copy>
</target>
+ <!--
+ A jar-like task that creates an OSGi source bundle. It adds the required MANIFEST.MF headers that allow
+ Eclipse to match sources with the corresponding binaries.
+ -->
+ <macrodef name="osgi.source.bundle">
+ <attribute name="destfile" description="The jar file name"/>
+ <attribute name="symbolicName" description="The original bundle symbolic name (without .source at the end)"/>
+ <attribute name="bundleName" description="A value for Bundle-Name, usually a textual description"/>
+ <element name="file-sets" description="A sequence of fileset elements to be included in the jar" optional="true" implicit="true"/>
+
+ <sequential>
+ <jar whenmanifestonly="fail" destfile="@{destFile}">
+ <file-sets/>
+ <manifest>
+ <attribute name="Manifest-Version" value="1.0"/>
+ <attribute name="Bundle-Name" value="@{bundleName}"/>
+ <attribute name="Bundle-SymbolicName" value="@{symbolicName}.source"/>
+ <attribute name="Bundle-Version" value="${osgi.version.number}"/>
+ <attribute name="Eclipse-SourceBundle" value="@{symbolicName};version=&quot;${osgi.version.number}&quot;;roots:=&quot;.&quot;" />
+ </manifest>
+ </jar>
+ </sequential>
+ </macrodef>
+
<target name="dist.src" depends="dist.base">
<mkdir dir="${dist.dir}/src"/>
<copy toDir="${dist.dir}/src">
@@ -1968,20 +1997,36 @@ TODO:
<file file="${scala-parser-combinators-sources}"/>
</copy>
- <jar whenmanifestonly="fail" destfile="${dist.dir}/src/scala-library-src.jar">
+ <osgi.source.bundle destfile="${dist.dir}/src/scala-library-src.jar"
+ symbolicName="org.scala-lang.scala-library"
+ bundleName="Scala Library Sources">
<fileset dir="${src.dir}/library"/>
<fileset dir="${src.dir}/continuations/library"/>
- </jar>
- <jar whenmanifestonly="fail" destfile="${dist.dir}/src/scala-actors-src.jar" basedir="${src.dir}/actors"/>
- <jar whenmanifestonly="fail" destfile="${dist.dir}/src/scala-compiler-src.jar">
+ </osgi.source.bundle>
+ <osgi.source.bundle destfile="${dist.dir}/src/scala-actors-src.jar"
+ symbolicName="org.scala-lang.scala-actors"
+ bundleName="Scala Actors Sources">
+ <fileset dir="${src.dir}/actors"/>
+ </osgi.source.bundle>
+ <osgi.source.bundle destfile="${dist.dir}/src/scala-compiler-src.jar"
+ symbolicName="org.scala-lang.scala-compiler"
+ bundleName="Scala Compiler Sources">
<fileset dir="${src.dir}/compiler"/>
<fileset dir="${src.dir}/repl"/>
<fileset dir="${src.dir}/scaladoc"/>
<fileset dir="${src.dir}/interactive"/>
<fileset dir="${src.dir}/continuations/plugin"/>
- </jar>
- <jar whenmanifestonly="fail" destfile="${dist.dir}/src/scala-swing-src.jar" basedir="${src.dir}/swing"/>
- <jar whenmanifestonly="fail" destfile="${dist.dir}/src/scala-reflect-src.jar" basedir="${src.dir}/reflect"/>
+ </osgi.source.bundle>
+ <osgi.source.bundle destfile="${dist.dir}/src/scala-swing-src.jar"
+ symbolicName="org.scala-lang.scala-swing"
+ bundleName="Scala Swing Sources">
+ <fileset dir="${src.dir}/swing"/>
+ </osgi.source.bundle>
+ <osgi.source.bundle destfile="${dist.dir}/src/scala-reflect-src.jar"
+ symbolicName="org.scala-lang.scala-reflect"
+ bundleName="Scala Reflect Sources">
+ <fileset dir="${src.dir}/reflect"/>
+ </osgi.source.bundle>
<jar whenmanifestonly="fail" destfile="${dist.dir}/src/scalap-src.jar" basedir="${src.dir}/scalap"/>
</target>
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 05ad2dbc57..50aad8e043 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -1402,7 +1402,7 @@ self =>
if (in.token == EQUALS) {
t match {
case Ident(_) | Select(_, _) | Apply(_, _) =>
- t = atPos(t.pos.startOrPoint, in.skipToken()) { makeAssign(t, expr()) }
+ t = atPos(t.pos.startOrPoint, in.skipToken()) { gen.mkAssign(t, expr()) }
case _ =>
}
} else if (in.token == COLON) {
diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
index 976e578afd..fba74330a6 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala
@@ -191,14 +191,6 @@ abstract class TreeBuilder {
}
}
- /** Create a tree representing an assignment <lhs = rhs> */
- def makeAssign(lhs: Tree, rhs: Tree): Tree = lhs match {
- case Apply(fn, args) =>
- Apply(atPos(fn.pos) { Select(fn, nme.update) }, args ::: List(rhs))
- case _ =>
- Assign(lhs, rhs)
- }
-
/** Tree for `od op`, start is start0 if od.pos is borked. */
def makePostfixSelect(start0: Int, end: Int, od: Tree, op: Name): Tree = {
val start = if (od.pos.isDefined) od.pos.startOrPoint else start0
diff --git a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
index 843299398b..a80fee876e 100644
--- a/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
+++ b/src/compiler/scala/tools/nsc/backend/icode/GenICode.scala
@@ -1319,6 +1319,8 @@ abstract class GenICode extends SubComponent {
/** Some useful equality helpers.
*/
def isNull(t: Tree) = cond(t) { case Literal(Constant(null)) => true }
+ def isLiteral(t: Tree) = cond(t) { case Literal(_) => true }
+ def isNonNullExpr(t: Tree) = isLiteral(t) || ((t.symbol ne null) && t.symbol.isModule)
/* If l or r is constant null, returns the other ; otherwise null */
def ifOneIsNull(l: Tree, r: Tree) = if (isNull(l)) r else if (isNull(r)) l else null
@@ -1514,6 +1516,23 @@ abstract class GenICode extends SubComponent {
val branchesReachable = !ctx1.bb.ignore
ctx1.bb emitOnly CZJUMP(thenCtx.bb, elseCtx.bb, EQ, ObjectReference)
branchesReachable
+ } else if (isNonNullExpr(l)) {
+ // Avoid null check if L is statically non-null.
+ //
+ // "" == expr -> "".equals(expr)
+ // Nil == expr -> Nil.equals(expr)
+ //
+ // Common enough (through pattern matching) to treat this specially here rather than
+ // hoping that -Yconst-opt is enabled. The impossible branches for null checks lead
+ // to spurious "branch not covered" warnings in Jacoco code coverage.
+ var ctx1 = genLoad(l, ctx, ObjectReference)
+ val branchesReachable = !ctx1.bb.ignore
+ ctx1 = genLoad(r, ctx1, ObjectReference)
+ ctx1.bb emitOnly(
+ CALL_METHOD(Object_equals, Dynamic),
+ CZJUMP(thenCtx.bb, elseCtx.bb, NE, BOOL)
+ )
+ branchesReachable
} else {
val eqEqTempLocal = getTempLocal
var ctx1 = genLoad(l, ctx, ObjectReference)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 5c8f1bd1c7..157c6ba4de 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -4874,26 +4874,37 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
}
// Warn about likely interpolated strings which are missing their interpolators
- def warnMissingInterpolator(tree: Literal) {
+ def warnMissingInterpolator(tree: Literal) = if (!isPastTyper) {
// Unfortunately implicit not found strings looks for all the world like
// missing interpolators.
def isArgToImplicitNotFound = context.enclosingApply.tree match {
- case Apply(fn, _) => fn.symbol.enclClass == ImplicitNotFoundClass
+ case Apply(fn, _) => fn.symbol != null && fn.symbol.enclClass == ImplicitNotFoundClass
case _ => false
}
+ def warnAbout(s: String) = {
+ def names = InterpolatorIdentRegex findAllIn s map (n => TermName(n stripPrefix "$"))
+ def isSuspiciousExpr = (InterpolatorCodeRegex findFirstIn s).nonEmpty
+ //def isSuspiciousName = names exists (lookUp _ andThen (_.exists))
+ def suspiciousName = names find (lookUp _ andThen (_.exists))
+ def lookUp(n: TermName) = context.lookupSymbol(n, !_.alternatives.exists(symRequiresArg)).symbol
+ def symRequiresArg(s: Symbol) = (
+ s.paramss.nonEmpty
+ && (s.paramss.head.headOption filterNot (_.isImplicit)).isDefined
+ )
+ val suggest = "Did you forget the interpolator?"
+ if (isSuspiciousExpr)
+ unit.warning(tree.pos, s"That looks like an interpolated expression! $suggest")
+ else /* if (isSuspiciousName) */ suspiciousName foreach (n =>
+ unit.warning(tree.pos, s"`$$$n` looks like an interpolated identifier! $suggest")
+ )
+ }
tree.value match {
case Constant(s: String) =>
- def names = InterpolatorIdentRegex findAllIn s map (n => newTermName(n stripPrefix "$"))
- def suspicious = (
- (InterpolatorCodeRegex findFirstIn s).nonEmpty
- || (names exists (n => context.lookupSymbol(n, _ => true).symbol.exists))
- )
val noWarn = (
isArgToImplicitNotFound
|| !(s contains ' ') // another heuristic - e.g. a string with only "$asInstanceOf"
)
- if (!noWarn && suspicious)
- unit.warning(tree.pos, "looks like an interpolated String; did you forget the interpolator?")
+ if (!noWarn) warnAbout(s)
case _ =>
}
}
diff --git a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
index c2d8bcdcd6..0d1fb6be07 100644
--- a/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
+++ b/src/compiler/scala/tools/reflect/quasiquotes/Reifiers.scala
@@ -10,7 +10,7 @@ trait Reifiers { self: Quasiquotes =>
import global.build.{SyntacticClassDef, SyntacticTraitDef, SyntacticModuleDef,
SyntacticDefDef, SyntacticValDef, SyntacticVarDef,
SyntacticBlock, SyntacticApplied, SyntacticTypeApplied,
- SyntacticFunction, SyntacticNew}
+ SyntacticFunction, SyntacticNew, SyntacticAssign}
import global.treeInfo._
import global.definitions._
import Cardinality._
@@ -71,9 +71,9 @@ trait Reifiers { self: Quasiquotes =>
reifyBuildCall(nme.SyntacticValDef, mods, name, tpt, rhs)
case SyntacticVarDef(mods, name, tpt, rhs) =>
reifyBuildCall(nme.SyntacticVarDef, mods, name, tpt, rhs)
- case SyntacticApplied(fun, argss) if argss.length > 1 =>
- reifyBuildCall(nme.SyntacticApplied, fun, argss)
- case SyntacticApplied(fun, argss @ (_ :+ (_ :+ Placeholder(_, _, DotDotDot)))) =>
+ case SyntacticAssign(lhs, rhs) =>
+ reifyBuildCall(nme.SyntacticAssign, lhs, rhs)
+ case SyntacticApplied(fun, argss) if argss.nonEmpty =>
reifyBuildCall(nme.SyntacticApplied, fun, argss)
case SyntacticTypeApplied(fun, targs) if targs.nonEmpty =>
reifyBuildCall(nme.SyntacticTypeApplied, fun, targs)
diff --git a/src/interactive/scala/tools/nsc/interactive/Response.scala b/src/interactive/scala/tools/nsc/interactive/Response.scala
index 0da400378e..3e84c83e55 100644
--- a/src/interactive/scala/tools/nsc/interactive/Response.scala
+++ b/src/interactive/scala/tools/nsc/interactive/Response.scala
@@ -55,7 +55,10 @@ class Response[T] {
try {
wait()
} catch {
- case exc: InterruptedException => raise(exc)
+ case exc: InterruptedException => {
+ Thread.currentThread().interrupt()
+ raise(exc)
+ }
}
}
data.get
@@ -73,7 +76,10 @@ class Response[T] {
try {
wait(timeout - (current - start))
} catch {
- case exc: InterruptedException => raise(exc)
+ case exc: InterruptedException => {
+ Thread.currentThread().interrupt()
+ raise(exc)
+ }
}
current = System.currentTimeMillis
}
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index ec6de84a9d..4e3f3c6c81 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -473,6 +473,13 @@ object Future {
*/
def successful[T](result: T): Future[T] = Promise.successful(result).future
+ /** Creates an already completed Future with the specified result or exception.
+ *
+ * @tparam T the type of the value in the promise
+ * @return the newly created `Future` object
+ */
+ def fromTry[T](result: Try[T]): Future[T] = Promise.fromTry(result).future
+
/** Starts an asynchronous computation and returns a `Future` object with the result of that computation.
*
* The result becomes available once the asynchronous computation is completed.
diff --git a/src/library/scala/concurrent/Promise.scala b/src/library/scala/concurrent/Promise.scala
index cfb1dda01f..eb8044ed3b 100644
--- a/src/library/scala/concurrent/Promise.scala
+++ b/src/library/scala/concurrent/Promise.scala
@@ -128,12 +128,19 @@ object Promise {
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
- def failed[T](exception: Throwable): Promise[T] = new impl.Promise.KeptPromise[T](Failure(exception))
+ def failed[T](exception: Throwable): Promise[T] = fromTry(Failure(exception))
/** Creates an already completed Promise with the specified result.
*
* @tparam T the type of the value in the promise
* @return the newly created `Promise` object
*/
- def successful[T](result: T): Promise[T] = new impl.Promise.KeptPromise[T](Success(result))
+ def successful[T](result: T): Promise[T] = fromTry(Success(result))
+
+ /** Creates an already completed Promise with the specified result or exception.
+ *
+ * @tparam T the type of the value in the promise
+ * @return the newly created `Promise` object
+ */
+ def fromTry[T](result: Try[T]): Promise[T] = new impl.Promise.KeptPromise[T](result)
}
diff --git a/src/library/scala/sys/process/ProcessBuilder.scala b/src/library/scala/sys/process/ProcessBuilder.scala
index a144d51609..feced71dae 100644
--- a/src/library/scala/sys/process/ProcessBuilder.scala
+++ b/src/library/scala/sys/process/ProcessBuilder.scala
@@ -123,7 +123,7 @@ import ProcessBuilder._
* 1. `#&&` conditionally executes the second command if the previous one finished with
* exit value 0. It mirrors shell's `&&`.
* 1. `#||` conditionally executes the third command if the exit value of the previous
- * command is different than zero. It mirrors shell's `&&`.
+ * command is different than zero. It mirrors shell's `||`.
*
* Finally, `!` at the end executes the commands, and returns the exit value.
* Whatever is printed will be sent to the Scala process standard output. If
diff --git a/src/reflect/scala/reflect/api/BuildUtils.scala b/src/reflect/scala/reflect/api/BuildUtils.scala
index 60c2a81947..551c27bf9c 100644
--- a/src/reflect/scala/reflect/api/BuildUtils.scala
+++ b/src/reflect/scala/reflect/api/BuildUtils.scala
@@ -193,5 +193,12 @@ private[reflect] trait BuildUtils { self: Universe =>
def apply(mods: Modifiers, name: TermName, tpt: Tree, rhs: Tree): ValDef
def unapply(tree: Tree): Option[(Modifiers, TermName, Tree, Tree)]
}
+
+ val SyntacticAssign: SyntacticAssignExtractor
+
+ trait SyntacticAssignExtractor {
+ def apply(lhs: Tree, rhs: Tree): Tree
+ def unapply(tree: Tree): Option[(Tree, Tree)]
+ }
}
}
diff --git a/src/reflect/scala/reflect/internal/BuildUtils.scala b/src/reflect/scala/reflect/internal/BuildUtils.scala
index de24b88397..e5c7dc44af 100644
--- a/src/reflect/scala/reflect/internal/BuildUtils.scala
+++ b/src/reflect/scala/reflect/internal/BuildUtils.scala
@@ -140,7 +140,7 @@ trait BuildUtils { self: SymbolTable =>
object SyntacticApplied extends SyntacticAppliedExtractor {
def apply(tree: Tree, argss: List[List[Tree]]): Tree =
- argss.foldLeft(tree) { Apply(_, _) }
+ argss.foldLeft(tree) { (f, args) => Apply(f, args.map(treeInfo.assignmentToMaybeNamedArg)) }
def unapply(tree: Tree): Some[(Tree, List[List[Tree]])] = {
val treeInfo.Applied(fun, targs, argss) = tree
@@ -401,6 +401,16 @@ trait BuildUtils { self: SymbolTable =>
object SyntacticValDef extends SyntacticValDefBase { val isMutable = false }
object SyntacticVarDef extends SyntacticValDefBase { val isMutable = true }
+
+ object SyntacticAssign extends SyntacticAssignExtractor {
+ def apply(lhs: Tree, rhs: Tree): Tree = gen.mkAssign(lhs, rhs)
+ def unapply(tree: Tree): Option[(Tree, Tree)] = tree match {
+ case Assign(lhs, rhs) => Some((lhs, rhs))
+ case AssignOrNamedArg(lhs, rhs) => Some((lhs, rhs))
+ case Apply(Select(fn, nme.update), args :+ rhs) => Some((atPos(fn.pos)(Apply(fn, args)), rhs))
+ case _ => None
+ }
+ }
}
val build: BuildApi = new BuildImpl
diff --git a/src/reflect/scala/reflect/internal/StdNames.scala b/src/reflect/scala/reflect/internal/StdNames.scala
index 6407a3979c..f4eae5590a 100644
--- a/src/reflect/scala/reflect/internal/StdNames.scala
+++ b/src/reflect/scala/reflect/internal/StdNames.scala
@@ -602,6 +602,7 @@ trait StdNames {
val SelectFromTypeTree: NameType = "SelectFromTypeTree"
val StringContext: NameType = "StringContext"
val SyntacticApplied: NameType = "SyntacticApplied"
+ val SyntacticAssign: NameType = "SyntacticAssign"
val SyntacticBlock: NameType = "SyntacticBlock"
val SyntacticClassDef: NameType = "SyntacticClassDef"
val SyntacticDefDef: NameType = "SyntacticDefDef"
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala
index a8af3e0f0e..a9f2807e9f 100644
--- a/src/reflect/scala/reflect/internal/TreeGen.scala
+++ b/src/reflect/scala/reflect/internal/TreeGen.scala
@@ -434,4 +434,12 @@ abstract class TreeGen extends macros.TreeBuilder {
case head :: Nil => head
case _ => gen.mkBlock(stats)
}
+
+ /** Create a tree representing an assignment <lhs = rhs> */
+ def mkAssign(lhs: Tree, rhs: Tree): Tree = lhs match {
+ case Apply(fn, args) =>
+ Apply(atPos(fn.pos)(Select(fn, nme.update)), args :+ rhs)
+ case _ =>
+ Assign(lhs, rhs)
+ }
}
diff --git a/test/files/neg/forgot-interpolator.check b/test/files/neg/forgot-interpolator.check
index f6de4d7b3a..a96431841f 100644
--- a/test/files/neg/forgot-interpolator.check
+++ b/test/files/neg/forgot-interpolator.check
@@ -1,9 +1,24 @@
-forgot-interpolator.scala:4: warning: looks like an interpolated String; did you forget the interpolator?
+forgot-interpolator.scala:4: warning: `$bippy` looks like an interpolated identifier! Did you forget the interpolator?
def f = "Put the $bippy in the $bippy!" // warn
^
-forgot-interpolator.scala:14: warning: looks like an interpolated String; did you forget the interpolator?
+forgot-interpolator.scala:14: warning: That looks like an interpolated expression! Did you forget the interpolator?
def f = """Put the ${println("bippy")} in the bippy!""" // warn
^
+forgot-interpolator.scala:30: warning: `$beppo` looks like an interpolated identifier! Did you forget the interpolator?
+ def f = "$beppo was a marx bros who saw dollars." // warn
+ ^
+forgot-interpolator.scala:34: warning: `$aleppo` looks like an interpolated identifier! Did you forget the interpolator?
+ def f = "$aleppo is a pepper and a city." // warn
+ ^
+forgot-interpolator.scala:40: warning: `$bar` looks like an interpolated identifier! Did you forget the interpolator?
+ def f = "$bar is private, shall we warn just in case?" // warn
+ ^
+forgot-interpolator.scala:45: warning: `$hippo` looks like an interpolated identifier! Did you forget the interpolator?
+ def h = "$hippo takes an implicit" // warn
+ ^
+forgot-interpolator.scala:37: warning: private method in class Bar is never used
+ private def bar = 8
+ ^
error: No warnings can be incurred under -Xfatal-warnings.
-two warnings found
+7 warnings found
one error found
diff --git a/test/files/neg/forgot-interpolator.scala b/test/files/neg/forgot-interpolator.scala
index d67db82643..5067f1dce9 100644
--- a/test/files/neg/forgot-interpolator.scala
+++ b/test/files/neg/forgot-interpolator.scala
@@ -13,3 +13,35 @@ class B {
class C {
def f = """Put the ${println("bippy")} in the bippy!""" // warn
}
+
+package object test {
+ def aleppo = 9
+ def greppo(n: Int) = ???
+ def zappos(n: Int)(implicit ord: math.Ordering[Int]) = ???
+ def hippo(implicit n: Int) = ???
+}
+
+package test {
+ // not sure if overloading is kosher in pkg obj yet
+ class Doo {
+ def beppo(i: Int) = 8 * i
+ def beppo = 8
+ class Dah extends Doo {
+ def f = "$beppo was a marx bros who saw dollars." // warn
+ }
+ }
+ class E {
+ def f = "$aleppo is a pepper and a city." // warn
+ }
+ class Bar {
+ private def bar = 8
+ }
+ class Baz extends Bar {
+ def f = "$bar is private, shall we warn just in case?" // warn
+ }
+ class G {
+ def g = "$greppo takes an arg" // no warn
+ def z = "$zappos takes an arg too" // no warn
+ def h = "$hippo takes an implicit" // warn
+ }
+}
diff --git a/test/files/neg/macro-quasiquotes.check b/test/files/neg/macro-quasiquotes.check
index a2d48723b5..96ef75dd32 100644
--- a/test/files/neg/macro-quasiquotes.check
+++ b/test/files/neg/macro-quasiquotes.check
@@ -1,6 +1,6 @@
Macros_1.scala:14: error: macro implementation has wrong shape:
required: (x: Impls.this.c.Expr[Int]): Impls.this.c.Expr[Any]
- found : (x: Impls.this.c.universe.Block): Impls.this.c.universe.Apply
+ found : (x: Impls.this.c.universe.Block): Impls.this.c.universe.Tree
type mismatch for parameter x: Impls.this.c.Expr[Int] does not conform to Impls.this.c.universe.Block
def m3(x: Int) = macro Impls.impl3
^
diff --git a/test/files/neg/t7848-interp-warn.check b/test/files/neg/t7848-interp-warn.check
new file mode 100644
index 0000000000..cbdc9f4c27
--- /dev/null
+++ b/test/files/neg/t7848-interp-warn.check
@@ -0,0 +1,9 @@
+t7848-interp-warn.scala:7: warning: `$foo` looks like an interpolated identifier! Did you forget the interpolator?
+ "An important $foo message!"
+ ^
+t7848-interp-warn.scala:11: warning: That looks like an interpolated expression! Did you forget the interpolator?
+ "A doubly important ${foo * 2} message!"
+ ^
+error: No warnings can be incurred under -Xfatal-warnings.
+two warnings found
+one error found
diff --git a/test/files/neg/t7848-interp-warn.flags b/test/files/neg/t7848-interp-warn.flags
new file mode 100644
index 0000000000..7949c2afa2
--- /dev/null
+++ b/test/files/neg/t7848-interp-warn.flags
@@ -0,0 +1 @@
+-Xlint -Xfatal-warnings
diff --git a/test/files/neg/t7848-interp-warn.scala b/test/files/neg/t7848-interp-warn.scala
new file mode 100644
index 0000000000..bb3eeff60c
--- /dev/null
+++ b/test/files/neg/t7848-interp-warn.scala
@@ -0,0 +1,13 @@
+
+package test
+
+object Test {
+ def f = {
+ val foo = "bar"
+ "An important $foo message!"
+ }
+ def g = {
+ val foo = "bar"
+ "A doubly important ${foo * 2} message!"
+ }
+}
diff --git a/test/files/pos/t7864.flags b/test/files/pos/t7864.flags
new file mode 100644
index 0000000000..7ccd56103a
--- /dev/null
+++ b/test/files/pos/t7864.flags
@@ -0,0 +1 @@
+-Xlint \ No newline at end of file
diff --git a/test/files/pos/t7864.scala b/test/files/pos/t7864.scala
new file mode 100644
index 0000000000..b2d8911a17
--- /dev/null
+++ b/test/files/pos/t7864.scala
@@ -0,0 +1,5 @@
+object Test {
+ val f = 0;
+ ({ toString; (x: Any) => x})("$f ")
+}
+
diff --git a/test/files/run/t6719.check b/test/files/run/t6719.check
new file mode 100644
index 0000000000..6a452c185a
--- /dev/null
+++ b/test/files/run/t6719.check
@@ -0,0 +1 @@
+()
diff --git a/test/files/run/t6719.scala b/test/files/run/t6719.scala
new file mode 100644
index 0000000000..847929a95d
--- /dev/null
+++ b/test/files/run/t6719.scala
@@ -0,0 +1,8 @@
+import scala.reflect.runtime.universe._
+import scala.reflect.runtime.{currentMirror => cm}
+import scala.tools.reflect.{ToolBox, ToolBoxError}
+object Test extends App {
+ val tb = cm.mkToolBox()
+ val tree = tb.parse("(); val res = 0")
+ println(tb.eval(tree))
+} \ No newline at end of file
diff --git a/test/files/run/t7852.check b/test/files/run/t7852.check
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/test/files/run/t7852.check
diff --git a/test/files/run/t7852.flags b/test/files/run/t7852.flags
new file mode 100644
index 0000000000..f6262fd3e0
--- /dev/null
+++ b/test/files/run/t7852.flags
@@ -0,0 +1 @@
+-Ynooptimise
diff --git a/test/files/run/t7852.scala b/test/files/run/t7852.scala
new file mode 100644
index 0000000000..c93db718fd
--- /dev/null
+++ b/test/files/run/t7852.scala
@@ -0,0 +1,39 @@
+import scala.tools.partest.BytecodeTest
+import scala.tools.asm
+import scala.tools.asm.util._
+import scala.tools.nsc.util.stringFromWriter
+import scala.collection.JavaConverters._
+
+object Test extends BytecodeTest {
+ val nullChecks = Set(asm.Opcodes.IFNONNULL, asm.Opcodes.IFNULL)
+
+ def show: Unit = {
+ def test(methodName: String, expected: Int) {
+ val classNode = loadClassNode("Lean")
+ val methodNode = getMethod(classNode, methodName)
+ val got = countNullChecks(methodNode.instructions)
+ assert(got == expected, s"expected $expected but got $got comparisons")
+ }
+ test("string", expected = 0)
+ test("module", expected = 0)
+ test("moduleIndirect", expected = 2)
+ }
+
+ def countNullChecks(insnList: asm.tree.InsnList): Int =
+ insnList.iterator.asScala.map(_.getOpcode).count(nullChecks)
+}
+
+class Lean {
+ def string {
+ "" == toString
+ }
+
+ def module {
+ Nil == (toString: Any)
+ }
+
+ def moduleIndirect {
+ val n: Nil.type = null
+ n == (toString: Any) // still need null checks here.
+ }
+}
diff --git a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
index c6cca85c81..753ad1aa59 100644
--- a/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermConstructionProps.scala
@@ -167,4 +167,28 @@ object TermConstructionProps extends QuasiquoteProperties("term construction") {
val x = q"val x: Int = 1"
assertThrows[IllegalArgumentException] { q"($x) => x" }
}
+
+ property("assign variable") = test {
+ val v = q"v"
+ val value = q"foo"
+ assertEqAst(q"$v = $value", "v = foo")
+ }
+
+ property("assign update 1") = test {
+ val v = q"v"
+ val args = q"1" :: q"2" :: Nil
+ val value = q"foo"
+ assertEqAst(q"$v(..$args) = $value", "v(1, 2) = foo")
+ }
+
+ property("assign update 2") = test {
+ val a = q"v(0)"
+ val value = q"foo"
+ assertEqAst(q"$a = $value", "v(0) = foo")
+ }
+
+ property("assign or named arg") = test {
+ val assignx = q"x = 1"
+ assertEqAst(q"f($assignx)", "f(x = 1)")
+ }
}
diff --git a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
index 45c7ee4bb7..22d4b1ce4f 100644
--- a/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
+++ b/test/files/scalacheck/quasiquotes/TermDeconstructionProps.scala
@@ -91,4 +91,24 @@ object TermDeconstructionProps extends QuasiquoteProperties("term deconstruction
matches("new { val early = 1} with Parent[Int] { body }")
matches("new Foo { selfie => }")
}
+
+ property("exhaustive assign pattern") = test {
+ def matches(tree: Tree) { val q"$rhs = $lhs" = tree }
+ matches(parse("left = right"))
+ matches(parse("arr(1) = 2"))
+ matches(AssignOrNamedArg(EmptyTree, EmptyTree))
+ }
+
+ property("deconstruct update 1") = test {
+ val q"$obj(..$args) = $value" = q"foo(bar) = baz"
+ assert(obj ≈ q"foo")
+ assert(args ≈ List(q"bar"))
+ assert(value ≈ q"baz")
+ }
+
+ property("deconstruct update 2") = test {
+ val q"$left = $value" = q"foo(bar) = baz"
+ assert(left ≈ q"foo(bar)")
+ assert(value ≈ q"baz")
+ }
}
diff --git a/versions.properties b/versions.properties
index 2b8c1de7b7..865ce3e995 100644
--- a/versions.properties
+++ b/versions.properties
@@ -1,7 +1,7 @@
-starr.version=2.11.0-M4
+starr.version=2.11.0-M5
# the below is used for depending on dependencies like partest
-scala.binary.version=2.11.0-M4
-partest.version.number=1.0-RC4
-scala-xml.version.number=1.0-RC3
-scala-parser-combinators.version.number=1.0-RC1
+scala.binary.version=2.11.0-M5
+partest.version.number=1.0-RC5
+scala-xml.version.number=1.0-RC4
+scala-parser-combinators.version.number=1.0-RC2