From aa0f345de2955819e7048984a7e5fa0acb7e8bc2 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 15 Jun 2015 11:21:06 -0700 Subject: SI-1931 Hide Predef.any2stringadd in REPL User imports that reference Predef are relocated to the top of the wrapping template so that they can hide implicits defined in Predef. Only one import from Predef is retained for special treatment. This is simple and sane. The test shows that `import Predef._` restores Predef implicits even if a user-defined term would normally be in scope. A smart `:import` command to turn off or quarantine imports explicitly would allow fine-grained control. --- src/repl/scala/tools/nsc/interpreter/IMain.scala | 3 +- src/repl/scala/tools/nsc/interpreter/Imports.scala | 31 +++++++++++----- test/files/jvm/interpreter.check | 6 +-- test/files/run/constrained-types.check | 8 ++-- test/files/run/kind-repl-command.check | 2 +- test/files/run/reify-repl-fail-gracefully.check | 2 +- test/files/run/reify_newimpl_22.check | 2 +- test/files/run/reify_newimpl_23.check | 2 +- test/files/run/reify_newimpl_25.check | 2 +- test/files/run/reify_newimpl_26.check | 2 +- test/files/run/repl-bare-expr.check | 12 +++--- test/files/run/repl-parens.check | 12 +++--- test/files/run/repl-paste-2.check | 2 +- test/files/run/repl-reset.check | 8 ++-- test/files/run/repl-trim-stack-trace.scala | 6 +-- test/files/run/t1931.scala | 43 ++++++++++++++++++++++ test/files/run/t4542.check | 2 +- test/files/run/t4594-repl-settings.scala | 2 +- test/files/run/t5655.check | 4 +- test/files/run/t7319.check | 6 +-- test/files/run/t7747-repl.check | 32 ++++++++-------- test/files/run/t9170.scala | 24 ++++++------ test/files/run/t9206.scala | 4 +- test/files/run/xMigration.check | 6 +-- 24 files changed, 139 insertions(+), 84 deletions(-) create mode 100644 test/files/run/t1931.scala diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index 841b4abfa5..06ae179da9 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -888,7 +888,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set /** Code to import bound names from previous lines - accessPath is code to * append to objectName to access anything bound by request. */ - lazy val ComputedImports(importsPreamble, importsTrailer, accessPath) = + lazy val ComputedImports(headerPreamble, importsPreamble, importsTrailer, accessPath) = exitingTyper(importsCode(referencedNames.toSet, ObjectSourceCode, definesClass)) /** the line of code to compute */ @@ -908,6 +908,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set else List("def %s = %s".format("$line", tquoted(originalLine)), "def %s = Nil".format("$trees")) } def preamble = s""" + |$headerPreamble |${preambleHeader format lineRep.readName} |${envLines mkString (" ", ";\n ", ";\n")} |$importsPreamble diff --git a/src/repl/scala/tools/nsc/interpreter/Imports.scala b/src/repl/scala/tools/nsc/interpreter/Imports.scala index 3ec77e46f1..5b231d94b6 100644 --- a/src/repl/scala/tools/nsc/interpreter/Imports.scala +++ b/src/repl/scala/tools/nsc/interpreter/Imports.scala @@ -70,7 +70,10 @@ trait Imports { /** Compute imports that allow definitions from previous * requests to be visible in a new request. Returns - * three pieces of related code: + * three or four pieces of related code: + * + * 0. Header code fragment that should go at the beginning + * of the compilation unit, specifically, import Predef. * * 1. An initial code fragment that should go before * the code of the new request. @@ -91,30 +94,34 @@ trait Imports { * (3) It imports multiple same-named implicits, but only the * last one imported is actually usable. */ - case class ComputedImports(prepend: String, append: String, access: String) + case class ComputedImports(header: String, prepend: String, append: String, access: String) protected def importsCode(wanted: Set[Name], wrapper: Request#Wrapper, definesClass: Boolean): ComputedImports = { + val header, code, trailingBraces, accessPath = new StringBuilder + val currentImps = mutable.HashSet[Name]() + var predefEscapes = false // only emit predef import header if name not resolved in history, loosely + /** Narrow down the list of requests from which imports * should be taken. Removes requests which cannot contribute * useful imports for the specified set of wanted names. */ - case class ReqAndHandler(req: Request, handler: MemberHandler) { } + case class ReqAndHandler(req: Request, handler: MemberHandler) def reqsToUse: List[ReqAndHandler] = { /** Loop through a list of MemberHandlers and select which ones to keep. - * 'wanted' is the set of names that need to be imported. + * 'wanted' is the set of names that need to be imported. */ def select(reqs: List[ReqAndHandler], wanted: Set[Name]): List[ReqAndHandler] = { // Single symbol imports might be implicits! See bug #1752. Rather than // try to finesse this, we will mimic all imports for now. def keepHandler(handler: MemberHandler) = handler match { - /* While defining classes in class based mode - implicits are not needed. */ + // While defining classes in class based mode - implicits are not needed. case h: ImportHandler if isClassBased && definesClass => h.importedNames.exists(x => wanted.contains(x)) case _: ImportHandler => true case x => x.definesImplicit || (x.definedNames exists wanted) } reqs match { - case Nil => Nil + case Nil => predefEscapes = wanted contains PredefModule.name ; Nil case rh :: rest if !keepHandler(rh.handler) => select(rest, wanted) case rh :: rest => import rh.handler._ @@ -127,9 +134,6 @@ trait Imports { select(allReqAndHandlers reverseMap { case (r, h) => ReqAndHandler(r, h) }, wanted).reverse } - val code, trailingBraces, accessPath = new StringBuilder - val currentImps = mutable.HashSet[Name]() - // add code for a new object to hold some imports def addWrapper() { import nme.{ INTERPRETER_IMPORT_WRAPPER => iw } @@ -146,6 +150,9 @@ trait Imports { try op finally addWrapper() } + // imports from Predef are relocated to the template header to allow hiding. + def checkHeader(h: ImportHandler) = h.referencedNames contains PredefModule.name + // loop through previous requests, adding imports for each one wrapBeforeAndAfter { // Reusing a single temporary value when import from a line with multiple definitions. @@ -153,6 +160,9 @@ trait Imports { for (ReqAndHandler(req, handler) <- reqsToUse) { val objName = req.lineRep.readPathInstance handler match { + case h: ImportHandler if checkHeader(h) => + header.clear() + header append f"${h.member}%n" // If the user entered an import, then just use it; add an import wrapping // level if the import might conflict with some other import case x: ImportHandler if x.importsWildcard => @@ -194,7 +204,8 @@ trait Imports { } } - ComputedImports(code.toString, trailingBraces.toString, accessPath.toString) + val computedHeader = if (predefEscapes) header.toString else "" + ComputedImports(computedHeader, code.toString, trailingBraces.toString, accessPath.toString) } private def allReqAndHandlers = diff --git a/test/files/jvm/interpreter.check b/test/files/jvm/interpreter.check index 08372685d6..ce3c8062d7 100644 --- a/test/files/jvm/interpreter.check +++ b/test/files/jvm/interpreter.check @@ -30,7 +30,7 @@ scala> val four: anotherint = 4 four: anotherint = 4 scala> val bogus: anotherint = "hello" -:11: error: type mismatch; +:12: error: type mismatch; found : String("hello") required: anotherint (which expands to) Int @@ -353,7 +353,7 @@ defined class Term scala> def f(e: Exp) = e match { // non-exhaustive warning here case _:Fact => 3 } -:21: warning: match may not be exhaustive. +:22: warning: match may not be exhaustive. It would fail on the following inputs: Exp(), Term() def f(e: Exp) = e match { // non-exhaustive warning here ^ @@ -363,6 +363,6 @@ scala> :quit plusOne: (x: Int)Int res0: Int = 6 res0: String = after reset -:11: error: not found: value plusOne +:12: error: not found: value plusOne plusOne(5) // should be undefined now ^ diff --git a/test/files/run/constrained-types.check b/test/files/run/constrained-types.check index 670d6f49aa..5444cf2088 100644 --- a/test/files/run/constrained-types.check +++ b/test/files/run/constrained-types.check @@ -133,16 +133,16 @@ y: String = hello scala> scala> val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message -:11: error: not found: value e +:12: error: not found: value e val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message ^ -:11: error: not found: value f +:12: error: not found: value f val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message ^ -:11: error: not found: value g +:12: error: not found: value g val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message ^ -:11: error: not found: value h +:12: error: not found: value h val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message ^ diff --git a/test/files/run/kind-repl-command.check b/test/files/run/kind-repl-command.check index e050fb4bc1..560529ba03 100644 --- a/test/files/run/kind-repl-command.check +++ b/test/files/run/kind-repl-command.check @@ -19,7 +19,7 @@ scala> :k new { def empty = false } AnyRef{def empty: Boolean}'s kind is A scala> :k Nonexisting -:11: error: not found: value Nonexisting +:12: error: not found: value Nonexisting Nonexisting ^ diff --git a/test/files/run/reify-repl-fail-gracefully.check b/test/files/run/reify-repl-fail-gracefully.check index 025d377a43..32ed876356 100644 --- a/test/files/run/reify-repl-fail-gracefully.check +++ b/test/files/run/reify-repl-fail-gracefully.check @@ -8,7 +8,7 @@ import scala.reflect.runtime.universe._ scala> scala> reify -:15: error: too few argument lists for macro invocation +:16: error: too few argument lists for macro invocation reify ^ diff --git a/test/files/run/reify_newimpl_22.check b/test/files/run/reify_newimpl_22.check index e69dc60199..985f646579 100644 --- a/test/files/run/reify_newimpl_22.check +++ b/test/files/run/reify_newimpl_22.check @@ -15,7 +15,7 @@ scala> { } println(code.eval) } -:18: free term: Ident(TermName("x")) defined by res0 in :17:14 +:19: free term: Ident(TermName("x")) defined by res0 in :18:14 val code = reify { ^ 2 diff --git a/test/files/run/reify_newimpl_23.check b/test/files/run/reify_newimpl_23.check index 1356d509d3..f60113c69f 100644 --- a/test/files/run/reify_newimpl_23.check +++ b/test/files/run/reify_newimpl_23.check @@ -14,7 +14,7 @@ scala> def foo[T]{ } println(code.eval) } -:16: free type: Ident(TypeName("T")) defined by foo in :15:16 +:17: free type: Ident(TypeName("T")) defined by foo in :16:16 val code = reify { ^ foo: [T]=> Unit diff --git a/test/files/run/reify_newimpl_25.check b/test/files/run/reify_newimpl_25.check index e512cfc52e..9104d8df0b 100644 --- a/test/files/run/reify_newimpl_25.check +++ b/test/files/run/reify_newimpl_25.check @@ -5,7 +5,7 @@ scala> { val tt = implicitly[TypeTag[x.type]] println(tt) } -:14: free term: Ident(TermName("x")) defined by res0 in :13:14 +:15: free term: Ident(TermName("x")) defined by res0 in :14:14 val tt = implicitly[TypeTag[x.type]] ^ TypeTag[x.type] diff --git a/test/files/run/reify_newimpl_26.check b/test/files/run/reify_newimpl_26.check index b203389db1..cbb21854ba 100644 --- a/test/files/run/reify_newimpl_26.check +++ b/test/files/run/reify_newimpl_26.check @@ -4,7 +4,7 @@ scala> def foo[T]{ val tt = implicitly[WeakTypeTag[List[T]]] println(tt) } -:12: free type: Ident(TypeName("T")) defined by foo in :10:16 +:13: free type: Ident(TypeName("T")) defined by foo in :11:16 val tt = implicitly[WeakTypeTag[List[T]]] ^ foo: [T]=> Unit diff --git a/test/files/run/repl-bare-expr.check b/test/files/run/repl-bare-expr.check index f0c488455f..e0a1f4ecd6 100644 --- a/test/files/run/repl-bare-expr.check +++ b/test/files/run/repl-bare-expr.check @@ -1,12 +1,12 @@ scala> 2 ; 3 -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 2 ;; ^ res0: Int = 3 scala> { 2 ; 3 } -:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses { 2 ; 3 } ^ res1: Int = 3 @@ -15,16 +15,16 @@ scala> 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Mooo 1 + 2 + 3 } ; bippy+88+11 -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ defined object Cow diff --git a/test/files/run/repl-parens.check b/test/files/run/repl-parens.check index 35853f10da..6516f4ea90 100644 --- a/test/files/run/repl-parens.check +++ b/test/files/run/repl-parens.check @@ -18,10 +18,10 @@ scala> ( (2 + 2 ) ) res5: Int = 4 scala> 5 ; ( (2 + 2 ) ) ; ((5)) -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; ( (2 + 2 ) ) ;; ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; ( (2 + 2 ) ) ;; ^ res6: Int = 5 @@ -38,16 +38,16 @@ res9: String = 4423 scala> scala> 55 ; ((2 + 2)) ; (1, 2, 3) -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 55 ; ((2 + 2)) ;; ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 55 ; ((2 + 2)) ;; ^ res10: (Int, Int, Int) = (1,2,3) scala> 55 ; (x: Int) => x + 1 ; () => ((5)) -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 55 ; (x: Int) => x + 1 ;; ^ res11: () => Int = @@ -58,7 +58,7 @@ scala> () => 5 res12: () => Int = scala> 55 ; () => 5 -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 55 ;; ^ res13: () => Int = diff --git a/test/files/run/repl-paste-2.check b/test/files/run/repl-paste-2.check index 5b6a84144d..dbf5363c0f 100644 --- a/test/files/run/repl-paste-2.check +++ b/test/files/run/repl-paste-2.check @@ -42,7 +42,7 @@ scala> res5 + res6 res1: Int = 690 scala> val x = dingus -:10: error: not found: value dingus +:11: error: not found: value dingus val x = dingus ^ diff --git a/test/files/run/repl-reset.check b/test/files/run/repl-reset.check index b0683fff79..cf4d9a149e 100644 --- a/test/files/run/repl-reset.check +++ b/test/files/run/repl-reset.check @@ -28,13 +28,13 @@ Forgetting all expression results and named terms: $intp, BippyBungus, x1, x2, x Forgetting defined types: BippyBungus scala> x1 + x2 + x3 -:11: error: not found: value x1 +:12: error: not found: value x1 x1 + x2 + x3 ^ -:11: error: not found: value x2 +:12: error: not found: value x2 x1 + x2 + x3 ^ -:11: error: not found: value x3 +:12: error: not found: value x3 x1 + x2 + x3 ^ @@ -42,7 +42,7 @@ scala> val x1 = 4 x1: Int = 4 scala> new BippyBungus -:11: error: not found: type BippyBungus +:12: error: not found: type BippyBungus new BippyBungus ^ diff --git a/test/files/run/repl-trim-stack-trace.scala b/test/files/run/repl-trim-stack-trace.scala index ea91e32239..c0814905f9 100644 --- a/test/files/run/repl-trim-stack-trace.scala +++ b/test/files/run/repl-trim-stack-trace.scala @@ -12,7 +12,7 @@ f: Nothing scala> f java.lang.Exception: Uh-oh - at .f(:10) + at .f(:11) ... 69 elided scala> def f = throw new Exception("") @@ -20,7 +20,7 @@ f: Nothing scala> f java.lang.Exception: - at .f(:10) + at .f(:11) ... 69 elided scala> def f = throw new Exception @@ -28,7 +28,7 @@ f: Nothing scala> f java.lang.Exception - at .f(:10) + at .f(:11) ... 69 elided scala> :quit""" diff --git a/test/files/run/t1931.scala b/test/files/run/t1931.scala new file mode 100644 index 0000000000..eedfa9b03d --- /dev/null +++ b/test/files/run/t1931.scala @@ -0,0 +1,43 @@ + +import scala.tools.partest.SessionTest + +object Test extends SessionTest { + + def session = +""" +scala> val x: Any = 42 +x: Any = 42 + +scala> x + " works" +res0: String = 42 works + +scala> import Predef.{ any2stringadd => _, _ } +import Predef.{any2stringadd=>_, _} + +scala> x + " works" +:14: error: value + is not a member of Any + x + " works" + ^ + +scala> import Predef._ +import Predef._ + +scala> x + " works" +res2: String = 42 works + +scala> object Predef { def f = 42 } +defined object Predef + +scala> import Predef._ +import Predef._ + +scala> f +:14: error: not found: value f + f + ^ + +scala> Predef.f +res4: Int = 42 + +scala> :quit""" +} diff --git a/test/files/run/t4542.check b/test/files/run/t4542.check index 3ab3eaffd8..6e099222b0 100644 --- a/test/files/run/t4542.check +++ b/test/files/run/t4542.check @@ -5,7 +5,7 @@ scala> @deprecated("foooo", "ReplTest version 1.0-FINAL") class Foo() { defined class Foo scala> val f = new Foo -:11: warning: class Foo is deprecated: foooo +:12: warning: class Foo is deprecated: foooo val f = new Foo ^ f: Foo = Bippy diff --git a/test/files/run/t4594-repl-settings.scala b/test/files/run/t4594-repl-settings.scala index cbd87b5949..f2d1a8b3f8 100644 --- a/test/files/run/t4594-repl-settings.scala +++ b/test/files/run/t4594-repl-settings.scala @@ -15,7 +15,7 @@ object Test extends SessionTest { |scala> :settings -deprecation | |scala> def b = depp - |:11: warning: method depp is deprecated: Please don't do that. + |:12: warning: method depp is deprecated: Please don't do that. | def b = depp | ^ |b: String diff --git a/test/files/run/t5655.check b/test/files/run/t5655.check index 857a5ab556..9191997624 100644 --- a/test/files/run/t5655.check +++ b/test/files/run/t5655.check @@ -6,7 +6,7 @@ scala> import x._ import x._ scala> x -:15: error: reference to x is ambiguous; +:16: error: reference to x is ambiguous; it is imported twice in the same scope by import x._ and import x @@ -14,7 +14,7 @@ and import x ^ scala> x -:15: error: reference to x is ambiguous; +:16: error: reference to x is ambiguous; it is imported twice in the same scope by import x._ and import x diff --git a/test/files/run/t7319.check b/test/files/run/t7319.check index 31923e7119..4d8429e8f2 100644 --- a/test/files/run/t7319.check +++ b/test/files/run/t7319.check @@ -15,21 +15,21 @@ warning: there was one feature warning; re-run with -feature for details convert: [F[X <: F[X]]](builder: F[_ <: F[_]])Int scala> convert(Some[Int](0)) -:15: error: no type parameters for method convert: (builder: F[_ <: F[_]])Int exist so that it can be applied to arguments (Some[Int]) +:16: error: no type parameters for method convert: (builder: F[_ <: F[_]])Int exist so that it can be applied to arguments (Some[Int]) --- because --- argument expression's type is not compatible with formal parameter type; found : Some[Int] required: ?F[_$1] forSome { type _$1 <: ?F[_$2] forSome { type _$2 } } convert(Some[Int](0)) ^ -:15: error: type mismatch; +:16: error: type mismatch; found : Some[Int] required: F[_ <: F[_]] convert(Some[Int](0)) ^ scala> Range(1,2).toArray: Seq[_] -:14: error: polymorphic expression cannot be instantiated to expected type; +:15: error: polymorphic expression cannot be instantiated to expected type; found : [B >: Int]Array[B] required: Seq[_] Range(1,2).toArray: Seq[_] diff --git a/test/files/run/t7747-repl.check b/test/files/run/t7747-repl.check index f19c39e7e1..487daf4878 100644 --- a/test/files/run/t7747-repl.check +++ b/test/files/run/t7747-repl.check @@ -15,13 +15,13 @@ scala> val z = x * y z: Int = 156 scala> 2 ; 3 -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 2 ;; ^ res0: Int = 3 scala> { 2 ; 3 } -:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses { 2 ; 3 } ^ res1: Int = 3 @@ -30,16 +30,16 @@ scala> 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Mooo 1 + 2 + 3 } ; bippy+88+11 -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { ^ defined object Cow @@ -81,10 +81,10 @@ scala> ( (2 + 2 ) ) res10: Int = 4 scala> 5 ; ( (2 + 2 ) ) ; ((5)) -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; ( (2 + 2 ) ) ;; ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 5 ; ( (2 + 2 ) ) ;; ^ res11: Int = 5 @@ -101,16 +101,16 @@ res14: String = 4423 scala> scala> 55 ; ((2 + 2)) ; (1, 2, 3) -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 55 ; ((2 + 2)) ;; ^ -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 55 ; ((2 + 2)) ;; ^ res15: (Int, Int, Int) = (1,2,3) scala> 55 ; (x: Int) => x + 1 ; () => ((5)) -:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:13: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 55 ; (x: Int) => x + 1 ;; ^ res16: () => Int = @@ -121,7 +121,7 @@ scala> () => 5 res17: () => Int = scala> 55 ; () => 5 -:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses +:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses 55 ;; ^ res18: () => Int = @@ -209,13 +209,13 @@ Forgetting all expression results and named terms: $intp, BippyBungus, Bovine, C Forgetting defined types: BippyBungus, Moo, Ruminant scala> x1 + x2 + x3 -:11: error: not found: value x1 +:12: error: not found: value x1 x1 + x2 + x3 ^ -:11: error: not found: value x2 +:12: error: not found: value x2 x1 + x2 + x3 ^ -:11: error: not found: value x3 +:12: error: not found: value x3 x1 + x2 + x3 ^ @@ -223,7 +223,7 @@ scala> val x1 = 4 x1: Int = 4 scala> new BippyBungus -:11: error: not found: type BippyBungus +:12: error: not found: type BippyBungus new BippyBungus ^ diff --git a/test/files/run/t9170.scala b/test/files/run/t9170.scala index d6cf516615..f39467bc25 100644 --- a/test/files/run/t9170.scala +++ b/test/files/run/t9170.scala @@ -8,17 +8,17 @@ object Test extends SessionTest { def session = """ scala> object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 } -:10: error: double definition: -def f[A](a: => A): Int at line 10 and -def f[A](a: => Either[Exception,A]): Int at line 10 +:11: error: double definition: +def f[A](a: => A): Int at line 11 and +def f[A](a: => Either[Exception,A]): Int at line 11 have same type after erasure: (a: Function0)Int object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 } ^ scala> object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 } -:10: error: double definition: -def f[A](a: => A): Int at line 10 and -def f[A](a: => Either[Exception,A]): Int at line 10 +:11: error: double definition: +def f[A](a: => A): Int at line 11 and +def f[A](a: => Either[Exception,A]): Int at line 11 have same type after erasure: (a: Function0)Int object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 } ^ @@ -27,9 +27,9 @@ scala> object Y { | def f[A](a: => A) = 1 | def f[A](a: => Either[Exception, A]) = 2 | } -:12: error: double definition: -def f[A](a: => A): Int at line 11 and -def f[A](a: => Either[Exception,A]): Int at line 12 +:13: error: double definition: +def f[A](a: => A): Int at line 12 and +def f[A](a: => Either[Exception,A]): Int at line 13 have same type after erasure: (a: Function0)Int def f[A](a: => Either[Exception, A]) = 2 ^ @@ -44,9 +44,9 @@ object Y { // Exiting paste mode, now interpreting. -:12: error: double definition: -def f[A](a: => A): Int at line 11 and -def f[A](a: => Either[Exception,A]): Int at line 12 +:13: error: double definition: +def f[A](a: => A): Int at line 12 and +def f[A](a: => Either[Exception,A]): Int at line 13 have same type after erasure: (a: Function0)Int def f[A](a: => Either[Exception, A]) = 2 ^ diff --git a/test/files/run/t9206.scala b/test/files/run/t9206.scala index 872c980fe4..406798104e 100644 --- a/test/files/run/t9206.scala +++ b/test/files/run/t9206.scala @@ -7,14 +7,14 @@ object Test extends SessionTest { def session = s"""| |scala> val i: Int = "foo" - |:10: error: type mismatch; + |:11: error: type mismatch; | found : String("foo") | required: Int | val i: Int = "foo" | ^ | |scala> { val j = 42 ; val i: Int = "foo" + j } - |:11: error: type mismatch; + |:12: error: type mismatch; | found : String | required: Int | { val j = 42 ; val i: Int = "foo" + j } diff --git a/test/files/run/xMigration.check b/test/files/run/xMigration.check index 79ce544493..cd860bf394 100644 --- a/test/files/run/xMigration.check +++ b/test/files/run/xMigration.check @@ -10,7 +10,7 @@ res1: Iterable[String] = MapLike(eis) scala> :setting -Xmigration:any scala> Map(1 -> "eis").values // warn -:11: warning: method values in trait MapLike has changed semantics in version 2.8.0: +:12: warning: method values in trait MapLike has changed semantics in version 2.8.0: `values` returns `Iterable[B]` rather than `Iterator[B]`. Map(1 -> "eis").values // warn ^ @@ -24,7 +24,7 @@ res3: Iterable[String] = MapLike(eis) scala> :setting -Xmigration:2.7 scala> Map(1 -> "eis").values // warn -:11: warning: method values in trait MapLike has changed semantics in version 2.8.0: +:12: warning: method values in trait MapLike has changed semantics in version 2.8.0: `values` returns `Iterable[B]` rather than `Iterator[B]`. Map(1 -> "eis").values // warn ^ @@ -38,7 +38,7 @@ res5: Iterable[String] = MapLike(eis) scala> :setting -Xmigration // same as :any scala> Map(1 -> "eis").values // warn -:11: warning: method values in trait MapLike has changed semantics in version 2.8.0: +:12: warning: method values in trait MapLike has changed semantics in version 2.8.0: `values` returns `Iterable[B]` rather than `Iterator[B]`. Map(1 -> "eis").values // warn ^ -- cgit v1.2.3 From 0aa9281bdf91b8354f138edb175e774ff65d3824 Mon Sep 17 00:00:00 2001 From: Li Yao Date: Sat, 11 Jul 2015 00:49:41 +0800 Subject: Fix the bug in the example in scala.sys.process There's no `!` method with argument type `ProcessIO`. I suppose this is intended to be `run`. --- src/library/scala/sys/process/package.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/sys/process/package.scala b/src/library/scala/sys/process/package.scala index b1976ad4b6..141ec07ab4 100644 --- a/src/library/scala/sys/process/package.scala +++ b/src/library/scala/sys/process/package.scala @@ -157,7 +157,7 @@ package scala.sys { * while(input.read() != -1) count += 1 * input.close() * } - * cat ! new ProcessIO(_.close(), byteCounter, _.close()) + * cat run new ProcessIO(_.close(), byteCounter, _.close()) * count * } * -- cgit v1.2.3 From 6b53b0302abf4e4946012174a153372ea56abe9a Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Wed, 29 Jul 2015 21:46:02 +0100 Subject: ScalaDoc fixes for compiler --- src/compiler/scala/tools/nsc/ScriptRunner.scala | 12 ++++++------ src/compiler/scala/tools/nsc/ast/parser/Scanners.scala | 2 +- src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala | 4 ++-- src/compiler/scala/tools/nsc/typechecker/Checkable.scala | 2 +- src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 8 ++++---- src/compiler/scala/tools/nsc/typechecker/Infer.scala | 2 +- .../scala/tools/nsc/typechecker/StdAttachments.scala | 2 +- src/compiler/scala/tools/nsc/typechecker/Tags.scala | 4 ++-- src/compiler/scala/tools/nsc/typechecker/Typers.scala | 2 +- src/compiler/scala/tools/nsc/util/DocStrings.scala | 4 ++-- 10 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/compiler/scala/tools/nsc/ScriptRunner.scala b/src/compiler/scala/tools/nsc/ScriptRunner.scala index 6d24b31531..bf93ad30bc 100644 --- a/src/compiler/scala/tools/nsc/ScriptRunner.scala +++ b/src/compiler/scala/tools/nsc/ScriptRunner.scala @@ -16,16 +16,16 @@ import util.Exceptional.unwrap /** An object that runs Scala code in script files. * - *

For example, here is a complete Scala script on Unix: - *

+ *  For example, here is a complete Scala script on Unix:
+ *  {{{
  *    #!/bin/sh
  *    exec scala "$0" "$@"
  *    !#
  *    Console.println("Hello, world!")
  *    args.toList foreach Console.println
- *  
- *

And here is a batch file example on Windows XP:

- *
+ *  }}}
+ *  And here is a batch file example on Windows XP:
+ *  {{{
  *    ::#!
  *    @echo off
  *    call scala %0 %*
@@ -33,7 +33,7 @@ import util.Exceptional.unwrap
  *    ::!#
  *    Console.println("Hello, world!")
  *    args.toList foreach Console.println
- *  
+ * }}} * * @author Lex Spoon * @version 1.0, 15/05/2006 diff --git a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala index 92833d647b..cd41c75298 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Scanners.scala @@ -226,7 +226,7 @@ trait Scanners extends ScannersCommon { * RPAREN if region starts with '(' * RBRACKET if region starts with '[' * RBRACE if region starts with '{' - * ARROW if region starts with `case' + * ARROW if region starts with 'case' * STRINGLIT if region is a string interpolation expression starting with '${' * (the STRINGLIT appears twice in succession on the stack iff the * expression is a multiline string literal). diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index a34ab914ef..5b59150f5d 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -495,8 +495,8 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self => * generic classes or interfaces. * * @param superName the internal of name of the super class. For interfaces, - * the super class is {@link Object}. May be null, but - * only for the {@link Object} class. + * the super class is [[Object]]. May be null, but + * only for the [[Object]] class. * * @param interfaces the internal names of the class's interfaces (see * {@link Type#getInternalName() getInternalName}). May be diff --git a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala index fc632e0d0d..309b80f9ba 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Checkable.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Checkable.scala @@ -44,7 +44,7 @@ import scala.language.postfixOps * which is essentially the intersection of X and |P|, where |P| is * the erasure of P. If XR <: P, then no warning is emitted. * - * We evaluate "X with conform to P" by checking `X <: P_wild, where + * We evaluate "X with conform to P" by checking `X <: P_wild`, where * P_wild is the result of substituting wildcard types in place of * pattern type variables. This is intentionally stricter than * (X matchesPattern P), see SI-8597 for motivating test cases. diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 7ec9cd74a4..6c37cb96c0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -110,10 +110,10 @@ trait Implicits { * Ignore their constr field! The list of type constraints returned along with each tree specifies the constraints that * must be met by the corresponding type parameter in `tpars` (for the returned implicit view to be valid). * - * @arg tp from-type for the implicit conversion - * @arg context search implicits here - * @arg tpars symbols that should be considered free type variables - * (implicit search should not try to solve them, just track their constraints) + * @param tp from-type for the implicit conversion + * @param context search implicits here + * @param tpars symbols that should be considered free type variables + * (implicit search should not try to solve them, just track their constraints) */ def allViewsFrom(tp: Type, context: Context, tpars: List[Symbol]): List[(SearchResult, List[TypeConstraint])] = { // my untouchable typevars are better than yours (they can't be constrained by them) diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index ab9fa26bac..9f7bdf7aff 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -1375,7 +1375,7 @@ trait Infer extends Checkable { * Otherwise, if there is no best alternative, error. * * @param argtpes0 contains the argument types. If an argument is named, as - * "a = 3", the corresponding type is `NamedType("a", Int)'. If the name + * "a = 3", the corresponding type is `NamedType("a", Int)`. If the name * of some NamedType does not exist in an alternative's parameter names, * the type is replaces by `Unit`, i.e. the argument is treated as an * assignment expression. diff --git a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala index ea44b9dc39..92b0719ba3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala +++ b/src/compiler/scala/tools/nsc/typechecker/StdAttachments.scala @@ -132,7 +132,7 @@ trait StdAttachments { /** Marks the tree as a macro impl reference, which is a naked reference to a method. * * This is necessary for typechecking macro impl references (see `DefaultMacroCompiler.defaultResolveMacroImpl`), - * because otherwise typing a naked reference will result in the "follow this method with `_' if you want to + * because otherwise typing a naked reference will result in the "follow this method with `_` if you want to * treat it as a partially applied function" errors. * * This mark suppresses adapt except for when the annottee is a macro application. diff --git a/src/compiler/scala/tools/nsc/typechecker/Tags.scala b/src/compiler/scala/tools/nsc/typechecker/Tags.scala index 57dc74d2a0..56127f4026 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Tags.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Tags.scala @@ -36,7 +36,7 @@ trait Tags { * @param allowMaterialization If true (default) then the resolver is allowed to launch materialization macros when there's no class tag in scope. * If false then materialization macros are prohibited from running. * - * @returns Tree that represents an `scala.reflect.ClassTag` for `tp` if everything is okay. + * @return Tree that represents an `scala.reflect.ClassTag` for `tp` if everything is okay. * EmptyTree if the result contains unresolved (i.e. not spliced) type parameters and abstract type members. * EmptyTree if `allowMaterialization` is false, and there is no class tag in scope. */ @@ -57,7 +57,7 @@ trait Tags { * @param allowMaterialization If true (default) then the resolver is allowed to launch materialization macros when there's no type tag in scope. * If false then materialization macros are prohibited from running. * - * @returns Tree that represents a `scala.reflect.TypeTag` for `tp` if everything is okay. + * @return Tree that represents a `scala.reflect.TypeTag` for `tp` if everything is okay. * EmptyTree if `concrete` is true and the result contains unresolved (i.e. not spliced) type parameters and abstract type members. * EmptyTree if `allowMaterialization` is false, and there is no array tag in scope. */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index fd1a6f293f..a7046e45e0 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -2725,7 +2725,7 @@ trait Typers extends Adaptations with Tags with TypersTracking with PatternTyper * * If 'T' is not fully defined, it is inferred by type checking * `apply$body` without a result type before type checking the block. - * The method's inferred result type is used instead of T`. [See test/files/pos/sammy_poly.scala] + * The method's inferred result type is used instead of `T`. [See test/files/pos/sammy_poly.scala] * * The `apply` method is identified by the argument `sam`; `S` corresponds to the argument `samClassTp`, * and `resPt` is derived from `samClassTp` -- it may be fully defined, or not... diff --git a/src/compiler/scala/tools/nsc/util/DocStrings.scala b/src/compiler/scala/tools/nsc/util/DocStrings.scala index 4ff7067a21..501546b8f6 100755 --- a/src/compiler/scala/tools/nsc/util/DocStrings.scala +++ b/src/compiler/scala/tools/nsc/util/DocStrings.scala @@ -37,7 +37,7 @@ object DocStrings { /** Returns index of string `str` after `start` skipping longest * sequence of space and tab characters, possibly also containing * a single `*` character or the `/``**` sequence. - * @pre start == str.length || str(start) == `\n' + * @pre start == str.length || str(start) == `\n` */ def skipLineLead(str: String, start: Int): Int = if (start == str.length) start @@ -49,7 +49,7 @@ object DocStrings { else idx } - /** Skips to next occurrence of `\n' or to the position after the `/``**` sequence following index `start`. + /** Skips to next occurrence of `\n` or to the position after the `/``**` sequence following index `start`. */ def skipToEol(str: String, start: Int): Int = if (start + 2 < str.length && (str charAt start) == '/' && (str charAt (start + 1)) == '*' && (str charAt (start + 2)) == '*') start + 3 -- cgit v1.2.3 From c201eac291682a9bdb9ca2790403084b4f36da76 Mon Sep 17 00:00:00 2001 From: Mariot Chauvin Date: Tue, 10 Feb 2015 15:15:29 +0000 Subject: SI-8362: AbstractPromise extends AtomicReference To avoid `sun.misc.Unsafe`, which is not supported on Google App Engine. Deprecate `AbstractPromise` --> extend `j.u.c.atomic.AtomicReference` directly. `AtomicReference.compareAndSet()` should also provide better performance on HotSpot, which compiles it down to the machine's CAS instruction. The binary incompatible change is ok because it's in an internal package. I can't think of any real issue with adding a superclass (which contributes only final methods) to a class in an implementation package (as long as those methods were not introduced in any illicit subclasses of said class). Instead of changing `DefaultPromise`'s super class, let's be more conservative, and do it closest to the source. This is both clearer and more focussed, leaving those subclasses of AbstractPromise we never heard of unaffected. Genesis of the commit: since the work on `Future` performance, `AbstractPromise` is using `Unsafe`, breaking the ability for `Future` to be executed on GAE. At that time, viktorklang suggested to implement a fallback in case `Unsafe` is not available. carey proposed an implementation, and mchv submitted a patch, which was refined by adriaanm. --- bincompat-backward.whitelist.conf | 9 ++++++ bincompat-forward.whitelist.conf | 9 ++++++ .../scala/concurrent/impl/AbstractPromise.java | 37 ++++------------------ 3 files changed, 25 insertions(+), 30 deletions(-) diff --git a/bincompat-backward.whitelist.conf b/bincompat-backward.whitelist.conf index a1706d103d..0d85590b41 100644 --- a/bincompat-backward.whitelist.conf +++ b/bincompat-backward.whitelist.conf @@ -208,6 +208,15 @@ filter { { matchName="scala.reflect.io.ZipArchive.scala$reflect$io$ZipArchive$$walkIterator" problemName=MissingMethodProblem + }, + // SI-8362: AbstractPromise extends AtomicReference + // It's ok to change a package-protected class in an impl package, + // even though it's not clear why it changed -- bug in generic signature generation? + // -public class scala.concurrent.impl.Promise$DefaultPromise extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise + // +public class scala.concurrent.impl.Promise$DefaultPromise extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise + { + matchName="scala.concurrent.impl.Promise$DefaultPromise" + problemName=MissingTypesProblem } ] } diff --git a/bincompat-forward.whitelist.conf b/bincompat-forward.whitelist.conf index 8fadb65f39..a9fbaa7b87 100644 --- a/bincompat-forward.whitelist.conf +++ b/bincompat-forward.whitelist.conf @@ -372,6 +372,15 @@ filter { { matchName="scala.util.Sorting.scala$util$Sorting$$booleanSort" problemName=MissingMethodProblem + }, + // SI-8362: AbstractPromise extends AtomicReference + // It's ok to change a package-protected class in an impl package, + // even though it's not clear why it changed -- bug in generic signature generation? + // -public class scala.concurrent.impl.Promise$DefaultPromise extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise + // +public class scala.concurrent.impl.Promise$DefaultPromise extends scala.concurrent.impl.AbstractPromise implements scala.concurrent.impl.Promise + { + matchName="scala.concurrent.impl.Promise$DefaultPromise" + problemName=MissingTypesProblem } ] } diff --git a/src/library/scala/concurrent/impl/AbstractPromise.java b/src/library/scala/concurrent/impl/AbstractPromise.java index b8165b6cde..c2520a1692 100644 --- a/src/library/scala/concurrent/impl/AbstractPromise.java +++ b/src/library/scala/concurrent/impl/AbstractPromise.java @@ -1,6 +1,6 @@ /* __ *\ ** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2003-2013, LAMP/EPFL ** +** / __/ __// _ | / / / _ | (c) 2003-2015, LAMP/EPFL ** ** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** ** /____/\___/_/ |_/____/_/ | | ** ** |/ ** @@ -8,33 +8,10 @@ package scala.concurrent.impl; +import java.util.concurrent.atomic.AtomicReference; -import scala.concurrent.util.Unsafe; -import java.util.concurrent.atomic.AtomicReferenceFieldUpdater; - - - -abstract class AbstractPromise { - private volatile Object _ref; - - final static long _refoffset; - - static { - try { - _refoffset = Unsafe.instance.objectFieldOffset(AbstractPromise.class.getDeclaredField("_ref")); - } catch (Throwable t) { - throw new ExceptionInInitializerError(t); - } - } - - protected final boolean updateState(Object oldState, Object newState) { - return Unsafe.instance.compareAndSwapObject(this, _refoffset, oldState, newState); - } - - protected final Object getState() { - return _ref; - } - - protected final static AtomicReferenceFieldUpdater updater = - AtomicReferenceFieldUpdater.newUpdater(AbstractPromise.class, Object.class, "_ref"); -} \ No newline at end of file +@Deprecated // Since 2.11.8. Extend java.util.concurrent.atomic.AtomicReference instead. +abstract class AbstractPromise extends AtomicReference { + protected final boolean updateState(Object oldState, Object newState) { return compareAndSet(oldState, newState); } + protected final Object getState() { return get(); } +} -- cgit v1.2.3 From f5dc96bb550a840ea150985125f52e025ac8ac49 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 31 Jul 2015 15:27:15 +1000 Subject: SI-9425 Leave Companion.apply if constructor is less accessible Calls to synthetic case class apply methods are inlined to the underlying constructor invocation in refchecks. However, this can lead to accessibility errors if the constructor is private. This commit ensures that the constructor is at least as accessible as the apply method before performing this tranform. I've manually checked that other the optimization still works in other cases: scala> class CaseApply { Some(42) } defined class CaseApply scala> :javap -c CaseApply Compiled from "" public class CaseApply { public CaseApply(); Code: 0: aload_0 1: invokespecial #9 // Method java/lang/Object."":()V 4: new #11 // class scala/Some 7: dup 8: bipush 42 10: invokestatic #17 // Method scala/runtime/BoxesRunTime.boxToInteger:(I)Ljava/lang/Integer; 13: invokespecial #20 // Method scala/Some."":(Ljava/lang/Object;)V 16: pop 17: return } --- src/compiler/scala/tools/nsc/typechecker/RefChecks.scala | 3 ++- test/files/run/t9425.scala | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 test/files/run/t9425.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 0198529ef7..90ac1f466d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -1511,7 +1511,8 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans sym.isSourceMethod && sym.isCase && sym.name == nme.apply && - isClassTypeAccessible(tree) + isClassTypeAccessible(tree) && + !tree.tpe.resultType.typeSymbol.primaryConstructor.isLessAccessibleThan(tree.symbol) if (doTransform) { tree foreach { diff --git a/test/files/run/t9425.scala b/test/files/run/t9425.scala new file mode 100644 index 0000000000..f251cc8579 --- /dev/null +++ b/test/files/run/t9425.scala @@ -0,0 +1,8 @@ +class C { case class Foo private (x: Int); Foo.apply(0) } + +object Test { + def test(c: C) = {import c.Foo; Foo.apply(0)} + def main(args: Array[String]): Unit = { + test(new C) + } +} -- cgit v1.2.3 From 6fcd8a6d059c574bd18afe73bcb11812bfba3dd3 Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Wed, 5 Aug 2015 13:05:18 +0100 Subject: Stop mapping to Unit when executing finally code. Finally.invoke has result type Unit so foreach is sufficient here. --- src/library/scala/util/control/Exception.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/util/control/Exception.scala b/src/library/scala/util/control/Exception.scala index aa30887ba0..24c297a2fc 100644 --- a/src/library/scala/util/control/Exception.scala +++ b/src/library/scala/util/control/Exception.scala @@ -105,7 +105,7 @@ object Exception { case x if rethrow(x) => throw x case x if pf isDefinedAt x => pf(x) } - finally fin map (_.invoke()) + finally fin foreach (_.invoke()) /* Create an empty Try container with this Catch and the supplied `Finally`. */ def andFinally(body: => Unit): Catch[T] = fin match { -- cgit v1.2.3 From 0fbb2c451b98e922eeed8547e2d7b7465bbf8b2b Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Wed, 5 Aug 2015 14:00:14 +0100 Subject: Avoid unnecessary implicit view on String Using length instead of size on String to avoid a conversion call. This dump confirms there is a conversion to StringOps when using size. object StringSize { val s = "hi" println(s.size) } $ scalac -Xprint:typer StringSize.scala [[syntax trees at end of typer]] // StringSize.scala package { object StringSize extends scala.AnyRef { def (): StringSize.type = { StringSize.super.(); () }; private[this] val s: String = "hi"; def s: String = StringSize.this.s; scala.this.Predef.println(scala.this.Predef.augmentString(StringSize.this.s).size) } } --- src/library/scala/collection/immutable/StringLike.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/library/scala/collection/immutable/StringLike.scala b/src/library/scala/collection/immutable/StringLike.scala index 1ead894faf..1b52e40b72 100644 --- a/src/library/scala/collection/immutable/StringLike.scala +++ b/src/library/scala/collection/immutable/StringLike.scala @@ -217,8 +217,8 @@ self => pos = thisString.indexOf(separator, prev) } while (pos != -1) - if (prev != thisString.size) - res += thisString.substring(prev, thisString.size) + if (prev != thisString.length) + res += thisString.substring(prev, thisString.length) val initialResult = res.result() pos = initialResult.length -- cgit v1.2.3 From 39ea54bf3eb681de7b0484f60e80002d45ebe7ba Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Thu, 6 Aug 2015 14:10:30 +1000 Subject: Fix tracing of implicit search under -Ytyper-debug The log messages intented to chronicle implicit search were always being filtered out by virtue of the fact that the the tree passed to `printTyping` was already typed, (e.g. with an implicit MethodType.) This commit enabled printing in this case, although it still filters out trees that are deemed unfit for typer tracing, such as `()`. In the context of implicit search, this happens to filter out the noise of: ``` | | | [search #2] start `()`, searching for adaptation to pt=Unit => Foo[Int,Int] (silent: value in Test) implicits disabled | | | [search #3] start `()`, searching for adaptation to pt=(=> Unit) => Foo[Int,Int] (silent: value in Test) implicits disabled | | | \-> ``` ... which I think is desirable. The motivation for this fix was to better display the interaction between implicit search and type inference. For instance: ``` class Foo[A, B] class Test { implicit val f: Foo[Int, String] = ??? def t[A, B](a: A)(implicit f: Foo[A, B]) = ??? t(1) } ``` ```` % scalac -Ytyper-debug sandbox/instantiate.scala ... | |-- t(1) BYVALmode-EXPRmode (site: value in Test) | | |-- t BYVALmode-EXPRmode-FUNmode-POLYmode (silent: value in Test) | | | [adapt] [A, B](a: A)(implicit f: Foo[A,B])Nothing adapted to [A, B](a: A)(implicit f: Foo[A,B])Nothing | | | \-> (a: A)(implicit f: Foo[A,B])Nothing | | |-- 1 BYVALmode-EXPRmode-POLYmode (site: value in Test) | | | \-> Int(1) | | solving for (A: ?A, B: ?B) | | solving for (B: ?B) | | [search #1] start `[A, B](a: A)(implicit f: Foo[A,B])Nothing` inferring type B, searching for adaptation to pt=Foo[Int,B] (silent: value in Test) implicits disabled | | [search #1] considering f | | [adapt] f adapted to => Foo[Int,String] based on pt Foo[Int,B] | | [search #1] solve tvars=?B, tvars.constr= >: String <: String | | solving for (B: ?B) | | [search #1] success inferred value of type Foo[Int,=?String] is SearchResult(Test.this.f, TreeTypeSubstituter(List(type B),List(String))) | | |-- [A, B](a: A)(implicit f: Foo[A,B])Nothing BYVALmode-EXPRmode (site: value in Test) | | | \-> Nothing | | [adapt] [A, B](a: A)(implicit f: Foo[A,B])Nothing adapted to [A, B](a: A)(implicit f: Foo[A,B])Nothing | | \-> Nothing ``` --- src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 6 ++++-- src/compiler/scala/tools/nsc/typechecker/TypersTracking.scala | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index 7ec9cd74a4..14a64abfe2 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -324,8 +324,10 @@ trait Implicits { */ class ImplicitSearch(tree: Tree, pt: Type, isView: Boolean, context0: Context, pos0: Position = NoPosition) extends Typer(context0) with ImplicitsContextErrors { val searchId = implicitSearchId() - private def typingLog(what: String, msg: => String) = - typingStack.printTyping(tree, f"[search #$searchId] $what $msg") + private def typingLog(what: String, msg: => String) = { + if (printingOk(tree)) + typingStack.printTyping(f"[search #$searchId] $what $msg") + } import infer._ if (Statistics.canEnable) Statistics.incCounter(implicitSearchCount) diff --git a/src/compiler/scala/tools/nsc/typechecker/TypersTracking.scala b/src/compiler/scala/tools/nsc/typechecker/TypersTracking.scala index 550fd4e68d..37fbb73b85 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypersTracking.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypersTracking.scala @@ -159,7 +159,7 @@ trait TypersTracking { // Some trees which are typed with mind-numbing frequency and // which add nothing by being printed. Did () type to Unit? Let's // gamble on yes. - private def printingOk(t: Tree) = printTypings && (settings.debug.value || !noPrint(t)) + def printingOk(t: Tree) = printTypings && (settings.debug.value || !noPrint(t)) def noPrintTyping(t: Tree) = (t.tpe ne null) || !printingOk(t) def noPrintAdapt(tree1: Tree, tree2: Tree) = !printingOk(tree1) || ( (tree1.tpe == tree2.tpe) -- cgit v1.2.3 From 2b5f26e61a843af720daf59fa469d921cfc091ca Mon Sep 17 00:00:00 2001 From: Li Yao Date: Fri, 7 Aug 2015 13:48:38 +0800 Subject: Wait until the cat process is finished. --- src/library/scala/sys/process/package.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/library/scala/sys/process/package.scala b/src/library/scala/sys/process/package.scala index 141ec07ab4..445c3aee60 100644 --- a/src/library/scala/sys/process/package.scala +++ b/src/library/scala/sys/process/package.scala @@ -157,7 +157,8 @@ package scala.sys { * while(input.read() != -1) count += 1 * input.close() * } - * cat run new ProcessIO(_.close(), byteCounter, _.close()) + * val p = cat run new ProcessIO(_.close(), byteCounter, _.close()) + * p.exitValue() * count * } * -- cgit v1.2.3 From cb8d924ab894cb3fb2b0e6cfe2fc41afc0b52457 Mon Sep 17 00:00:00 2001 From: stusmall Date: Sun, 2 Aug 2015 20:31:15 -0600 Subject: SI-3623 Improved error message for "filename too long" build errors When building on ecryptfs filenames can be limited to ~142 characters. This limit doesn't take long to hit and can leave the the user with a hard to diagnosis error message. Some legacy file systems will have similarly small limits. This just adds a hint that the error might be related to the underlying fs. --- src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index a34ab914ef..fca0582539 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -532,6 +532,10 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self => case e: java.lang.RuntimeException if e.getMessage != null && (e.getMessage contains "too large!") => reporter.error(sym.pos, s"Could not write class $jclassName because it exceeds JVM code size limits. ${e.getMessage}") + case e: java.io.IOException if e.getMessage != null && (e.getMessage contains "File name too long") => + reporter.error(sym.pos, e.getMessage + "\n" + + "This can happen on some encrypted or legacy file systems. Please see SI-3623 for more details.") + } } -- cgit v1.2.3 From 670f377d19496e8922624b43721cb88b8023a56b Mon Sep 17 00:00:00 2001 From: Adriaan Moors Date: Tue, 18 Aug 2015 12:16:40 -0700 Subject: Revert "SI-8346 Rebuild invariant sets in #toSet, avoiding CCE" --- .../scala/collection/immutable/HashSet.scala | 7 ----- .../scala/collection/immutable/ListSet.scala | 7 ----- src/library/scala/collection/immutable/Set.scala | 16 ++++------ test/files/run/t8346.check | 6 ---- test/files/run/t8346.scala | 34 ---------------------- 5 files changed, 6 insertions(+), 64 deletions(-) delete mode 100644 test/files/run/t8346.check delete mode 100644 test/files/run/t8346.scala diff --git a/src/library/scala/collection/immutable/HashSet.scala b/src/library/scala/collection/immutable/HashSet.scala index f548eac88d..6851ab6bc7 100644 --- a/src/library/scala/collection/immutable/HashSet.scala +++ b/src/library/scala/collection/immutable/HashSet.scala @@ -162,13 +162,6 @@ class HashSet[A] extends AbstractSet[A] def - (e: A): HashSet[A] = nullToEmpty(removed0(e, computeHash(e), 0)) - /** Returns this $coll as an immutable set. - * - * A new set will not be built; lazy collections will stay lazy. - */ - @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") - override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] - override def filter(p: A => Boolean) = { val buffer = new Array[HashSet[A]](bufferSize(size)) nullToEmpty(filter0(p, false, 0, buffer, 0)) diff --git a/src/library/scala/collection/immutable/ListSet.scala b/src/library/scala/collection/immutable/ListSet.scala index a6e6fba0a5..2e17677359 100644 --- a/src/library/scala/collection/immutable/ListSet.scala +++ b/src/library/scala/collection/immutable/ListSet.scala @@ -138,13 +138,6 @@ class ListSet[A] extends AbstractSet[A] override def stringPrefix = "ListSet" - /** Returns this $coll as an immutable set. - * - * A new set will not be built; lazy collections will stay lazy. - */ - @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") - override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] - /** Represents an entry in the `ListSet`. */ protected class Node(override val head: A) extends ListSet[A] with Serializable { diff --git a/src/library/scala/collection/immutable/Set.scala b/src/library/scala/collection/immutable/Set.scala index 7725ad9ee3..0fbf7942d4 100644 --- a/src/library/scala/collection/immutable/Set.scala +++ b/src/library/scala/collection/immutable/Set.scala @@ -35,7 +35,12 @@ trait Set[A] extends Iterable[A] override def companion: GenericCompanion[Set] = Set - override def toSet[B >: A]: Set[B] = to[({type l[a] = immutable.Set[B]})#l] // for bincompat; remove in dev + /** Returns this $coll as an immutable map. + * + * A new map will not be built; lazy collections will stay lazy. + */ + @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") + override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] override def seq: Set[A] = this protected override def parCombiner = ParSet.newCombiner[A] // if `immutable.SetLike` gets introduced, please move this there! @@ -57,7 +62,6 @@ object Set extends ImmutableSetFactory[Set] { def - (elem: Any): Set[Any] = this def iterator: Iterator[Any] = Iterator.empty override def foreach[U](f: Any => U): Unit = {} - override def toSet[B >: Any]: Set[B] = this.asInstanceOf[Set[B]] } private[collection] def emptyInstance: Set[Any] = EmptySet @@ -88,8 +92,6 @@ object Set extends ImmutableSetFactory[Set] { if (f(elem1)) Some(elem1) else None } - @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") - override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] } /** An optimized representation for immutable sets of size 2 */ @@ -121,8 +123,6 @@ object Set extends ImmutableSetFactory[Set] { else if (f(elem2)) Some(elem2) else None } - @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") - override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] } /** An optimized representation for immutable sets of size 3 */ @@ -156,8 +156,6 @@ object Set extends ImmutableSetFactory[Set] { else if (f(elem3)) Some(elem3) else None } - @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") - override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] } /** An optimized representation for immutable sets of size 4 */ @@ -193,8 +191,6 @@ object Set extends ImmutableSetFactory[Set] { else if (f(elem4)) Some(elem4) else None } - @deprecatedOverriding("Immutable sets should do nothing on toSet but return themselves cast as a Set.", "2.11.0") - override def toSet[B >: A]: Set[B] = this.asInstanceOf[Set[B]] } } diff --git a/test/files/run/t8346.check b/test/files/run/t8346.check deleted file mode 100644 index 1ba5c31abe..0000000000 --- a/test/files/run/t8346.check +++ /dev/null @@ -1,6 +0,0 @@ -BitSet: List(invariant, invariant, invariant, invariant) -HashSet: List(covariant (true), covariant (true), covariant (true), covariant (true)) -ListSet: List(covariant (true), covariant (true), covariant (true), covariant (true)) -SortedSet: List(invariant, invariant, invariant, invariant) -TreeSet: List(invariant, invariant, invariant, invariant) -ValueSet: invariant diff --git a/test/files/run/t8346.scala b/test/files/run/t8346.scala deleted file mode 100644 index 5f3df84174..0000000000 --- a/test/files/run/t8346.scala +++ /dev/null @@ -1,34 +0,0 @@ -object Test extends App { - import reflect.ClassTag - - object SomeEnum extends Enumeration { - val one, two, three, four = Value - } - - def sctor[A <: Set[Int]](f: Int => A)(implicit A: ClassTag[A]) - : (String, Int => Set[Int]) = - (A.runtimeClass.getSimpleName, f) - - val inits: Seq[(String, Int => Set[Int])] = { - import collection.immutable.{Seq => _, _} - Seq(sctor(BitSet(_)), - sctor(HashSet(_)), - sctor(ListSet(_)), - sctor(SortedSet(_)), - sctor(TreeSet(_))) - } - - def sVarInfo[A](sa: Set[A]): String = { - val saa = sa.toSet[Any] - if (sa eq saa) s"""covariant (${(saa + "hi") contains "hi"})""" - else "invariant" - } - - inits foreach {case (name, singleton) => - print(s"${name}: ") - val one = singleton(1) - println(Seq(2,3,4).scanLeft(one)(_ + _) map sVarInfo toList) - } - - println(s"ValueSet: ${sVarInfo(SomeEnum.values)}") -} -- cgit v1.2.3 From d978442e5d57d934cb0cfe52daf620a4c11a192b Mon Sep 17 00:00:00 2001 From: Janek Bogucki Date: Wed, 19 Aug 2015 08:50:12 +0100 Subject: Fix method name reference in Predef documentation --- src/library/scala/Predef.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/library/scala/Predef.scala b/src/library/scala/Predef.scala index cef62922ac..94cb331ce1 100644 --- a/src/library/scala/Predef.scala +++ b/src/library/scala/Predef.scala @@ -56,7 +56,7 @@ import scala.io.StdIn * only contain natural numbers (i.e. non-negative), and that the result returned * will also be natural. `require` is distinct from `assert` in that if the * condition fails, then the caller of the function is to blame rather than a - * logical error having been made within `addNaturals` itself. `ensures` is a + * logical error having been made within `addNaturals` itself. `ensuring` is a * form of `assert` that declares the guarantee the function is providing with * regards to its return value. * -- cgit v1.2.3 From e9b47102ed2c49200a4bef48cfb5e21c37086e7b Mon Sep 17 00:00:00 2001 From: martijnhoekstra Date: Wed, 19 Aug 2015 13:15:10 +0200 Subject: Fix documentation of filter introduced in 13f30c --- src/library/scala/collection/immutable/Stream.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/library/scala/collection/immutable/Stream.scala b/src/library/scala/collection/immutable/Stream.scala index d8f0559706..a6c55f8828 100644 --- a/src/library/scala/collection/immutable/Stream.scala +++ b/src/library/scala/collection/immutable/Stream.scala @@ -508,8 +508,8 @@ self => * * @example {{{ * $naturalsEx - * naturalsFrom(1) 10 } filter { _ % 5 == 0 } take 10 mkString(", ") - * // produces + * naturalsFrom(1) filter { _ % 5 == 0 } take 10 mkString(", ") + * // produces "5, 10, 15, 20, 25, 30, 35, 40, 45, 50" * }}} */ override def filter(p: A => Boolean): Stream[A] = { -- cgit v1.2.3