summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@typesafe.com>2015-10-05 14:17:29 +0200
committerLukas Rytz <lukas.rytz@typesafe.com>2015-10-05 14:17:29 +0200
commit4cbf89fa4408942ca38815e946f1e02ab913c3ad (patch)
treeb1fc98841d6c26171221e66a5d659b39d856bf65
parentc3906917675b54e9ac1f248c9fb0fba9fa310f0e (diff)
parente6917ac758e782fa03b6912a3feb8f9f8d0950a9 (diff)
downloadscala-4cbf89fa4408942ca38815e946f1e02ab913c3ad.tar.gz
scala-4cbf89fa4408942ca38815e946f1e02ab913c3ad.tar.bz2
scala-4cbf89fa4408942ca38815e946f1e02ab913c3ad.zip
Merge pull request #4784 from lrytz/merge-2.11-to-2.12-oct-5v2.12.0-M3
Merge 2.11 to 2.12 oct 5
-rw-r--r--.gitattributes30
-rw-r--r--README.md4
-rw-r--r--spec/08-pattern-matching.md2
-rwxr-xr-xsrc/compiler/scala/tools/ant/templates/tool-unix.tmpl13
-rw-r--r--src/compiler/scala/tools/nsc/Global.scala5
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala10
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/UnCurry.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/PatternExpander.scala18
-rw-r--r--src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala50
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Contexts.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala1
-rw-r--r--src/library/scala/concurrent/Future.scala2
-rw-r--r--src/library/scala/sys/process/Process.scala4
-rw-r--r--src/partest-extras/scala/tools/partest/IcodeComparison.scala9
-rw-r--r--src/reflect/scala/reflect/internal/AnnotationInfos.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Chars.scala2
-rw-r--r--src/reflect/scala/reflect/internal/Positions.scala9
-rw-r--r--src/reflect/scala/reflect/io/Streamable.scala8
-rw-r--r--src/reflect/scala/reflect/runtime/JavaUniverseForce.scala1
-rw-r--r--src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala2
-rw-r--r--test/files/neg/t4425b.check22
-rw-r--r--test/files/neg/t8127a.check4
-rw-r--r--test/files/neg/t8127a.scala12
-rw-r--r--test/files/neg/t8989.check4
-rw-r--r--test/files/neg/t8989.scala14
-rw-r--r--test/files/run/t7850c.scala11
-rw-r--r--test/files/run/t7850d.scala17
-rw-r--r--test/files/run/t9029.flags1
-rw-r--r--test/files/run/t9029.scala15
-rw-r--r--test/files/run/t9029b.check1
-rw-r--r--test/files/run/t9029b.scala31
-rw-r--r--test/files/run/t9029c.scala21
-rw-r--r--test/junit/scala/tools/nsc/interpreter/CompletionTest.scala19
34 files changed, 291 insertions, 69 deletions
diff --git a/.gitattributes b/.gitattributes
index ac98781b3d..da4421cb78 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2,20 +2,24 @@
# this must be first so later entries will override it
* text=auto
+# check out text files with lf, not crlf, on Windows. (especially
+# important for Scala source files, since """ preserves line endings)
+text eol=lf
+
# These files are text and should be normalized (convert crlf => lf)
-*.c text
-*.check text
-*.css text
-*.flags text
-*.html text
-*.java text
-*.js text
-*.policy text
-*.sbt text
-*.scala text
-*.sh text
-*.txt text
-*.xml text
+*.c eol=lf
+*.check eol=lf
+*.css eol=lf
+*.flags eol=lf
+*.html eol=lf
+*.java eol=lf
+*.js eol=lf
+*.policy eol=lf
+*.sbt eol=lf
+*.scala eol=lf
+*.sh eol=lf
+*.txt eol=lf
+*.xml eol=lf
# Windows-specific files get windows endings
*.bat eol=crlf
diff --git a/README.md b/README.md
index 7ee3cac42b..40c61a0aa1 100644
--- a/README.md
+++ b/README.md
@@ -154,6 +154,10 @@ ideas and coordinate your effort with others.
NOTE: we are working on migrating the build to sbt.
+If you are behind a HTTP proxy, include
+[`ANT_ARGS=-autoproxy`](https://ant.apache.org/manual/proxy.html) in
+your environment.
+
Run `ant build-opt` to build an optimized version of the compiler.
Verify your build using `ant test-opt`.
diff --git a/spec/08-pattern-matching.md b/spec/08-pattern-matching.md
index c494fbcef5..d496388a91 100644
--- a/spec/08-pattern-matching.md
+++ b/spec/08-pattern-matching.md
@@ -507,7 +507,7 @@ def f[B](t: Term[B]): B = t match {
The expected type of the pattern `y: Number` is
`Term[B]`. The type `Number` does not conform to
`Term[B]`; hence Case 2 of the rules above
-applies. This means that `b` is treated as another type
+applies. This means that `B` is treated as another type
variable for which subtype constraints are inferred. In our case the
applicable constraint is `Number <: Term[B]`, which
entails `B = Int`. Hence, `B` is treated in
diff --git a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl
index 6e91a2a202..5e6b3c041e 100755
--- a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl
+++ b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl
@@ -67,6 +67,11 @@ if uname | grep -q ^MINGW; then
mingw="$(uname)"
fi
+unset msys
+if uname | grep -q ^MSYS; then
+ msys="$(uname)"
+fi
+
# Finding the root folder for this Scala distribution
SCALA_HOME="$(findScalaHome)"
SEP=":"
@@ -111,9 +116,9 @@ if [[ -n "$cygwin" ]]; then
TOOL_CLASSPATH="$(cygpath --path --$format "$TOOL_CLASSPATH")"
fi
-if [[ -n "$cygwin$mingw" ]]; then
+if [[ -n "$cygwin$mingw$msys" ]]; then
case "$TERM" in
- rxvt* | xterm*)
+ rxvt* | xterm* | cygwin*)
stty -icanon min 1 -echo
WINDOWS_OPT="-Djline.terminal=unix"
;;
@@ -182,10 +187,10 @@ fi
declare -a classpath_args
-# default to the boot classpath for speed, except on cygwin/mingw because
+# default to the boot classpath for speed, except on cygwin/mingw/msys because
# JLine on Windows requires a custom DLL to be loaded.
unset usebootcp
-if [[ -z "$cygwin$mingw" ]]; then
+if [[ -z "$cygwin$mingw$msys" ]]; then
usebootcp="true"
fi
diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala
index 5cb31c1b64..422e2080f0 100644
--- a/src/compiler/scala/tools/nsc/Global.scala
+++ b/src/compiler/scala/tools/nsc/Global.scala
@@ -1690,7 +1690,10 @@ class Global(var currentSettings: Settings, var reporter: Reporter)
try {
val stream = new FileOutputStream(file)
printer.setWriter(new PrintWriter(stream, true))
- printer.printClass(cls)
+ try
+ printer.printClass(cls)
+ finally
+ stream.close()
informProgress(s"wrote $file")
} catch {
case e: IOException =>
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index f9e6a12241..dac3c7a285 100644
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -2692,7 +2692,10 @@ self =>
case t if t == SUPERTYPE || t == SUBTYPE || t == COMMA || t == RBRACE || isStatSep(t) =>
TypeDef(mods | Flags.DEFERRED, name, tparams, typeBounds())
case _ =>
- syntaxErrorOrIncompleteAnd("`=', `>:', or `<:' expected", skipIt = true)(EmptyTree)
+ syntaxErrorOrIncompleteAnd("`=', `>:', or `<:' expected", skipIt = true)(
+ // assume a dummy type def so as to have somewhere to stash the annotations
+ TypeDef(mods, tpnme.ERROR, Nil, EmptyTree)
+ )
}
}
}
@@ -2725,7 +2728,10 @@ self =>
case CASEOBJECT =>
objectDef(pos, (mods | Flags.CASE) withPosition (Flags.CASE, tokenRange(in.prev /*scanner skips on 'case' to 'object', thus take prev*/)))
case _ =>
- syntaxErrorOrIncompleteAnd("expected start of definition", skipIt = true)(EmptyTree)
+ syntaxErrorOrIncompleteAnd("expected start of definition", skipIt = true)(
+ // assume a class definition so as to have somewhere to stash the annotations
+ atPos(pos)(gen.mkClassDef(mods, tpnme.ERROR, Nil, Template(Nil, noSelfType, Nil)))
+ )
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala
index ce2fe943e4..242171476a 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/analysis/ProdConsAnalyzerImpl.scala
@@ -459,4 +459,4 @@ class InitialProducerSourceInterpreter extends SourceInterpreter {
override def newExceptionValue(tryCatchBlockNode: TryCatchBlockNode, handlerFrame: Frame[_ <: Value], exceptionType: Type): SourceValue = {
new SourceValue(1, ExceptionProducer(handlerFrame))
}
-} \ No newline at end of file
+}
diff --git a/src/compiler/scala/tools/nsc/transform/UnCurry.scala b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
index 57639a94c7..9d61dbbcae 100644
--- a/src/compiler/scala/tools/nsc/transform/UnCurry.scala
+++ b/src/compiler/scala/tools/nsc/transform/UnCurry.scala
@@ -475,13 +475,6 @@ abstract class UnCurry extends InfoTransform
withNeedLift(needLift = true) { super.transform(tree) }
else
super.transform(tree)
- case UnApply(fn, args) =>
- val fn1 = transform(fn)
- val args1 = fn.symbol.name match {
- case nme.unapplySeq => transformArgs(tree.pos, fn.symbol, args, patmat.alignPatterns(global.typer.context, tree).expectedTypes)
- case _ => args
- }
- treeCopy.UnApply(tree, fn1, args1)
case Apply(fn, args) =>
val needLift = needTryLift || !fn.symbol.isLabel // SI-6749, no need to lift in args to label jumps.
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/PatternExpander.scala b/src/compiler/scala/tools/nsc/transform/patmat/PatternExpander.scala
index e84ccbf754..1916050dd8 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/PatternExpander.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/PatternExpander.scala
@@ -86,9 +86,25 @@ trait PatternExpander[Pattern, Type] {
* @param fixed The non-sequence types which are extracted
* @param repeated The sequence type which is extracted
*/
- final case class Extractor(whole: Type, fixed: List[Type], repeated: Repeated) {
+ final case class Extractor(whole: Type, fixed: List[Type], repeated: Repeated, typeOfSinglePattern: Type) {
require(whole != NoType, s"expandTypes($whole, $fixed, $repeated)")
+ /** A pattern with arity-1 that doesn't match the arity of the Product-like result of the `get` method,
+ * will match that result in its entirety. Example:
+ *
+ * {{{
+ * warning: there was one deprecation warning; re-run with -deprecation for details
+ * scala> object Extractor { def unapply(a: Any): Option[(Int, String)] = Some((1, "2")) }
+ * defined object Extractor
+ *
+ * scala> "" match { case Extractor(x: Int, y: String) => }
+ *
+ * scala> "" match { case Extractor(xy : (Int, String)) => }
+ * warning: there was one deprecation warning; re-run with -deprecation for details
+ * }}}
+ * */
+ def asSinglePattern: Extractor = copy(fixed = List(typeOfSinglePattern))
+
def productArity = fixed.length
def hasSeq = repeated.exists
def elementType = repeated.elementType
diff --git a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala
index b1783dc81f..d4f44303bb 100644
--- a/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala
+++ b/src/compiler/scala/tools/nsc/transform/patmat/ScalacPatternExpanders.scala
@@ -43,8 +43,9 @@ trait ScalacPatternExpanders {
orElse definitions.elementType(ArrayClass, seq)
)
}
- def newExtractor(whole: Type, fixed: List[Type], repeated: Repeated): Extractor =
- logResult(s"newExtractor($whole, $fixed, $repeated")(Extractor(whole, fixed, repeated))
+ def newExtractor(whole: Type, fixed: List[Type], repeated: Repeated, typeOfSinglePattern: Type): Extractor =
+ logResult(s"newExtractor($whole, $fixed, $repeated, $typeOfSinglePattern")(Extractor(whole, fixed, repeated, typeOfSinglePattern))
+ def newExtractor(whole: Type, fixed: List[Type], repeated: Repeated): Extractor = newExtractor(whole, fixed, repeated, tupleType(fixed))
// Turn Seq[A] into Repeated(Seq[A], A, A*)
def repeatedFromSeq(seqType: Type): Repeated = {
@@ -73,26 +74,27 @@ trait ScalacPatternExpanders {
* Unfortunately the MethodType does not carry the information of whether
* it was unapplySeq, so we have to funnel that information in separately.
*/
- def unapplyMethodTypes(whole: Type, result: Type, isSeq: Boolean): Extractor = {
- val expanded = (
- if (result =:= BooleanTpe) Nil
- else typeOfMemberNamedGet(result) match {
+ def unapplyMethodTypes(context: Context, whole: Type, result: Type, isSeq: Boolean): Extractor = {
+ if (result =:= BooleanTpe) newExtractor(whole, Nil, NoRepeated)
+ else {
+ val getResult = typeOfMemberNamedGet(result)
+ def noGetError() = {
+ val name = "unapply" + (if (isSeq) "Seq" else "")
+ context.error(context.tree.pos, s"The result type of an $name method must contain a member `get` to be used as an extractor pattern, no such member exists in ${result}")
+ }
+ val expanded = getResult match {
+ case global.NoType => noGetError(); Nil
case rawGet if !hasSelectors(rawGet) => rawGet :: Nil
case rawGet => typesOfSelectors(rawGet)
}
- )
- expanded match {
- case init :+ last if isSeq => newExtractor(whole, init, repeatedFromSeq(last))
- case tps => newExtractor(whole, tps, NoRepeated)
+ expanded match {
+ case init :+ last if isSeq => newExtractor(whole, init, repeatedFromSeq(last), getResult)
+ case tps => newExtractor(whole, tps, NoRepeated, getResult)
+ }
}
}
}
object alignPatterns extends ScalacPatternExpander {
- /** Converts a T => (A, B, C) extractor to a T => ((A, B, CC)) extractor.
- */
- def tupleExtractor(extractor: Extractor): Extractor =
- extractor.copy(fixed = tupleType(extractor.fixed) :: Nil)
-
private def validateAligned(context: Context, tree: Tree, aligned: Aligned): Aligned = {
import aligned._
@@ -129,8 +131,8 @@ trait ScalacPatternExpanders {
val isUnapply = sel.symbol.name == nme.unapply
val extractor = sel.symbol.name match {
- case nme.unapply => unapplyMethodTypes(firstParamType(fn.tpe), sel.tpe, isSeq = false)
- case nme.unapplySeq => unapplyMethodTypes(firstParamType(fn.tpe), sel.tpe, isSeq = true)
+ case nme.unapply => unapplyMethodTypes(context, firstParamType(fn.tpe), sel.tpe, isSeq = false)
+ case nme.unapplySeq => unapplyMethodTypes(context, firstParamType(fn.tpe), sel.tpe, isSeq = true)
case _ => applyMethodTypes(fn.tpe)
}
@@ -142,12 +144,14 @@ trait ScalacPatternExpanders {
def acceptMessage = if (extractor.isErroneous) "" else s" to hold ${extractor.offeringString}"
val requiresTupling = isUnapply && patterns.totalArity == 1 && productArity > 1
- if (requiresTupling && effectivePatternArity(args) == 1) {
- val sym = sel.symbol.owner
- currentRun.reporting.deprecationWarning(sel.pos, sym, s"${sym} expects $productArity patterns$acceptMessage but crushing into $productArity-tuple to fit single pattern (SI-6675)")
- }
-
- val normalizedExtractor = if (requiresTupling) tupleExtractor(extractor) else extractor
+ val normalizedExtractor = if (requiresTupling) {
+ val tupled = extractor.asSinglePattern
+ if (effectivePatternArity(args) == 1 && isTupleType(extractor.typeOfSinglePattern)) {
+ val sym = sel.symbol.owner
+ currentRun.reporting.deprecationWarning(sel.pos, sym, s"${sym} expects $productArity patterns$acceptMessage but crushing into $productArity-tuple to fit single pattern (SI-6675)")
+ }
+ tupled
+ } else extractor
validateAligned(context, fn, Aligned(patterns, normalizedExtractor))
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
index 3fe2f24818..cb4eab335b 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala
@@ -827,7 +827,12 @@ trait Contexts { self: Analyzer =>
case List() =>
List()
case List(ImportSelector(nme.WILDCARD, _, _, _)) =>
- collectImplicits(pre.implicitMembers, pre, imported = true)
+ // Using pre.implicitMembers seems to exposes a problem with out-dated symbols in the IDE,
+ // see the example in https://www.assembla.com/spaces/scala-ide/tickets/1002552#/activity/ticket
+ // I haven't been able to boil that down the an automated test yet.
+ // Looking up implicit members in the package, rather than package object, here is at least
+ // consistent with what is done just below for named imports.
+ collectImplicits(qual.tpe.implicitMembers, pre, imported = true)
case ImportSelector(from, _, to, _) :: sels1 =>
var impls = collect(sels1) filter (info => info.name != from)
if (to != nme.WILDCARD) {
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 533ef13574..26e04edcca 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -3547,6 +3547,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper
def typedAnnotation(ann: Tree, mode: Mode = EXPRmode): AnnotationInfo = {
var hasError: Boolean = false
val pending = ListBuffer[AbsTypeError]()
+ def ErroneousAnnotation = new ErroneousAnnotation().setOriginal(ann)
def finish(res: AnnotationInfo): AnnotationInfo = {
if (hasError) {
diff --git a/src/library/scala/concurrent/Future.scala b/src/library/scala/concurrent/Future.scala
index 6304f35da9..c8ababbcab 100644
--- a/src/library/scala/concurrent/Future.scala
+++ b/src/library/scala/concurrent/Future.scala
@@ -610,7 +610,7 @@ object Future {
def sequence[A, M[X] <: TraversableOnce[X]](in: M[Future[A]])(implicit cbf: CanBuildFrom[M[Future[A]], A, M[A]], executor: ExecutionContext): Future[M[A]] = {
in.foldLeft(successful(cbf(in))) {
(fr, fa) => for (r <- fr; a <- fa) yield (r += a)
- } map (_.result())
+ }.map(_.result())(InternalCallbackExecutor)
}
/** Asynchronously and non-blockingly returns a new `Future` to the result of the first future
diff --git a/src/library/scala/sys/process/Process.scala b/src/library/scala/sys/process/Process.scala
index c40838bb06..06b9967908 100644
--- a/src/library/scala/sys/process/Process.scala
+++ b/src/library/scala/sys/process/Process.scala
@@ -68,7 +68,7 @@ trait ProcessCreation {
/** Creates a [[scala.sys.process.ProcessBuilder]] with working dir set to `File` and extra
* environment variables.
*
- * @example {{{ apply("java", new java.ioFile("/opt/app"), "CLASSPATH" -> "library.jar") }}}
+ * @example {{{ apply("java", new java.io.File("/opt/app"), "CLASSPATH" -> "library.jar") }}}
*/
def apply(command: String, cwd: File, extraEnv: (String, String)*): ProcessBuilder =
apply(command, Some(cwd), extraEnv: _*)
@@ -76,7 +76,7 @@ trait ProcessCreation {
/** Creates a [[scala.sys.process.ProcessBuilder]] with working dir set to `File` and extra
* environment variables.
*
- * @example {{{ apply("java" :: javaArgs, new java.ioFile("/opt/app"), "CLASSPATH" -> "library.jar") }}}
+ * @example {{{ apply("java" :: javaArgs, new java.io.File("/opt/app"), "CLASSPATH" -> "library.jar") }}}
*/
def apply(command: Seq[String], cwd: File, extraEnv: (String, String)*): ProcessBuilder =
apply(command, Some(cwd), extraEnv: _*)
diff --git a/src/partest-extras/scala/tools/partest/IcodeComparison.scala b/src/partest-extras/scala/tools/partest/IcodeComparison.scala
index 7122703918..1430db886e 100644
--- a/src/partest-extras/scala/tools/partest/IcodeComparison.scala
+++ b/src/partest-extras/scala/tools/partest/IcodeComparison.scala
@@ -48,8 +48,13 @@ abstract class IcodeComparison extends DirectTest {
compile("-d" :: testOutput.path :: arg0 :: args.toList : _*)
val icodeFiles = testOutput.files.toList filter (_ hasExtension "icode")
- try icodeFiles sortBy (_.name) flatMap (f => f.lines.toList)
- finally icodeFiles foreach (f => f.delete())
+ // Some methods in scala.reflect.io.File leak an InputStream, leaving the underlying file open.
+ // Windows won't delete an open file, but we must ensure the files get deleted, since the logic
+ // here depends on it (collectIcode will be called multiple times, and we can't allow crosstalk
+ // between calls). So we are careful to use `slurp` which does call `close`, and careful to
+ // check that `delete` returns true indicating successful deletion.
+ try icodeFiles sortBy (_.name) flatMap (f => f.slurp().lines.toList)
+ finally icodeFiles foreach (f => require(f.delete()))
}
/** Collect icode at the default phase, `printIcodeAfterPhase`. */
diff --git a/src/reflect/scala/reflect/internal/AnnotationInfos.scala b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
index 6863cdfd82..b923541b56 100644
--- a/src/reflect/scala/reflect/internal/AnnotationInfos.scala
+++ b/src/reflect/scala/reflect/internal/AnnotationInfos.scala
@@ -404,7 +404,7 @@ trait AnnotationInfos extends api.Annotations { self: SymbolTable =>
object UnmappableAnnotation extends CompleteAnnotationInfo(NoType, Nil, Nil)
- object ErroneousAnnotation extends CompleteAnnotationInfo(ErrorType, Nil, Nil)
+ class ErroneousAnnotation() extends CompleteAnnotationInfo(ErrorType, Nil, Nil)
/** Extracts symbol of thrown exception from AnnotationInfo.
*
diff --git a/src/reflect/scala/reflect/internal/Chars.scala b/src/reflect/scala/reflect/internal/Chars.scala
index 0f532a4e57..74413fdaba 100644
--- a/src/reflect/scala/reflect/internal/Chars.scala
+++ b/src/reflect/scala/reflect/internal/Chars.scala
@@ -66,7 +66,7 @@ trait Chars {
'0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z'
/** Can character start an alphanumeric Scala identifier? */
- def isIdentifierStart(c: Char): Boolean =
+ def isIdentifierStart(c: Char): Boolean =
(c == '_') || (c == '$') || Character.isUnicodeIdentifierStart(c)
/** Can character form part of an alphanumeric Scala identifier? */
diff --git a/src/reflect/scala/reflect/internal/Positions.scala b/src/reflect/scala/reflect/internal/Positions.scala
index 4d0e31b037..15d68bcdfe 100644
--- a/src/reflect/scala/reflect/internal/Positions.scala
+++ b/src/reflect/scala/reflect/internal/Positions.scala
@@ -252,7 +252,14 @@ trait Positions extends api.Positions { self: SymbolTable =>
super.traverse(t)
} else t match {
case mdef: MemberDef =>
- traverseTrees(mdef.mods.annotations)
+ val annTrees = mdef.mods.annotations match {
+ case Nil if mdef.symbol != null =>
+ // After typechecking, annotations are mvoed from the modifiers
+ // to the annotation on the symbol of the anotatee.
+ mdef.symbol.annotations.map(_.original)
+ case anns => anns
+ }
+ traverseTrees(annTrees)
case _ =>
}
}
diff --git a/src/reflect/scala/reflect/io/Streamable.scala b/src/reflect/scala/reflect/io/Streamable.scala
index aa47947672..99a14d1fb0 100644
--- a/src/reflect/scala/reflect/io/Streamable.scala
+++ b/src/reflect/scala/reflect/io/Streamable.scala
@@ -27,6 +27,10 @@ object Streamable {
* efficient method implementations.
*
* ''Note: This library is considered experimental and should not be used unless you know what you are doing.''
+ *
+ * Note that this code was not written with resource management in mind.
+ * Several methods (such as `chars` and `lines`) create InputStreams they
+ * don't close
*/
trait Bytes {
def inputStream(): InputStream
@@ -82,9 +86,13 @@ object Streamable {
*/
def creationCodec: Codec = implicitly[Codec]
+ /** Caller is responsible for closing the returned BufferedSource. */
def chars(codec: Codec): BufferedSource = Source.fromInputStream(inputStream())(codec)
+ /** Beware! Leaks an InputStream which will not be closed until it gets finalized. */
def lines(): Iterator[String] = lines(creationCodec)
+
+ /** Beware! Leaks an InputStream which will not be closed until it gets finalized. */
def lines(codec: Codec): Iterator[String] = chars(codec).getLines()
/** Obtains an InputStreamReader wrapped around a FileInputStream.
diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
index 278d081249..1e9a4fe8a5 100644
--- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
+++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala
@@ -106,7 +106,6 @@ trait JavaUniverseForce { self: runtime.JavaUniverse =>
this.AnnotationInfo
this.Annotation
this.UnmappableAnnotation
- this.ErroneousAnnotation
this.ThrownException
this.typeNames
this.tpnme
diff --git a/src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala b/src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala
index d9dbd780d4..62e12f8703 100644
--- a/src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala
+++ b/src/repl/scala/tools/nsc/interpreter/PresentationCompilerCompleter.scala
@@ -35,7 +35,7 @@ class PresentationCompilerCompleter(intp: IMain) extends Completion {
// secret handshakes
val slashPrint = """.*// *print *""".r
val slashTypeAt = """.*// *typeAt *(\d+) *(\d+) *""".r
- val Cursor = IMain.DummyCursorFragment
+ val Cursor = IMain.DummyCursorFragment + " "
def print(result: Result) = {
val offset = result.preambleLength
diff --git a/test/files/neg/t4425b.check b/test/files/neg/t4425b.check
index 8418b4fd12..a204467586 100644
--- a/test/files/neg/t4425b.check
+++ b/test/files/neg/t4425b.check
@@ -22,16 +22,28 @@ t4425b.scala:10: error: object X is not a case class, nor does it have an unappl
Note: def unapply(x: String)(y: String): Nothing exists in object X, but it cannot be used as an extractor due to its second non-implicit parameter list
println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" })
^
-t4425b.scala:18: error: too many patterns for object X: expected 1, found 2
+t4425b.scala:18: error: The result type of an unapply method must contain a member `get` to be used as an extractor pattern, no such member exists in Nothing
+ println( "" match { case _ X _ => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:18: error: too many patterns for object X offering Boolean: expected 0, found 2
println( "" match { case _ X _ => "ok" ; case _ => "fail" })
^
-t4425b.scala:19: error: too many patterns for object X: expected 1, found 2
+t4425b.scala:19: error: The result type of an unapply method must contain a member `get` to be used as an extractor pattern, no such member exists in Nothing
+ println((X: Any) match { case _ X _ => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:19: error: too many patterns for object X offering Boolean: expected 0, found 2
println((X: Any) match { case _ X _ => "ok" ; case _ => "fail" })
^
-t4425b.scala:22: error: too many patterns for object X: expected 1, found 2
+t4425b.scala:20: error: The result type of an unapply method must contain a member `get` to be used as an extractor pattern, no such member exists in Nothing
+ println( "" match { case X(_) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:21: error: The result type of an unapply method must contain a member `get` to be used as an extractor pattern, no such member exists in Nothing
+ println((X: Any) match { case X(_) => "ok" ; case _ => "fail" })
+ ^
+t4425b.scala:22: error: The result type of an unapply method must contain a member `get` to be used as an extractor pattern, no such member exists in Nothing
println( "" match { case X(_, _) => "ok" ; case _ => "fail" })
^
-t4425b.scala:23: error: too many patterns for object X: expected 1, found 2
+t4425b.scala:23: error: The result type of an unapply method must contain a member `get` to be used as an extractor pattern, no such member exists in Nothing
println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" })
^
t4425b.scala:31: error: too many patterns for object X offering Nothing: expected 1, found 2
@@ -46,4 +58,4 @@ t4425b.scala:35: error: too many patterns for object X offering Nothing: expecte
t4425b.scala:36: error: too many patterns for object X offering Nothing: expected 1, found 2
println((X: Any) match { case X(_, _) => "ok" ; case _ => "fail" })
^
-14 errors found
+18 errors found
diff --git a/test/files/neg/t8127a.check b/test/files/neg/t8127a.check
new file mode 100644
index 0000000000..5a30574861
--- /dev/null
+++ b/test/files/neg/t8127a.check
@@ -0,0 +1,4 @@
+t8127a.scala:7: error: The result type of an unapplySeq method must contain a member `get` to be used as an extractor pattern, no such member exists in Seq[_$1]
+ case H(v) =>
+ ^
+one error found
diff --git a/test/files/neg/t8127a.scala b/test/files/neg/t8127a.scala
new file mode 100644
index 0000000000..c05facdac1
--- /dev/null
+++ b/test/files/neg/t8127a.scala
@@ -0,0 +1,12 @@
+object H {
+ def unapplySeq(m: Any): Seq[_] = List("")
+}
+
+object Test {
+ def unapply(m: Any) = m match {
+ case H(v) =>
+ case _ =>
+ }
+ // now: too many patterns for object H offering Boolean: expected 0, found 1
+ // was: result type Seq[_$2] of unapplySeq defined in method unapplySeq in object H does not conform to Option[_]
+}
diff --git a/test/files/neg/t8989.check b/test/files/neg/t8989.check
new file mode 100644
index 0000000000..4e89b862bd
--- /dev/null
+++ b/test/files/neg/t8989.check
@@ -0,0 +1,4 @@
+t8989.scala:11: error: The result type of an unapply method must contain a member `get` to be used as an extractor pattern, no such member exists in A
+ val f = p match {case d(1) => true; case _ => false}
+ ^
+one error found
diff --git a/test/files/neg/t8989.scala b/test/files/neg/t8989.scala
new file mode 100644
index 0000000000..8ed6a901cd
--- /dev/null
+++ b/test/files/neg/t8989.scala
@@ -0,0 +1,14 @@
+class A extends Product1[Int] {
+ def _1 = 1
+ def isEmpty = false // used by scalac
+ def isDefined = !isEmpty // used by dotty
+ def canEqual(a: Any) = true
+}
+
+object d{
+ def unapply(a: Any) = new A
+ val p: Any = ???
+ val f = p match {case d(1) => true; case _ => false}
+}
+
+
diff --git a/test/files/run/t7850c.scala b/test/files/run/t7850c.scala
new file mode 100644
index 0000000000..25b9c0028d
--- /dev/null
+++ b/test/files/run/t7850c.scala
@@ -0,0 +1,11 @@
+// Testing that isEmpty and get are viewed with `memberType` from `Casey1`.
+trait T[A, B >: Null] { def isEmpty: A = false.asInstanceOf[A]; def get: B = null}
+class Casey1() extends T[Boolean, String]
+object Casey1 { def unapply(a: Casey1) = a }
+
+object Test {
+ def main(args: Array[String]) {
+ val c @ Casey1(x) = new Casey1()
+ assert(x == c.get)
+ }
+}
diff --git a/test/files/run/t7850d.scala b/test/files/run/t7850d.scala
new file mode 100644
index 0000000000..ccc98f1bcc
--- /dev/null
+++ b/test/files/run/t7850d.scala
@@ -0,0 +1,17 @@
+// Testing that the ad-hoc overload resolution of isEmpty/get discards
+// parameter-accepting variants
+trait T[A, B >: Null] { def isEmpty: A = false.asInstanceOf[A]; def get: B = null}
+class Casey1(val a: Int) {
+ def isEmpty: Boolean = false
+ def isEmpty(x: Int): Boolean = ???
+ def get: Int = a
+ def get(x: Int): String = ???
+}
+object Casey1 { def unapply(a: Casey1) = a }
+
+object Test {
+ def main(args: Array[String]) {
+ val c @ Casey1(x) = new Casey1(0)
+ assert(x == c.get)
+ }
+}
diff --git a/test/files/run/t9029.flags b/test/files/run/t9029.flags
new file mode 100644
index 0000000000..dcc59ebe32
--- /dev/null
+++ b/test/files/run/t9029.flags
@@ -0,0 +1 @@
+-deprecation
diff --git a/test/files/run/t9029.scala b/test/files/run/t9029.scala
new file mode 100644
index 0000000000..c01033b76e
--- /dev/null
+++ b/test/files/run/t9029.scala
@@ -0,0 +1,15 @@
+class Y(val _2: Int, val _1: String)
+
+object X { def unapply(u: Unit): Option[Y] = Some(new Y(42, "!")) }
+
+object Test {
+ def test1 = {
+ val X(y) = ()
+ val yy: Y = y
+ assert(yy._1 == "!")
+ assert(yy._2 == 42)
+ }
+ def main(args: Array[String]): Unit = {
+ test1
+ }
+}
diff --git a/test/files/run/t9029b.check b/test/files/run/t9029b.check
new file mode 100644
index 0000000000..aeb2d5e239
--- /dev/null
+++ b/test/files/run/t9029b.check
@@ -0,0 +1 @@
+Some(1)
diff --git a/test/files/run/t9029b.scala b/test/files/run/t9029b.scala
new file mode 100644
index 0000000000..764d0771ec
--- /dev/null
+++ b/test/files/run/t9029b.scala
@@ -0,0 +1,31 @@
+class Foo(val x: Bar) {
+ def isEmpty = false
+ def get = x
+}
+
+object Foo {
+ def unapply(x: Foo) = x
+}
+
+class Bar(val x: Option[Int], val y: Option[Int]) {
+ def isEmpty = false
+ def get = this
+ def _1 = x
+ def _2 = y
+}
+
+object Bar {
+ def unapply(x: Bar) = x
+}
+
+object Test {
+ def nameBased: Unit = {
+ val x: AnyRef = new Foo(new Bar(Some(1), Some(2)))
+ x match {
+ case Foo(Bar(x1, x2)) => println(x1)
+ }
+ }
+ def main(args: Array[String]): Unit = {
+ nameBased
+ }
+}
diff --git a/test/files/run/t9029c.scala b/test/files/run/t9029c.scala
new file mode 100644
index 0000000000..ccb51e23ae
--- /dev/null
+++ b/test/files/run/t9029c.scala
@@ -0,0 +1,21 @@
+object Extractor {
+ def unapply(a: Any): Option[Product2[Int, String]] = Some(new P2(1, "2"))
+}
+class P2[A, B](val _1: A, val _2: B) extends Product2[A, B] {
+ def canEqual(other: Any) = true
+ def isP2 = true
+}
+
+object Test {
+ def main(args: Array[String]): Unit = {
+ "" match {
+ case Extractor(p) =>
+ val pp: Product2[Int, String] = p
+ }
+ "" match {
+ case Extractor(x, y) =>
+ val xx: Int = x
+ val yy: String = y
+ }
+ }
+}
diff --git a/test/junit/scala/tools/nsc/interpreter/CompletionTest.scala b/test/junit/scala/tools/nsc/interpreter/CompletionTest.scala
index 514f30571e..78ebb7cf9c 100644
--- a/test/junit/scala/tools/nsc/interpreter/CompletionTest.scala
+++ b/test/junit/scala/tools/nsc/interpreter/CompletionTest.scala
@@ -52,6 +52,25 @@ class CompletionTest {
}
@Test
+ def annotations(): Unit = {
+ val intp = newIMain()
+ val completer = new PresentationCompilerCompleter(intp)
+ checkExact(completer, "def foo[@specialize", " A]")("specialized")
+ checkExact(completer, "def foo[@specialize")("specialized")
+ checkExact(completer, """@deprecatedN""", """ class Foo""")("deprecatedName")
+ checkExact(completer, """@deprecateN""")("deprecatedName")
+ checkExact(completer, """{@deprecateN""")("deprecatedName")
+ }
+
+ @Test
+ def incompleteStringInterpolation(): Unit = {
+ val intp = newIMain()
+ val completer = new PresentationCompilerCompleter(intp)
+ checkExact(completer, """val x_y_z = 1; s"${x_""", "}\"")("x_y_z")
+ checkExact(completer, """val x_y_z = 1; s"${x_""", "\"")("x_y_z")
+ }
+
+ @Test
def symbolically(): Unit = {
val intp = newIMain()
val completer = new PresentationCompilerCompleter(intp)