diff options
author | Lukas Rytz <lukas.rytz@gmail.com> | 2015-10-05 11:35:33 +0200 |
---|---|---|
committer | Lukas Rytz <lukas.rytz@gmail.com> | 2015-10-05 11:35:33 +0200 |
commit | 5435d2b11e9d23c50c5448b7623712f6e647c315 (patch) | |
tree | b1fc98841d6c26171221e66a5d659b39d856bf65 /src | |
parent | c3906917675b54e9ac1f248c9fb0fba9fa310f0e (diff) | |
parent | bb3ded3826adbb52b23725a93d6d51fc127b5623 (diff) | |
download | scala-5435d2b11e9d23c50c5448b7623712f6e647c315.tar.gz scala-5435d2b11e9d23c50c5448b7623712f6e647c315.tar.bz2 scala-5435d2b11e9d23c50c5448b7623712f6e647c315.zip |
Merge commit 'bb3ded3' into merge-2.11-to-2.12-oct-5
Diffstat (limited to 'src')
18 files changed, 102 insertions, 50 deletions
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 |