diff options
48 files changed, 645 insertions, 467 deletions
diff --git a/spec/05-classes-and-objects.md b/spec/05-classes-and-objects.md index 8be792d3cb..cff5442641 100644 --- a/spec/05-classes-and-objects.md +++ b/spec/05-classes-and-objects.md @@ -501,14 +501,13 @@ declaration in a template. Such members can be accessed only from within the directly enclosing template and its companion module or [companion class](#object-definitions). -The modifier can be _qualified_ with an identifier $C$ (e.g. -`private[$C$]`) that must denote a class or package -enclosing the definition. Members labeled with such a modifier are -accessible respectively only from code inside the package $C$ or only -from code inside the class $C$ and its +A `private` modifier can be _qualified_ with an identifier $C$ (e.g. +`private[$C$]`) that must denote a class or package enclosing the definition. +Members labeled with such a modifier are accessible respectively only from code +inside the package $C$ or only from code inside the class $C$ and its [companion module](#object-definitions). -An different form of qualification is `private[this]`. A member +A different form of qualification is `private[this]`. A member $M$ marked with this modifier is called _object-protected_; it can be accessed only from within the object in which it is defined. That is, a selection $p.M$ is only legal if the prefix is `this` or `$O$.this`, for some @@ -533,11 +532,10 @@ Protected members of a class can be accessed from within - all templates that have the defining class as a base class, - the companion module of any of those classes. -A `protected` modifier can be qualified with an -identifier $C$ (e.g. `protected[$C$]`) that must denote a -class or package enclosing the definition. Members labeled with such -a modifier are also accessible respectively from all code inside the -package $C$ or from all code inside the class $C$ and its +A `protected` modifier can be qualified with an identifier $C$ (e.g. +`protected[$C$]`) that must denote a class or package enclosing the definition. +Members labeled with such a modifier are also accessible respectively from all +code inside the package $C$ or from all code inside the class $C$ and its [companion module](#object-definitions). A protected identifier $x$ may be used as a member name in a selection @@ -744,7 +742,7 @@ which when applied to parameters conforming to types $\mathit{ps}$ initializes instances of type `$c$[$\mathit{tps}\,$]` by evaluating the template $t$. -###### Example +###### Example – `val` and `var` parameters The following example illustrates `val` and `var` parameters of a class `C`: ```scala @@ -753,7 +751,7 @@ val c = new C(1, "abc", List()) c.z = c.y :: c.z ``` -### Example Private Constructor +###### Example – Private Constructor The following class can be created only from its companion module. ```scala @@ -835,7 +833,7 @@ This defines a class `LinkedList` with three constructors. The second constructor constructs an singleton list, while the third one constructs a list with a given head and tail. -## Case Classes +### Case Classes ```ebnf TmplDef ::= `case' `class' ClassDef diff --git a/spec/15-changelog.md b/spec/15-changelog.md index 54310c921c..3c8739359a 100644 --- a/spec/15-changelog.md +++ b/spec/15-changelog.md @@ -122,8 +122,8 @@ when compiling with `-target:jvm-1.4`, a Scala type such as #### Changes to Case Classes -The Scala compiler generates now for every case class a companion -extractor object (). For instance, given the case class: +The Scala compiler generates a [companion extractor object for every case class] +(05-classes-and-objects.html#case-classes) now. For instance, given the case class: case class X(elem: String) @@ -152,8 +152,9 @@ _(30-Nov-2007)_ #### Mutable variables introduced by pattern binding -Mutable variables can now be introduced by a pattern matching definition -(), just like values can. Examples: +[Mutable variables can now be introduced by a pattern matching definition] +(04-basic-declarations-and-definitions.html#variable-declarations-and-definitions), +just like values can. Examples: var (x, y) = if (positive) (1, 2) else (-1, -3) var hd :: tl = mylist @@ -161,7 +162,7 @@ Mutable variables can now be introduced by a pattern matching definition #### Self-types Self types can now be introduced without defining an alias name for -`this` (). Example: +[`this`](05-classes-and-objects.html#templates). Example: class C { type T <: Trait @@ -175,8 +176,8 @@ _(27-July-2007)_ #### Existential types -It is now possible to define existential types (). An existential type -has the form `T forSome {Q}` where `Q` is a sequence of value and/or +It is now possible to define [existential types](03-types.html#existential-types). +An existential type has the form `T forSome {Q}` where `Q` is a sequence of value and/or type declarations. Given the class definitions class Ref[T] @@ -189,8 +190,9 @@ one may for example write the following existential types #### Lazy values -It is now possible to define lazy value declarations using the new -modifier `lazy` (). A `lazy` value definition evaluates its right hand +It is now possible to define lazy value declarations using the new modifier +[`lazy`](04-basic-declarations-and-definitions.html#value-declarations-and-definitions). +A `lazy` value definition evaluates its right hand side \\(e\\) the first time the value is accessed. Example: import compat.Platform._ @@ -203,8 +205,8 @@ side \\(e\\) the first time the value is accessed. Example: #### Structural types -It is now possible to declare structural types using type refinements -(). For example: +It is now possible to declare structural types using [type refinements] +(03-types.html#compound-types). For example: class File(name: String) { def getName(): String = name @@ -230,10 +232,13 @@ Changes in Version 2.5 _(02-May-2007)_ -#### Type constructor polymorphism[^1] +#### Type constructor polymorphism -Type parameters () and abstract type members () can now also abstract -over type constructors (). +_Implemented by Adriaan Moors_ + +[Type parameters](04-basic-declarations-and-definitions.html#type-parameters) +and abstract +[type members](04-basic-declarations-and-definitions.html#type-declarations-and-type-aliases) can now also abstract over [type constructors](03-types.html#type-constructors). This allows a more precise `Iterable` interface: @@ -254,8 +259,9 @@ over a certain structure (e.g., a `List`) will yield the same structure #### Early object initialization -It is now possible to initialize some fields of an object before any -parent constructors are called (). This is particularly useful for +[Early object initialization](05-classes-and-objects.html#early-definitions) +makes it possible to initialize some fields of an object before any +parent constructors are called. This is particularly useful for traits, which do not have normal constructor parameters. Example: trait Greeting { @@ -273,10 +279,11 @@ called. Therefore, field `msg` in class is properly initialized to . #### For-comprehensions, revised -The syntax of for-comprehensions has changed (). In the new syntax, -generators do not start with a anymore, but filters start with an (and -are called guards). A semicolon in front of a guard is optional. For -example: +The syntax of [for-comprehensions](06-expressions.html#for-comprehensions-and-for-loops) +has changed. +In the new syntax, generators do not start with a `val` anymore, but filters +start with an `if` (and are called guards). +A semicolon in front of a guard is optional. For example: for (val x <- List(1, 2, 3); x % 2 == 0) println(x) @@ -288,8 +295,9 @@ The old syntax is still available but will be deprecated in the future. #### Implicit anonymous functions -It is now possible to define anonymous functions using underscores in -parameter position (). For instance, the expressions in the left column +It is now possible to define [anonymous functions using underscores] +(06-expressions.html#placeholder-syntax-for-anonymous-functions) in +parameter position. For instance, the expressions in the left column are each function values which expand to the anonymous functions on their right. @@ -300,8 +308,8 @@ their right. _.map(f) x => x.map(f) _.map(_ + 1) x => x.map(y => y + 1) -As a special case (), a partially unapplied method is now designated - `m _` instead of the previous notation `&m`. +As a special case, a [partially unapplied method](06-expressions.html#method-values) +is now designated `m _` instead of the previous notation `&m`. The new notation will displace the special syntax forms `.m()` for abstracting over method receivers and `&m` for treating an unapplied @@ -310,8 +318,9 @@ still available, but they will be deprecated in the future. #### Pattern matching anonymous functions, refined -It is now possible to use case clauses to define a function value -directly for functions of arities greater than one (). Previously, only +It is now possible to use [case clauses to define a function value] +(08-pattern-matching.html#pattern-matching-anonymous-functions) +directly for functions of arities greater than one. Previously, only unary functions could be defined that way. Example: def scalarProduct(xs: Array[Double], ys: Array[Double]) = @@ -326,8 +335,9 @@ _(09-Mar-2007)_ #### Object-local private and protected -The `private` and `protected` modifiers now accept a `[this]` qualifier -(). A definition \\(M\\) which is labelled `private[this]` is private, +The `private` and `protected` modifiers now accept a +[`[this]` qualifier](05-classes-and-objects.html#modifiers). +A definition \\(M\\) which is labelled `private[this]` is private, and in addition can be accessed only from within the current object. That is, the only legal prefixes for \\(M\\) are `this` or `$C$.this`. Analogously, a definition \\(M\\) which is labelled `protected[this]` is @@ -348,16 +358,17 @@ Analogously, for any sequence of expressions or patterns \\(x_1 #### Access modifiers for primary constructors -The primary constructor of a class can now be marked or (). If such an -access modifier is given, it comes between the name of the class and its +The primary constructor of a class can now be marked [`private` or `protected`] +(05-classes-and-objects.html#class-definitions). +If such an access modifier is given, it comes between the name of the class and its value parameters. Example: class C[T] private (x: T) { ... } #### Annotations -The support for attributes has been extended and its syntax changed (). -Attributes are now called <span>*annotations*</span>. The syntax has +The support for attributes has been extended and its syntax changed. +Attributes are now called [*annotations*](11-annotations.html). The syntax has been changed to follow Java’s conventions, e.g. `@attribute` instead of `[attribute]`. The old syntax is still available but will be deprecated in the future. @@ -373,12 +384,13 @@ symbol is accessed. #### Decidable subtyping The implementation of subtyping has been changed to prevent infinite -recursions. Termination of subtyping is now ensured by a new restriction -of class graphs to be finitary (). +recursions. +[Termination of subtyping](05-classes-and-objects.html#inheritance-closure) +is now ensured by a new restriction of class graphs to be finitary. #### Case classes cannot be abstract -It is now explicitly ruled out that case classes can be abstract (). The +It is now explicitly ruled out that case classes can be abstract. The specification was silent on this point before, but did not explain how abstract case classes were treated. The Scala compiler allowed the idiom. @@ -386,19 +398,21 @@ idiom. #### New syntax for self aliases and self types It is now possible to give an explicit alias name and/or type for the -self reference (). For instance, in +[self reference](05-classes-and-objects.html#templates) `this`. For instance, in class C { self: D => ... } -the name is introduced as an alias for within and the self type () of is -assumed to be . This construct is introduced now in order to replace +the name `self` is introduced as an alias for `this` within `C` and the +[self type](05-classes-and-objects.html#class-definitions) of `C` is +assumed to be `D`. This construct is introduced now in order to replace eventually both the qualified this construct and the clause in Scala. #### Assignment Operators -It is now possible to combine operators with assignments (). Example: +It is now possible to [combine operators with assignments] +(06-expressions.html#assignment-operators). Example: var x: int = 0 x += 1 @@ -410,8 +424,9 @@ _(23-Jan-2007)_ #### Extractors -It is now possible to define patterns independently of case classes, -using methods in extractor objects (). Here is an example: +It is now possible to define patterns independently of case classes, using +`unapply` methods in [extractor objects](08-pattern-matching.html#extractor-patterns). +Here is an example: object Twice { def apply(x:Int): int = x*2 @@ -422,25 +437,26 @@ using methods in extractor objects (). Here is an example: In the example, `Twice` is an extractor object with two methods: -- The method is used to build even numbers. +- The `apply` method is used to build even numbers. -- The method is used to decompose an even number; it is in a sense the - reverse of . `unapply` methods return option types: for a match that - suceeds, for a match that fails. Pattern variables are returned as - the elements of . If there are several variables, they are grouped - in a tuple. +- The `unapply` method is used to decompose an even number; it is in a sense + the reverse of `apply`. `unapply` methods return option types: + `Some(...)` for a match that suceeds, `None` for a match that fails. + Pattern variables are returned as the elements of `Some`. + If there are several variables, they are grouped in a tuple. -In the second-to-last line, ’s method is used to construct a number . In -the last line, is tested against the pattern . This pattern succeeds for -even numbers and assigns to the variable one half of the number that was -tested. The pattern match makes use of the method of object . More -details on extractors can be found in the paper “Matching Objects with +In the second-to-last line, `Twice`’s method is used to construct a number `x`. +In the last line, `x` is tested against the pattern `Twice(n)`. +This pattern succeeds for even numbers and assigns to the variable `n` one half +of the number that was tested. +The pattern match makes use of the `unapply` method of object `Twice`. +More details on extractors can be found in the paper “Matching Objects with Patterns” by Emir, Odersky and Williams. #### Tuples -A new lightweight syntax for tuples has been introduced (). For any -sequence of types \\(T_1 , … , T_n\\), +A new [lightweight syntax for tuples](06-expressions.html#tuples) has been introduced. +For any sequence of types \\(T_1 , … , T_n\\), \\(\{T_1 , … , T_n \}\\) is a shorthand for `Tuple$n$[$T_1 , … , T_n$]`. @@ -451,8 +467,8 @@ Analogously, for any sequence of expressions or patterns \\(x_1, … , x_n\\), #### Infix operators of greater arities It is now possible to use methods which have more than one parameter as -infix operators (). In this case, all method arguments are written as a -normal parameter list in parentheses. Example: +[infix operators](06-expressions.html#infix-operations). In this case, all +method arguments are written as a normal parameter list in parentheses. Example: class C { def +(x: int, y: String) = ... @@ -462,9 +478,9 @@ normal parameter list in parentheses. Example: #### Deprecated attribute -A new standard attribute `deprecated` is available (11-annotations.html#deprecation-annotations). If a member -definition is marked with this attribute, any reference to the member -will cause a “deprecated” warning message to be emitted. +A new standard attribute [`deprecated`](11-annotations.html#deprecation-annotations) +is available. If a member definition is marked with this attribute, any +reference to the member will cause a “deprecated” warning message to be emitted. Changes in Version 2.3 ---------------------- @@ -473,20 +489,23 @@ _(23-Nov-2006)_ #### Procedures -A simplified syntax for functions returning `unit` has been introduced -(). Scala now allows the following shorthands: +A simplified syntax for [methods returning `unit`] +(04-basic-declarations-and-definitions.html#procedures) has been introduced. +Scala now allows the following shorthands: `def f(params)` \\(\mbox{for}\\) `def f(params): unit` `def f(params) { ... }` \\(\mbox{for}\\) `def f(params): unit = { ... }` #### Type Patterns -The syntax of types in patterns has been refined (). Scala now -distinguishes between type variables (starting with a lower case letter) -and types as type arguments in patterns. Type variables are bound in the -pattern. Other type arguments are, as in previous versions, erased. The -Scala compiler will now issue an “unchecked” warning at places where -type erasure might compromise type-safety. +The [syntax of types in patterns](08-pattern-matching.html#type-patterns) has +been refined. +Scala now distinguishes between type variables (starting with a lower case +letter) and types as type arguments in patterns. +Type variables are bound in the pattern. +Other type arguments are, as in previous versions, erased. +The Scala compiler will now issue an “unchecked” warning at places where type +erasure might compromise type-safety. #### Standard Types @@ -505,43 +524,43 @@ _(23-Aug-2006)_ #### Visibility Qualifier for protected -Protected members can now have a visibility qualifier (), e.g. -`protected[<qualifier>]`. In particular, one can now simulate package -protected access as in Java writing +Protected members can now have a visibility qualifier, e.g. +[`protected[<qualifier>]`](05-classes-and-objects.html#protected). +In particular, one can now simulate package protected access as in Java writing protected[P] def X ... -where would name the package containing . +where would name the package containing `X`. #### Relaxation of Private Acess -Private members of a class can now be referenced from the companion -module of the class and vice versa () +[Private members of a class](05-classes-and-objects.html#private) can now be +referenced from the companion module of the class and vice versa. #### Implicit Lookup -The lookup method for implicit definitions has been generalized (). When -searching for an implicit definition matching a type \\(T\\), now are -considered +The lookup method for [implicit definitions](07-implicits.html#implicit-parameters) +has been generalized. +When searching for an implicit definition matching a type \\(T\\), now are considered 1. all identifiers accessible without prefix, and 2. all members of companion modules of classes associated with \\(T\\). -(The second clause is more general than before). Here, a class is -<span>*associated*</span> with a type \\(T\\) if it is referenced by -some part of \\(T\\), or if it is a base class of some part of \\(T\\). +(The second clause is more general than before). Here, a class is _associated_ +with a type \\(T\\) if it is referenced by some part of \\(T\\), or if it is a +base class of some part of \\(T\\). For instance, to find implicit members corresponding to the type HashSet[List[Int], String] -one would now look in the companion modules (aka static parts) of , , , -and . Before, it was just the static part of . +one would now look in the companion modules (aka static parts) of `HashSet`, +`List`, `Int`, and `String`. Before, it was just the static part of . #### Tightened Pattern Match -A typed pattern match with a singleton type now tests whether the -selector value is reference-equal to p (). Example: +A typed [pattern match with a singleton type `p.type`](08-pattern-matching.html#type-patterns) +now tests whether the selector value is reference-equal to `p`. Example: val p = List(1, 2, 3) val q = List(1, 2) @@ -551,8 +570,8 @@ selector value is reference-equal to p (). Example: case _: q.type => Console.println("q") } -This will match the second case and hence will print “”. Before, the -singleton types were erased to , and therefore the first case would have +This will match the second case and hence will print “q”. Before, the +singleton types were erased to `List`, and therefore the first case would have matched, which is non-sensical. Changes in Version 2.1.7 @@ -562,8 +581,8 @@ _(19-Jul-2006)_ #### Multi-Line string literals -It is now possible to write multi-line string-literals enclosed in -triple quotes (). Example: +It is now possible to write [multi-line string-literals] +(01-lexical-syntax.html#string-literals) enclosed in triple quotes. Example: """this is a multi-line @@ -574,13 +593,14 @@ string literals. #### Closure Syntax -The syntax of closures has been slightly restricted (). The form +The syntax of [closures](06-expressions.html#anonymous-functions) +has been slightly restricted. The form x: T => E is valid only when enclosed in braces, i.e. `{ x: T => E }`. The following is illegal, because it might be read as the value x typed with -the type T =\> E: +the type `T => E`: val f = x: T => E @@ -596,8 +616,9 @@ _(24-May-2006)_ #### Class Literals -There is a new syntax for class literals (): For any class type \\(C\\), -`classOf[$C$]` designates the run-time representation of \\(C\\). +There is a new syntax for [class literals](06-expressions.html#literals): +For any class type \\(C\\), `classOf[$C$]` designates the run-time +representation of \\(C\\). Changes in Version 2.0 ---------------------- @@ -612,14 +633,14 @@ changes. #### New Keywords The following three words are now reserved; they cannot be used as -identifiers () +[identifiers](01-lexical-syntax.html#identifiers): implicit match requires #### Newlines as Statement Separators -Newlines can now be used as statement separators in place of semicolons -() +[Newlines](http://www.scala-lang.org/files/archive/spec/2.11/) +can now be used as statement separators in place of semicolons. #### Syntax Restrictions @@ -649,8 +670,8 @@ is no longer supported. A `with` connective is only allowed following an class C extends AnyRef with M { ... } . -However, assuming `M` is a trait (see [sec:traits]), it is also legal to -write +However, assuming `M` is a [trait](05-classes-and-objects.html#traits), +it is also legal to write class C extends M { ... } @@ -665,7 +686,7 @@ where `S` is the superclass of `M`. The only form of regular expression pattern that is currently supported is a sequence pattern, which might end in a sequence wildcard . Example: - case List(1, 2, _*) => ... // will match all lists starting with \code{1,2}. + case List(1, 2, _*) => ... // will match all lists starting with 1, 2, ... It is at current not clear whether this is a permanent restriction. We are evaluating the possibility of re-introducing full regular expression @@ -686,7 +707,8 @@ old syntax is still available but is considered deprecated. #### For-comprehensions -For-comprehensions () now admit value and pattern definitions. Example: +[For-comprehensions](06-expressions.html#for-comprehensions-and-for-loops) +now admit value and pattern definitions. Example: for { val x <- List.range(1, 100) @@ -700,8 +722,9 @@ for-comprehension. #### Conversions -The rules for implicit conversions of methods to functions () have been -tightened. Previously, a parameterized method used as a value was always +The rules for [implicit conversions of methods to functions] +(06-expressions.html#method-conversions) have been tightened. +Previously, a parameterized method used as a value was always implicitly converted to a function. This could lead to unexpected results when method arguments where forgotten. Consider for instance the statement below: @@ -750,10 +773,11 @@ instance, the `show` expression above will now be expanded to show(x.toString()) . Scala version 2.0 also relaxes the rules of overriding with respect to -empty parameter lists. The revised definition of <span>*matching -members*</span> () makes it now possible to override a method with an +empty parameter lists. The revised definition of +[_matching members_](05-classes-and-objects.html#class-members) +makes it now possible to override a method with an explicit, but empty parameter list `()` with a parameterless method, and -<span>*vice versa*</span>. For instance, the following class definition +_vice versa_. For instance, the following class definition is now legal: class C { @@ -766,26 +790,29 @@ parameter list. #### Class Parameters -A class parameter may now be prefixed by `val` or `var` (). +A [class parameter](05-classes-and-objects.html#class-definitions) +may now be prefixed by `val` or `var`. #### Private Qualifiers Previously, Scala had three levels of visibility: <span>*private*</span>, <span>*protected*</span> and <span>*public*</span>. There was no way to restrict accesses to members -of the current package, as in Java. Scala 2 now defines access -qualifiers that let one express this level of visibility, among others. -In the definition +of the current package, as in Java. + +Scala 2 now defines [access qualifiers](05-classes-and-objects.html#modifiers) +that let one express this level of visibility, among others. In the definition private[C] def f(...) access to `f` is restricted to all code within the class or package `C` -(which must contain the definition of `f`) () +(which must contain the definition of `f`). #### Changes in the Mixin Model -The model which details mixin composition of classes has changed -significantly. The main differences are: +The model which details [mixin composition of classes] +(05-classes-and-objects.html#templates) has changed significantly. +The main differences are: 1. We now distinguish between <span>*traits*</span> that are used as mixin classes and normal classes. The syntax of traits has been @@ -802,22 +829,19 @@ significantly. The main differences are: different mixins. This makes method overloading in Scala conceptually the same as in Java. -The new mixin model is explained in more detail in . - #### Implicit Parameters Views in Scala 1.0 have been replaced by the more general concept of -implicit parameters () +[implicit parameters](07-implicits.html#implicit-parameters). #### Flexible Typing of Pattern Matching The new version of Scala implements more flexible typing rules when it -comes to pattern matching over heterogeneous class hierarchies (). A -<span>*heterogeneous class hierarchy*</span> is one where subclasses +comes to [pattern matching over heterogeneous class hierarchies] +(08-pattern-matching.html#pattern-matching-expressions). +A <span>*heterogeneous class hierarchy*</span> is one where subclasses inherit a common superclass with different parameter types. With the new rules in Scala version 2.0 one can perform pattern matches over such hierarchies with more precise typings that keep track of the information -gained by comparing the types of a selector and a matching pattern (). +gained by comparing the types of a selector and a matching pattern. This gives Scala capabilities analogous to guarded algebraic data types. - -[^1]: Implemented by Adriaan Moors diff --git a/src/compiler/scala/tools/nsc/Properties.scala b/src/compiler/scala/tools/nsc/Properties.scala index 9f160e2485..ca7d8776d4 100644 --- a/src/compiler/scala/tools/nsc/Properties.scala +++ b/src/compiler/scala/tools/nsc/Properties.scala @@ -13,7 +13,7 @@ object Properties extends scala.util.PropertiesTrait { // settings based on jar properties, falling back to System prefixed by "scala." def residentPromptString = scalaPropOrElse("resident.prompt", "\nnsc> ") - def shellPromptString = scalaPropOrElse("shell.prompt", "\nscala> ") + def shellPromptString = scalaPropOrElse("shell.prompt", "%nscala> ") // message to display at EOF (which by default ends with // a newline so as not to break the user's terminal) def shellInterruptedString = scalaPropOrElse("shell.interrupted", f":quit$lineSeparator") diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala index eadc404bee..dec5adc9aa 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BCodeAsmCommon.scala @@ -9,6 +9,7 @@ package backend.jvm import scala.tools.nsc.Global import scala.tools.nsc.backend.jvm.BTypes.{InternalName, MethodInlineInfo, InlineInfo} import BackendReporting.ClassSymbolInfoFailureSI9111 +import scala.tools.asm /** * This trait contains code shared between GenBCode and GenASM that depends on types defined in @@ -229,6 +230,44 @@ final class BCodeAsmCommon[G <: Global](val global: G) { } /** + * Reconstruct the classfile flags from a Java defined class symbol. + * + * The implementation of this method is slightly different that `javaFlags` in BTypesFromSymbols. + * The javaFlags method is primarily used to map Scala symbol flags to sensible classfile flags + * that are used in the generated classfiles. For example, all classes emitted by the Scala + * compiler have ACC_PUBLIC. + * + * When building a [[ClassBType]] from a Java class symbol, the flags in the type's `info` have + * to correspond exactly to the flags in the classfile. For example, if the class is package + * protected (i.e., it doesn't have the ACC_PUBLIC flag), this needs to be reflected in the + * ClassBType. For example, the inliner needs the correct flags for access checks. + * + * Class flags are listed here: + * https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1-200-E.1 + */ + def javaClassfileFlags(classSym: Symbol): Int = { + assert(classSym.isJava, s"Expected Java class symbol, got ${classSym.fullName}") + import asm.Opcodes._ + def enumFlags = ACC_ENUM | { + // Java enums have the `ACC_ABSTRACT` flag if they have a deferred method. + // We cannot trust `hasAbstractFlag`: the ClassfileParser adds `ABSTRACT` and `SEALED` to all + // Java enums for exhaustiveness checking. + val hasAbstractMethod = classSym.info.decls.exists(s => s.isMethod && s.isDeferred) + if (hasAbstractMethod) ACC_ABSTRACT else 0 + } + GenBCode.mkFlags( + if (classSym.isPublic) ACC_PUBLIC else 0, + if (classSym.isFinal) ACC_FINAL else 0, + // see the link above. javac does the same: ACC_SUPER for all classes, but not interfaces. + if (classSym.isInterface) ACC_INTERFACE else ACC_SUPER, + // for Java enums, we cannot trust `hasAbstractFlag` (see comment in enumFlags) + if (!classSym.hasEnumFlag && classSym.hasAbstractFlag) ACC_ABSTRACT else 0, + if (classSym.isArtifact) ACC_SYNTHETIC else 0, + if (classSym.hasEnumFlag) enumFlags else 0 + ) + } + + /** * The member classes of a class symbol. Note that the result of this method depends on the * current phase, for example, after lambdalift, all local classes become member of the enclosing * class. @@ -399,3 +438,16 @@ final class BCodeAsmCommon[G <: Global](val global: G) { InlineInfo(traitSelfType, isEffectivelyFinal, methodInlineInfos, warning) } } + +object BCodeAsmCommon { + /** + * Valid flags for InnerClass attribute entry. + * See http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.6 + */ + val INNER_CLASSES_FLAGS = { + asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_PRIVATE | asm.Opcodes.ACC_PROTECTED | + asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_FINAL | asm.Opcodes.ACC_INTERFACE | + asm.Opcodes.ACC_ABSTRACT | asm.Opcodes.ACC_SYNTHETIC | asm.Opcodes.ACC_ANNOTATION | + asm.Opcodes.ACC_ENUM + } +} diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala index e61190bf3a..176292669c 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypes.scala @@ -898,7 +898,7 @@ abstract class BTypes { // the static flag in the InnerClass table has a special meaning, see InnerClass comment i.flags & ~Opcodes.ACC_STATIC, if (isStaticNestedClass) Opcodes.ACC_STATIC else 0 - ) & ClassBType.INNER_CLASSES_FLAGS + ) & BCodeAsmCommon.INNER_CLASSES_FLAGS ) }) @@ -987,17 +987,6 @@ abstract class BTypes { } object ClassBType { - /** - * Valid flags for InnerClass attribute entry. - * See http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.6 - */ - private val INNER_CLASSES_FLAGS = { - asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_PRIVATE | asm.Opcodes.ACC_PROTECTED | - asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_FINAL | asm.Opcodes.ACC_INTERFACE | - asm.Opcodes.ACC_ABSTRACT | asm.Opcodes.ACC_SYNTHETIC | asm.Opcodes.ACC_ANNOTATION | - asm.Opcodes.ACC_ENUM - } - // Primitive classes have no super class. A ClassBType for those is only created when // they are actually being compiled (e.g., when compiling scala/Boolean.scala). private val hasNoSuper = Set( diff --git a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala index 356af36455..d68c916f09 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/BTypesFromSymbols.scala @@ -213,35 +213,6 @@ class BTypesFromSymbols[G <: Global](val global: G) extends BTypes { assert(!primitiveTypeMap.contains(sym) || isCompilingPrimitive, sym) } - /** - * Reconstruct the classfile flags from a Java defined class symbol. - * - * The implementation of this method is slightly different that [[javaFlags]]. The javaFlags - * method is primarily used to map Scala symbol flags to sensible classfile flags that are used - * in the generated classfiles. For example, all classes emitted by the Scala compiler have - * ACC_PUBLIC. - * - * When building a [[ClassBType]] from a Java class symbol, the flags in the type's `info` have - * to correspond exactly to the flags in the classfile. For example, if the class is package - * protected (i.e., it doesn't have the ACC_PUBLIC flag), this needs to be reflected in the - * ClassBType. For example, the inliner needs the correct flags for access checks. - * - * Class flags are listed here: - * https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.1-200-E.1 - */ - private def javaClassfileFlags(classSym: Symbol): Int = { - assert(classSym.isJava, s"Expected Java class symbol, got ${classSym.fullName}") - import asm.Opcodes._ - GenBCode.mkFlags( - if (classSym.isPublic) ACC_PUBLIC else 0, - if (classSym.isFinal) ACC_FINAL else 0, - if (classSym.isInterface) ACC_INTERFACE else ACC_SUPER, // see the link above. javac does the same: ACC_SUPER for all classes, but not interfaces. - if (classSym.hasAbstractFlag) ACC_ABSTRACT else 0, - if (classSym.isArtifact) ACC_SYNTHETIC else 0, - if (classSym.hasEnumFlag) ACC_ENUM else 0 - ) - } - private def setClassInfo(classSym: Symbol, classBType: ClassBType): ClassBType = { val superClassSym = if (classSym.isImplClass) ObjectClass else classSym.superClass assert( diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala index 76af40b330..71686fd9d7 100644 --- a/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala +++ b/src/compiler/scala/tools/nsc/backend/jvm/GenASM.scala @@ -479,10 +479,6 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self => val CLASS_CONSTRUCTOR_NAME = "<clinit>" val INSTANCE_CONSTRUCTOR_NAME = "<init>" - val INNER_CLASSES_FLAGS = - (asm.Opcodes.ACC_PUBLIC | asm.Opcodes.ACC_PRIVATE | asm.Opcodes.ACC_PROTECTED | - asm.Opcodes.ACC_STATIC | asm.Opcodes.ACC_INTERFACE | asm.Opcodes.ACC_ABSTRACT | asm.Opcodes.ACC_FINAL) - // ----------------------------------------------------------------------------------------- // factory methods // ----------------------------------------------------------------------------------------- @@ -756,9 +752,9 @@ abstract class GenASM extends SubComponent with BytecodeWriters { self => val flagsWithFinal: Int = mkFlags( // See comment in BTypes, when is a class marked static in the InnerClass table. if (isOriginallyStaticOwner(innerSym.originalOwner)) asm.Opcodes.ACC_STATIC else 0, - javaFlags(innerSym), + (if (innerSym.isJava) javaClassfileFlags(innerSym) else javaFlags(innerSym)) & ~asm.Opcodes.ACC_STATIC, if(isDeprecated(innerSym)) asm.Opcodes.ACC_DEPRECATED else 0 // ASM pseudo-access flag - ) & (INNER_CLASSES_FLAGS | asm.Opcodes.ACC_DEPRECATED) + ) & (BCodeAsmCommon.INNER_CLASSES_FLAGS | asm.Opcodes.ACC_DEPRECATED) val flags = if (innerSym.isModuleClass) flagsWithFinal & ~asm.Opcodes.ACC_FINAL else flagsWithFinal // For SI-5676, object overriding. val jname = javaName(innerSym) // never null val oname = outerName(innerSym) // null when method-enclosed diff --git a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala index d34c14be0f..9708cba281 100644 --- a/src/compiler/scala/tools/nsc/javac/JavaParsers.scala +++ b/src/compiler/scala/tools/nsc/javac/JavaParsers.scala @@ -761,9 +761,13 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { val interfaces = interfacesOpt() accept(LBRACE) val buf = new ListBuffer[Tree] + var enumIsFinal = true def parseEnumConsts() { if (in.token != RBRACE && in.token != SEMI && in.token != EOF) { - buf += enumConst(enumType) + val (const, hasClassBody) = enumConst(enumType) + buf += const + // if any of the enum constants has a class body, the enum class is not final (JLS 8.9.) + enumIsFinal &&= !hasClassBody if (in.token == COMMA) { in.nextToken() parseEnumConsts() @@ -793,15 +797,25 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { accept(RBRACE) val superclazz = AppliedTypeTree(javaLangDot(tpnme.Enum), List(enumType)) + val finalFlag = if (enumIsFinal) Flags.FINAL else 0l + val abstractFlag = { + // javac adds `ACC_ABSTRACT` to enum classes with deferred members + val hasAbstractMember = body exists { + case d: DefDef => d.mods.isDeferred + case _ => false + } + if (hasAbstractMember) Flags.ABSTRACT else 0l + } addCompanionObject(consts ::: statics ::: predefs, atPos(pos) { - ClassDef(mods | Flags.ENUM, name, List(), + ClassDef(mods | Flags.ENUM | finalFlag | abstractFlag, name, List(), makeTemplate(superclazz :: interfaces, body)) }) } - def enumConst(enumType: Tree) = { + def enumConst(enumType: Tree): (ValDef, Boolean) = { annotations() - atPos(in.currentPos) { + var hasClassBody = false + val res = atPos(in.currentPos) { val name = ident() if (in.token == LPAREN) { // skip arguments @@ -809,12 +823,14 @@ trait JavaParsers extends ast.parser.ParsersCommon with JavaScanners { accept(RPAREN) } if (in.token == LBRACE) { + hasClassBody = true // skip classbody skipAhead() accept(RBRACE) } ValDef(Modifiers(Flags.ENUM | Flags.STABLE | Flags.JAVA | Flags.STATIC), name.toTermName, enumType, blankExpr) } + (res, hasClassBody) } def typeDecl(mods: Modifiers): List[Tree] = in.token match { diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index 518a402230..660028eab8 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -539,6 +539,8 @@ abstract class ClassfileParser { devWarning(s"no linked class for java enum $sym in ${sym.owner}. A referencing class file might be missing an InnerClasses entry.") case linked => if (!linked.isSealed) + // Marking the enum class SEALED | ABSTRACT enables exhaustiveness checking. + // This is a bit of a hack and requires excluding the ABSTRACT flag in the backend, see method javaClassfileFlags. linked setFlag (SEALED | ABSTRACT) linked addChild sym } diff --git a/src/library/scala/sys/BooleanProp.scala b/src/library/scala/sys/BooleanProp.scala index 74b0a9077b..e5e4668edb 100644 --- a/src/library/scala/sys/BooleanProp.scala +++ b/src/library/scala/sys/BooleanProp.scala @@ -63,12 +63,13 @@ object BooleanProp { def valueIsTrue[T](key: String): BooleanProp = new BooleanPropImpl(key, _.toLowerCase == "true") /** As an alternative, this method creates a BooleanProp which is true - * if the key exists in the map. This way -Dfoo.bar is enough to be - * considered true. + * if the key exists in the map and is not assigned a value other than "true", + * compared case-insensitively, or the empty string. This way -Dmy.property + * results in a true-valued property, but -Dmy.property=false does not. * * @return A BooleanProp with a liberal truth policy */ - def keyExists[T](key: String): BooleanProp = new BooleanPropImpl(key, _ => true) + def keyExists[T](key: String): BooleanProp = new BooleanPropImpl(key, s => s == "" || s.equalsIgnoreCase("true")) /** A constant true or false property which ignores all method calls. */ diff --git a/src/partest-extras/scala/tools/partest/ReplTest.scala b/src/partest-extras/scala/tools/partest/ReplTest.scala index 5b65d6ab9b..1fde2370d3 100644 --- a/src/partest-extras/scala/tools/partest/ReplTest.scala +++ b/src/partest-extras/scala/tools/partest/ReplTest.scala @@ -75,18 +75,20 @@ abstract class SessionTest extends ReplTest { * Retain user input: prompt lines and continuations, without the prefix; or pasted text plus ctl-D. */ import SessionTest._ - override final def code = input findAllMatchIn (expected mkString ("", "\n", "\n")) map { - case input(null, null, prompted) => + lazy val pasted = input(prompt) + override final def code = pasted findAllMatchIn (expected mkString ("", "\n", "\n")) map { + case pasted(null, null, prompted) => def continued(m: Match): Option[String] = m match { case margin(text) => Some(text) case _ => None } margin.replaceSomeIn(prompted, continued) - case input(cmd, pasted, null) => + case pasted(cmd, pasted, null) => cmd + pasted + "\u0004" } mkString - final def prompt = "scala> " + // Just the last line of the interactive prompt + def prompt = "scala> " /** Default test is to compare expected and actual output and emit the diff on a failed comparison. */ override def show() = { @@ -98,7 +100,7 @@ abstract class SessionTest extends ReplTest { } object SessionTest { // \R for line break is Java 8, \v for vertical space might suffice - val input = """(?m)^scala> (:pa.*\u000A)// Entering paste mode.*\u000A\u000A((?:.*\u000A)*)\u000A// Exiting paste mode.*\u000A|^scala> (.*\u000A(?:\s*\| .*\u000A)*)""".r + def input(prompt: String) = s"""(?m)^$prompt(:pa.*\u000A)// Entering paste mode.*\u000A\u000A((?:.*\u000A)*)\u000A// Exiting paste mode.*\u000A|^scala> (.*\u000A(?:\\s*\\| .*\u000A)*)""".r val margin = """(?m)^\s*\| (.*)$""".r } diff --git a/src/reflect/scala/reflect/internal/ClassfileConstants.scala b/src/reflect/scala/reflect/internal/ClassfileConstants.scala index e0a6757d34..53241fb15b 100644 --- a/src/reflect/scala/reflect/internal/ClassfileConstants.scala +++ b/src/reflect/scala/reflect/internal/ClassfileConstants.scala @@ -344,10 +344,12 @@ object ClassfileConstants { case JAVA_ACC_STATIC => STATIC case JAVA_ACC_ABSTRACT => if (isAnnotation) 0L else if (isClass) ABSTRACT else DEFERRED case JAVA_ACC_INTERFACE => if (isAnnotation) 0L else TRAIT | INTERFACE | ABSTRACT + case JAVA_ACC_ENUM => ENUM case _ => 0L } - private def translateFlags(jflags: Int, baseFlags: Long, isAnnotation: Boolean, isClass: Boolean): Long = { - def translateFlag0(jflags: Int): Long = translateFlag(jflags, isAnnotation, isClass) + private def translateFlags(jflags: Int, baseFlags: Long, isClass: Boolean): Long = { + val isAnnot = isAnnotation(jflags) + def translateFlag0(jflags: Int): Long = translateFlag(jflags, isAnnot, isClass) var res: Long = JAVA | baseFlags /* fast, elegant, maintainable, pick any two... */ res |= translateFlag0(jflags & JAVA_ACC_PRIVATE) @@ -357,17 +359,18 @@ object ClassfileConstants { res |= translateFlag0(jflags & JAVA_ACC_STATIC) res |= translateFlag0(jflags & JAVA_ACC_ABSTRACT) res |= translateFlag0(jflags & JAVA_ACC_INTERFACE) + res |= translateFlag0(jflags & JAVA_ACC_ENUM) res } def classFlags(jflags: Int): Long = { - translateFlags(jflags, 0, isAnnotation(jflags), isClass = true) + translateFlags(jflags, 0, isClass = true) } def fieldFlags(jflags: Int): Long = { - translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) MUTABLE else 0 , isAnnotation(jflags), isClass = false) + translateFlags(jflags, if ((jflags & JAVA_ACC_FINAL) == 0) MUTABLE else 0 , isClass = false) } def methodFlags(jflags: Int): Long = { - translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | ARTIFACT else 0, isAnnotation(jflags), isClass = false) + translateFlags(jflags, if ((jflags & JAVA_ACC_BRIDGE) != 0) BRIDGE | ARTIFACT else 0, isClass = false) } } object FlagTranslation extends FlagTranslation { } diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index c705ca7069..15a87200f1 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -561,7 +561,7 @@ private[internal] trait TypeMaps { | tparams ${rhsSym.typeParams map own_s mkString ", "} |""" - if (argIndex < 0) + if (!rhsArgs.isDefinedAt(argIndex)) abort(s"Something is wrong: cannot find $lhs in applied type $rhs\n" + explain) else { val targ = rhsArgs(argIndex) diff --git a/src/repl/scala/tools/nsc/interpreter/Formatting.scala b/src/repl/scala/tools/nsc/interpreter/Formatting.scala index 43e653edfd..844997429c 100644 --- a/src/repl/scala/tools/nsc/interpreter/Formatting.scala +++ b/src/repl/scala/tools/nsc/interpreter/Formatting.scala @@ -8,28 +8,25 @@ package interpreter import util.stringFromWriter -trait Formatting { - def prompt: String +class Formatting(indent: Int) { - def spaces(code: String): String = { + private val indentation = " " * indent + + private def indenting(code: String): Boolean = { /** Heuristic to avoid indenting and thereby corrupting """-strings and XML literals. */ val tokens = List("\"\"\"", "</", "/>") val noIndent = (code contains "\n") && (tokens exists code.contains) - if (noIndent) "" - else prompt drop 1 map (_ => ' ') + !noIndent } /** Indent some code by the width of the scala> prompt. * This way, compiler error messages read better. */ - def indentCode(code: String) = { - val indent = spaces(code) - stringFromWriter(str => - for (line <- code.lines) { - str print indent - str print (line + "\n") - str.flush() - } - ) - } + def indentCode(code: String) = stringFromWriter(str => + for (line <- code.lines) { + if (indenting(code)) str print indentation + str println line + str.flush() + } + ) } diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index a3047ccc8e..525609171e 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -111,11 +111,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } class ILoopInterpreter extends IMain(settings, out) { - outer => - - override lazy val formatting = new Formatting { - def prompt = ILoop.this.prompt - } + // the expanded prompt but without color escapes and without leading newline, for purposes of indenting + override lazy val formatting: Formatting = new Formatting( + (replProps.promptString format Properties.versionNumberString).lines.toList.last.length + ) override protected def parentClassLoader = settings.explicitParentLoader.getOrElse( classOf[ILoop].getClassLoader ) } @@ -199,10 +198,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) echo("%d %s".format(index + offset, line)) } - private val currentPrompt = Properties.shellPromptString - /** Prompt to print when awaiting input */ - def prompt = currentPrompt + def prompt = replProps.prompt import LoopCommand.{ cmd, nullary } @@ -412,14 +409,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } private def readOneLine() = { - import scala.io.AnsiColor.{ MAGENTA, RESET } out.flush() - in readLine ( - if (replProps.colorOk) - MAGENTA + prompt + RESET - else - prompt - ) + in readLine prompt } /** The main read-eval-print loop for the repl. It calls @@ -770,8 +761,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) } private object paste extends Pasted { + import scala.util.matching.Regex.quote val ContinueString = " | " - val PromptString = "scala> " + val PromptString = prompt.lines.toList.last + val anyPrompt = s"""\\s*(?:${quote(PromptString.trim)}|${quote(AltPromptString.trim)})\\s*""".r + + def isPrompted(line: String) = matchesPrompt(line) + def isPromptOnly(line: String) = line match { case anyPrompt() => true ; case _ => false } def interpret(line: String): Unit = { echo(line.trim) @@ -781,10 +777,17 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) def transcript(start: String) = { echo("\n// Detected repl transcript paste: ctrl-D to finish.\n") - apply(Iterator(start) ++ readWhile(_.trim != PromptString.trim)) + apply(Iterator(start) ++ readWhile(!isPromptOnly(_))) } + + def unapply(line: String): Boolean = isPrompted(line) + } + + private object invocation { + def unapply(line: String): Boolean = Completion.looksLikeInvocation(line) } - import paste.{ ContinueString, PromptString } + + private val lineComment = """\s*//.*""".r // all comment /** Interpret expressions starting with the first line. * Read lines until a complete compilation unit is available @@ -796,53 +799,42 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) // signal completion non-completion input has been received in.completion.resetVerbosity() - def reallyInterpret = { - val reallyResult = intp.interpret(code) - (reallyResult, reallyResult match { - case IR.Error => None - case IR.Success => Some(code) - case IR.Incomplete => - if (in.interactive && code.endsWith("\n\n")) { - echo("You typed two blank lines. Starting a new command.") + def reallyInterpret = intp.interpret(code) match { + case IR.Error => None + case IR.Success => Some(code) + case IR.Incomplete if in.interactive && code.endsWith("\n\n") => + echo("You typed two blank lines. Starting a new command.") + None + case IR.Incomplete => + in.readLine(paste.ContinueString) match { + case null => + // we know compilation is going to fail since we're at EOF and the + // parser thinks the input is still incomplete, but since this is + // a file being read non-interactively we want to fail. So we send + // it straight to the compiler for the nice error message. + intp.compileString(code) None - } - else in.readLine(ContinueString) match { - case null => - // we know compilation is going to fail since we're at EOF and the - // parser thinks the input is still incomplete, but since this is - // a file being read non-interactively we want to fail. So we send - // it straight to the compiler for the nice error message. - intp.compileString(code) - None - - case line => interpretStartingWith(code + "\n" + line) - } - }) + + case line => interpretStartingWith(code + "\n" + line) + } } - /** Here we place ourselves between the user and the interpreter and examine - * the input they are ostensibly submitting. We intervene in several cases: + /* Here we place ourselves between the user and the interpreter and examine + * the input they are ostensibly submitting. We intervene in several cases: * - * 1) If the line starts with "scala> " it is assumed to be an interpreter paste. - * 2) If the line starts with "." (but not ".." or "./") it is treated as an invocation - * on the previous result. - * 3) If the Completion object's execute returns Some(_), we inject that value - * and avoid the interpreter, as it's likely not valid scala code. + * 1) If the line starts with "scala> " it is assumed to be an interpreter paste. + * 2) If the line starts with "." (but not ".." or "./") it is treated as an invocation + * on the previous result. + * 3) If the Completion object's execute returns Some(_), we inject that value + * and avoid the interpreter, as it's likely not valid scala code. */ - if (code == "") None - else if (!paste.running && code.trim.startsWith(PromptString)) { - paste.transcript(code) - None - } - else if (Completion.looksLikeInvocation(code) && intp.mostRecentVar != "") { - interpretStartingWith(intp.mostRecentVar + code) + code match { + case "" => None + case lineComment() => None // line comment, do nothing + case paste() if !paste.running => paste.transcript(code) ; None + case invocation() if intp.mostRecentVar != "" => interpretStartingWith(intp.mostRecentVar + code) + case _ => reallyInterpret } - else if (code.trim startsWith "//") { - // line comment, do nothing - None - } - else - reallyInterpret._2 } // runs :load `file` on any files passed via -i diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index e355d9f864..2550a5dc57 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -112,12 +112,13 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set def this(factory: ScriptEngineFactory) = this(factory, new Settings()) def this() = this(new Settings()) - lazy val formatting: Formatting = new Formatting { - val prompt = Properties.shellPromptString - } + // the expanded prompt but without color escapes and without leading newline, for purposes of indenting + lazy val formatting: Formatting = new Formatting( + (replProps.promptString format Properties.versionNumberString).lines.toList.last.length + ) lazy val reporter: ReplReporter = new ReplReporter(this) - import formatting._ + import formatting.indentCode import reporter.{ printMessage, printUntruncatedMessage } // This exists mostly because using the reporter too early leads to deadlock. @@ -468,7 +469,7 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set } private def requestFromLine(line: String, synthetic: Boolean): Either[IR.Result, Request] = { - val content = indentCode(line) + val content = line //indentCode(line) val trees = parse(content) match { case parse.Incomplete => return Left(IR.Incomplete) case parse.Error => return Left(IR.Error) @@ -909,10 +910,10 @@ 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""" - |$preambleHeader - |%s%s%s - """.stripMargin.format(lineRep.readName, envLines.map(" " + _ + ";\n").mkString, - importsPreamble, indentCode(toCompute)) + |${preambleHeader format lineRep.readName} + |${envLines mkString (" ", ";\n ", ";\n")} + |$importsPreamble + |${indentCode(toCompute)}""".stripMargin val generate = (m: MemberHandler) => m extraCodeToEvaluate Request.this diff --git a/src/repl/scala/tools/nsc/interpreter/Pasted.scala b/src/repl/scala/tools/nsc/interpreter/Pasted.scala index f5db3d9e3a..5f388eb15b 100644 --- a/src/repl/scala/tools/nsc/interpreter/Pasted.scala +++ b/src/repl/scala/tools/nsc/interpreter/Pasted.scala @@ -16,17 +16,21 @@ package interpreter * the same result. */ abstract class Pasted { + def interpret(line: String): Unit def ContinueString: String def PromptString: String - def interpret(line: String): Unit + def AltPromptString: String = "scala> " + + private val testBoth = PromptString != AltPromptString + private val spacey = " \t".toSet - def matchesPrompt(line: String) = matchesString(line, PromptString) + def matchesPrompt(line: String) = matchesString(line, PromptString) || testBoth && matchesString(line, AltPromptString) def matchesContinue(line: String) = matchesString(line, ContinueString) def running = isRunning private def matchesString(line: String, target: String): Boolean = ( (line startsWith target) || - (line.nonEmpty && " \t".toSet(line.head) && matchesString(line.tail, target)) + (line.nonEmpty && spacey(line.head) && matchesString(line.tail, target)) ) private def stripString(line: String, target: String) = line indexOf target match { case -1 => line @@ -39,7 +43,9 @@ abstract class Pasted { private class PasteAnalyzer(val lines: List[String]) { val referenced = lines flatMap (resReference findAllIn _.trim.stripPrefix("res")) toSet - val cmds = lines reduceLeft append split PromptString filterNot (_.trim == "") toList + val ActualPromptString = lines find matchesPrompt map (s => + if (matchesString(s, PromptString)) PromptString else AltPromptString) getOrElse PromptString + val cmds = lines reduceLeft append split ActualPromptString filterNot (_.trim == "") toList /** If it's a prompt or continuation line, strip the formatting bits and * assemble the code. Otherwise ship it off to be analyzed for res references @@ -67,10 +73,10 @@ abstract class Pasted { */ def fixResRefs(code: String, line: String) = line match { case resCreation(resName) if referenced(resName) => - code.lastIndexOf(PromptString) match { + code.lastIndexOf(ActualPromptString) match { case -1 => code case idx => - val (str1, str2) = code splitAt (idx + PromptString.length) + val (str1, str2) = code splitAt (idx + ActualPromptString.length) str2 match { case resAssign(`resName`) => code case _ => "%sval %s = { %s }".format(str1, resName, str2) @@ -79,10 +85,10 @@ abstract class Pasted { case _ => code } - def run() { + def run(): Unit = { println("// Replaying %d commands from transcript.\n" format cmds.size) cmds foreach { cmd => - print(PromptString) + print(ActualPromptString) interpret(cmd) } } diff --git a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala index 8c4faf7278..df65e9974d 100644 --- a/src/repl/scala/tools/nsc/interpreter/ReplProps.scala +++ b/src/repl/scala/tools/nsc/interpreter/ReplProps.scala @@ -6,12 +6,13 @@ package scala.tools.nsc package interpreter +import Properties.shellPromptString import scala.sys._ import Prop._ class ReplProps { private def bool(name: String) = BooleanProp.keyExists(name) - private def int(name: String) = IntProp(name) + private def int(name: String) = Prop[Int](name) // This property is used in TypeDebugging. Let's recycle it. val colorOk = bool("scala.color") @@ -21,6 +22,14 @@ class ReplProps { val trace = bool("scala.repl.trace") val power = bool("scala.repl.power") + // Handy system prop for shell prompt, or else pick it up from compiler.properties + val promptString = Prop[String]("scala.repl.prompt").option getOrElse (if (info) "%nscala %s> " else shellPromptString) + val prompt = { + import scala.io.AnsiColor.{ MAGENTA, RESET } + val p = promptString format Properties.versionNumberString + if (colorOk) s"$MAGENTA$p$RESET" else p + } + /** CSV of paged,across to enable pagination or `-x` style * columns, "across" instead of down the column. Since * pagination turns off columnar output, these flags are diff --git a/test/files/jvm/interpreter.check b/test/files/jvm/interpreter.check index d03edb638c..9e875235c7 100644 --- a/test/files/jvm/interpreter.check +++ b/test/files/jvm/interpreter.check @@ -32,7 +32,7 @@ scala> val four: anotherint = 4 four: anotherint = 4 scala> val bogus: anotherint = "hello" -<console>:8: error: type mismatch; +<console>:11: error: type mismatch; found : String("hello") required: anotherint (which expands to) Int @@ -280,13 +280,13 @@ scala> // both of the following should abort immediately: scala> def x => y => z <console>:1: error: '=' expected but '=>' found. - def x => y => z - ^ +def x => y => z + ^ scala> [1,2,3] <console>:1: error: illegal start of definition - [1,2,3] - ^ +[1,2,3] +^ scala> @@ -355,7 +355,7 @@ defined class Term scala> def f(e: Exp) = e match { // non-exhaustive warning here case _:Fact => 3 } -<console>:18: warning: match may not be exhaustive. +<console>:21: 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 ^ @@ -365,6 +365,6 @@ scala> :quit plusOne: (x: Int)Int res0: Int = 6 res0: String = after reset -<console>:8: error: not found: value plusOne - plusOne(5) // should be undefined now - ^ +<console>:11: 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 89a08d5ccb..6dbf8088c9 100644 --- a/test/files/run/constrained-types.check +++ b/test/files/run/constrained-types.check @@ -135,16 +135,16 @@ y: String = hello scala> scala> val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message -<console>:8: error: not found: value e +<console>:11: error: not found: value e val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message ^ -<console>:8: error: not found: value f +<console>:11: error: not found: value f val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message ^ -<console>:8: error: not found: value g +<console>:11: error: not found: value g val x = 3 : Int @Annot(e+f+g+h) // should have a graceful error message ^ -<console>:8: error: not found: value h +<console>:11: 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 586b2710e1..1853213555 100644 --- a/test/files/run/kind-repl-command.check +++ b/test/files/run/kind-repl-command.check @@ -21,8 +21,8 @@ scala> :k new { def empty = false } AnyRef{def empty: Boolean}'s kind is A scala> :k Nonexisting -<console>:8: error: not found: value Nonexisting - Nonexisting - ^ +<console>:11: error: not found: value Nonexisting + Nonexisting + ^ scala> :quit diff --git a/test/files/run/reify-repl-fail-gracefully.check b/test/files/run/reify-repl-fail-gracefully.check index c9e69744d6..eac4d25869 100644 --- a/test/files/run/reify-repl-fail-gracefully.check +++ b/test/files/run/reify-repl-fail-gracefully.check @@ -10,8 +10,8 @@ import scala.reflect.runtime.universe._ scala> scala> reify -<console>:12: error: too few argument lists for macro invocation - reify - ^ +<console>:15: error: too few argument lists for macro invocation + reify + ^ scala> :quit diff --git a/test/files/run/reify_newimpl_22.check b/test/files/run/reify_newimpl_22.check index 952f384a1c..24334df92c 100644 --- a/test/files/run/reify_newimpl_22.check +++ b/test/files/run/reify_newimpl_22.check @@ -17,9 +17,9 @@ scala> { } println(code.eval) } -<console>:15: free term: Ident(TermName("x")) defined by res0 in <console>:14:21 - val code = reify { - ^ +<console>:18: free term: Ident(TermName("x")) defined by res0 in <console>:17:14 + val code = reify { + ^ 2 scala> :quit diff --git a/test/files/run/reify_newimpl_23.check b/test/files/run/reify_newimpl_23.check index b7e9bfdfbc..f8379958db 100644 --- a/test/files/run/reify_newimpl_23.check +++ b/test/files/run/reify_newimpl_23.check @@ -16,7 +16,7 @@ scala> def foo[T]{ } println(code.eval) } -<console>:13: free type: Ident(TypeName("T")) defined by foo in <console>:12:16 +<console>:16: free type: Ident(TypeName("T")) defined by foo in <console>:15: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 4f36ba10ee..f9a5d7b578 100644 --- a/test/files/run/reify_newimpl_25.check +++ b/test/files/run/reify_newimpl_25.check @@ -7,9 +7,9 @@ scala> { val tt = implicitly[TypeTag[x.type]] println(tt) } -<console>:11: free term: Ident(TermName("x")) defined by res0 in <console>:10:21 - val tt = implicitly[TypeTag[x.type]] - ^ +<console>:14: free term: Ident(TermName("x")) defined by res0 in <console>:13:14 + val tt = implicitly[TypeTag[x.type]] + ^ TypeTag[x.type] scala> :quit diff --git a/test/files/run/reify_newimpl_26.check b/test/files/run/reify_newimpl_26.check index 681b862795..bd77d3d707 100644 --- a/test/files/run/reify_newimpl_26.check +++ b/test/files/run/reify_newimpl_26.check @@ -6,7 +6,7 @@ scala> def foo[T]{ val tt = implicitly[WeakTypeTag[List[T]]] println(tt) } -<console>:9: free type: Ident(TypeName("T")) defined by foo in <console>:7:16 +<console>:12: free type: Ident(TypeName("T")) defined by foo in <console>:10: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 07cf23412f..38ad7e818d 100644 --- a/test/files/run/repl-bare-expr.check +++ b/test/files/run/repl-bare-expr.check @@ -2,33 +2,33 @@ Type in expressions to have them evaluated. Type :help for more information. scala> 2 ; 3 -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 2 ;; - ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 2 ;; + ^ res0: Int = 3 scala> { 2 ; 3 } -<console>:8: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - { 2 ; 3 } - ^ +<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + { 2 ; 3 } + ^ res1: Int = 3 scala> 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { 1 + 2 + 3 } ; bippy+88+11 -<console>:7: 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 = { - ^ -<console>:7: 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 = { - ^ -<console>:7: 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 = { - ^ -<console>:7: 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 = { - ^ +<console>:10: 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 = { + ^ +<console>:10: 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 = { + ^ +<console>:10: 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 = { + ^ +<console>:10: 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 defined class Moo bippy: Int diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check index 9898027c1d..fa33af3beb 100644 --- a/test/files/run/repl-colon-type.check +++ b/test/files/run/repl-colon-type.check @@ -3,8 +3,8 @@ Type :help for more information. scala> :type List[1, 2, 3] <console>:1: error: identifier expected but integer literal found. - List[1, 2, 3] - ^ +List[1, 2, 3] + ^ scala> :type List(1, 2, 3) List[Int] diff --git a/test/files/run/repl-parens.check b/test/files/run/repl-parens.check index 74d15ff93c..756a063b68 100644 --- a/test/files/run/repl-parens.check +++ b/test/files/run/repl-parens.check @@ -20,12 +20,12 @@ scala> ( (2 + 2 ) ) res5: Int = 4 scala> 5 ; ( (2 + 2 ) ) ; ((5)) -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 5 ; ( (2 + 2 ) ) ;; - ^ -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 5 ; ( (2 + 2 ) ) ;; - ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; ( (2 + 2 ) ) ;; + ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; ( (2 + 2 ) ) ;; + ^ res6: Int = 5 scala> (((2 + 2)), ((2 + 2))) @@ -40,18 +40,18 @@ res9: String = 4423 scala> scala> 55 ; ((2 + 2)) ; (1, 2, 3) -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 55 ; ((2 + 2)) ;; - ^ -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 55 ; ((2 + 2)) ;; - ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ; ((2 + 2)) ;; + ^ +<console>:10: 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)) -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 55 ; (x: Int) => x + 1 ;; - ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ; (x: Int) => x + 1 ;; + ^ res11: () => Int = <function0> scala> @@ -60,9 +60,9 @@ scala> () => 5 res12: () => Int = <function0> scala> 55 ; () => 5 -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 55 ;; - ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ;; + ^ res13: () => Int = <function0> scala> () => { class X ; new X } diff --git a/test/files/run/repl-paste-2.check b/test/files/run/repl-paste-2.check index 6ea8e2f419..bc80615107 100644 --- a/test/files/run/repl-paste-2.check +++ b/test/files/run/repl-paste-2.check @@ -44,7 +44,7 @@ scala> res5 + res6 res1: Int = 690 scala> val x = dingus -<console>:7: error: not found: value dingus +<console>:10: 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 cd7893bbc3..a2d88fd445 100644 --- a/test/files/run/repl-reset.check +++ b/test/files/run/repl-reset.check @@ -30,23 +30,23 @@ Forgetting all expression results and named terms: $intp, BippyBungus, x1, x2, x Forgetting defined types: BippyBungus scala> x1 + x2 + x3 -<console>:8: error: not found: value x1 - x1 + x2 + x3 - ^ -<console>:8: error: not found: value x2 - x1 + x2 + x3 - ^ -<console>:8: error: not found: value x3 - x1 + x2 + x3 - ^ +<console>:11: error: not found: value x1 + x1 + x2 + x3 + ^ +<console>:11: error: not found: value x2 + x1 + x2 + x3 + ^ +<console>:11: error: not found: value x3 + x1 + x2 + x3 + ^ scala> val x1 = 4 x1: Int = 4 scala> new BippyBungus -<console>:8: error: not found: type BippyBungus - new BippyBungus - ^ +<console>:11: error: not found: type BippyBungus + new BippyBungus + ^ scala> class BippyBungus() { def f = 5 } defined class BippyBungus diff --git a/test/files/run/repl-trim-stack-trace.scala b/test/files/run/repl-trim-stack-trace.scala index a53ce3b3e4..b8c1668691 100644 --- a/test/files/run/repl-trim-stack-trace.scala +++ b/test/files/run/repl-trim-stack-trace.scala @@ -13,7 +13,7 @@ f: Nothing scala> f java.lang.Exception: Uh-oh - at .f(<console>:7) + at .f(<console>:10) ... 69 elided scala> def f = throw new Exception("") @@ -21,7 +21,7 @@ f: Nothing scala> f java.lang.Exception: - at .f(<console>:7) + at .f(<console>:10) ... 69 elided scala> def f = throw new Exception @@ -29,7 +29,7 @@ f: Nothing scala> f java.lang.Exception - at .f(<console>:7) + at .f(<console>:10) ... 69 elided scala> :quit""" diff --git a/test/files/run/t4542.check b/test/files/run/t4542.check index f7716dc2f0..f7aad3deb2 100644 --- a/test/files/run/t4542.check +++ b/test/files/run/t4542.check @@ -7,7 +7,7 @@ scala> @deprecated("foooo", "ReplTest version 1.0-FINAL") class Foo() { defined class Foo scala> val f = new Foo -<console>:8: warning: class Foo is deprecated: foooo +<console>:11: 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 db5dc19866..1b883983cf 100644 --- a/test/files/run/t4594-repl-settings.scala +++ b/test/files/run/t4594-repl-settings.scala @@ -17,7 +17,7 @@ object Test extends SessionTest { |scala> :settings -deprecation | |scala> def b = depp - |<console>:8: warning: method depp is deprecated: Please don't do that. + |<console>:11: 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 4bbc54b641..e8375c3e90 100644 --- a/test/files/run/t5655.check +++ b/test/files/run/t5655.check @@ -8,19 +8,19 @@ scala> import x._ import x._ scala> x -<console>:12: error: reference to x is ambiguous; +<console>:15: error: reference to x is ambiguous; it is imported twice in the same scope by import x._ and import x - x - ^ + x + ^ scala> x -<console>:12: error: reference to x is ambiguous; +<console>:15: error: reference to x is ambiguous; it is imported twice in the same scope by import x._ and import x - x - ^ + x + ^ scala> :quit diff --git a/test/files/run/t7319.check b/test/files/run/t7319.check index e35cfc90c0..885136b432 100644 --- a/test/files/run/t7319.check +++ b/test/files/run/t7319.check @@ -17,25 +17,25 @@ 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)) -<console>:12: error: no type parameters for method convert: (builder: F[_ <: F[_]])Int exist so that it can be applied to arguments (Some[Int]) +<console>:15: 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)) - ^ -<console>:12: error: type mismatch; + convert(Some[Int](0)) + ^ +<console>:15: error: type mismatch; found : Some[Int] required: F[_ <: F[_]] - convert(Some[Int](0)) - ^ + convert(Some[Int](0)) + ^ scala> Range(1,2).toArray: Seq[_] -<console>:11: error: polymorphic expression cannot be instantiated to expected type; +<console>:14: error: polymorphic expression cannot be instantiated to expected type; found : [B >: Int]Array[B] required: Seq[_] - Range(1,2).toArray: Seq[_] - ^ + Range(1,2).toArray: Seq[_] + ^ scala> 0 res2: Int = 0 diff --git a/test/files/run/t7582.check b/test/files/run/t7582.check index 2a11210000..0cfbf08886 100644 --- a/test/files/run/t7582.check +++ b/test/files/run/t7582.check @@ -1,6 +1 @@ -#partest !-Ybackend:GenBCode -warning: there was one inliner warning; re-run with -Yinline-warnings for details -#partest -Ybackend:GenBCode -warning: there was one inliner warning; re-run with -Yopt-warnings for details -#partest 2 diff --git a/test/files/run/t7582/InlineHolder.scala b/test/files/run/t7582/InlineHolder.scala index a18b9effaa..3cbf233ce1 100644 --- a/test/files/run/t7582/InlineHolder.scala +++ b/test/files/run/t7582/InlineHolder.scala @@ -1,3 +1,6 @@ +/* + * filter: inliner warning; re-run with + */ package p1 { object InlineHolder { @inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1 diff --git a/test/files/run/t7582b.check b/test/files/run/t7582b.check index 2a11210000..0cfbf08886 100644 --- a/test/files/run/t7582b.check +++ b/test/files/run/t7582b.check @@ -1,6 +1 @@ -#partest !-Ybackend:GenBCode -warning: there was one inliner warning; re-run with -Yinline-warnings for details -#partest -Ybackend:GenBCode -warning: there was one inliner warning; re-run with -Yopt-warnings for details -#partest 2 diff --git a/test/files/run/t7582b/InlineHolder.scala b/test/files/run/t7582b/InlineHolder.scala index a18b9effaa..3cbf233ce1 100644 --- a/test/files/run/t7582b/InlineHolder.scala +++ b/test/files/run/t7582b/InlineHolder.scala @@ -1,3 +1,6 @@ +/* + * filter: inliner warning; re-run with + */ package p1 { object InlineHolder { @inline def inlinable = p1.PackageProtectedJava.protectedMethod() + 1 diff --git a/test/files/run/t7747-repl.check b/test/files/run/t7747-repl.check index 5f436ba6b1..98e3d3b821 100644 --- a/test/files/run/t7747-repl.check +++ b/test/files/run/t7747-repl.check @@ -17,33 +17,33 @@ scala> val z = x * y z: Int = 156 scala> 2 ; 3 -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 2 ;; - ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 2 ;; + ^ res0: Int = 3 scala> { 2 ; 3 } -<console>:8: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - { 2 ; 3 } - ^ +<console>:11: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + { 2 ; 3 } + ^ res1: Int = 3 scala> 5 ; 10 ; case object Cow ; 20 ; class Moo { override def toString = "Moooooo" } ; 30 ; def bippy = { 1 + 2 + 3 } ; bippy+88+11 -<console>:7: 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 = { - ^ -<console>:7: 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 = { - ^ -<console>:7: 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 = { - ^ -<console>:7: 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 = { - ^ +<console>:10: 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 = { + ^ +<console>:10: 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 = { + ^ +<console>:10: 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 = { + ^ +<console>:10: 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 defined class Moo bippy: Int @@ -83,12 +83,12 @@ scala> ( (2 + 2 ) ) res10: Int = 4 scala> 5 ; ( (2 + 2 ) ) ; ((5)) -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 5 ; ( (2 + 2 ) ) ;; - ^ -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 5 ; ( (2 + 2 ) ) ;; - ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; ( (2 + 2 ) ) ;; + ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 5 ; ( (2 + 2 ) ) ;; + ^ res11: Int = 5 scala> (((2 + 2)), ((2 + 2))) @@ -103,18 +103,18 @@ res14: String = 4423 scala> scala> 55 ; ((2 + 2)) ; (1, 2, 3) -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 55 ; ((2 + 2)) ;; - ^ -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 55 ; ((2 + 2)) ;; - ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ; ((2 + 2)) ;; + ^ +<console>:10: 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)) -<console>:9: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 55 ; (x: Int) => x + 1 ;; - ^ +<console>:12: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ; (x: Int) => x + 1 ;; + ^ res16: () => Int = <function0> scala> @@ -123,9 +123,9 @@ scala> () => 5 res17: () => Int = <function0> scala> 55 ; () => 5 -<console>:7: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses - 55 ;; - ^ +<console>:10: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses + 55 ;; + ^ res18: () => Int = <function0> scala> () => { class X ; new X } @@ -211,23 +211,23 @@ Forgetting all expression results and named terms: $intp, BippyBungus, Bovine, C Forgetting defined types: BippyBungus, Moo, Ruminant scala> x1 + x2 + x3 -<console>:8: error: not found: value x1 - x1 + x2 + x3 - ^ -<console>:8: error: not found: value x2 - x1 + x2 + x3 - ^ -<console>:8: error: not found: value x3 - x1 + x2 + x3 - ^ +<console>:11: error: not found: value x1 + x1 + x2 + x3 + ^ +<console>:11: error: not found: value x2 + x1 + x2 + x3 + ^ +<console>:11: error: not found: value x3 + x1 + x2 + x3 + ^ scala> val x1 = 4 x1: Int = 4 scala> new BippyBungus -<console>:8: error: not found: type BippyBungus - new BippyBungus - ^ +<console>:11: error: not found: type BippyBungus + new BippyBungus + ^ scala> class BippyBungus() { def f = 5 } defined class BippyBungus diff --git a/test/files/run/t9170.scala b/test/files/run/t9170.scala index 25a0e84581..67a58d6803 100644 --- a/test/files/run/t9170.scala +++ b/test/files/run/t9170.scala @@ -10,17 +10,17 @@ object Test extends SessionTest { Type :help for more information. scala> object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 } -<console>:7: error: double definition: -def f[A](a: => A): Int at line 7 and -def f[A](a: => Either[Exception,A]): Int at line 7 +<console>: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 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 } -<console>:7: error: double definition: -def f[A](a: => A): Int at line 7 and -def f[A](a: => Either[Exception,A]): Int at line 7 +<console>: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 have same type after erasure: (a: Function0)Int object Y { def f[A](a: => A) = 1 ; def f[A](a: => Either[Exception, A]) = 2 } ^ @@ -29,9 +29,9 @@ scala> object Y { | def f[A](a: => A) = 1 | def f[A](a: => Either[Exception, A]) = 2 | } -<console>:9: error: double definition: -def f[A](a: => A): Int at line 8 and -def f[A](a: => Either[Exception,A]): Int at line 9 +<console>: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 have same type after erasure: (a: Function0)Int def f[A](a: => Either[Exception, A]) = 2 ^ @@ -46,9 +46,9 @@ object Y { // Exiting paste mode, now interpreting. -<console>:9: error: double definition: -def f[A](a: => A): Int at line 8 and -def f[A](a: => Either[Exception,A]): Int at line 9 +<console>: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 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 new file mode 100644 index 0000000000..2942d0f73e --- /dev/null +++ b/test/files/run/t9206.scala @@ -0,0 +1,39 @@ + +import scala.tools.partest.SessionTest + +object Test extends SessionTest { + //override def prompt = "XXX> " +//Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40). + def session = + s"""|Type in expressions to have them evaluated. + |Type :help for more information. + | + |scala> val i: Int = "foo" + |<console>:10: error: type mismatch; + | found : String("foo") + | required: Int + | val i: Int = "foo" + | ^ + | + |scala> { val j = 42 ; val i: Int = "foo" + j } + |<console>:11: error: type mismatch; + | found : String + | required: Int + | { val j = 42 ; val i: Int = "foo" + j } + | ^ + | + |scala> :quit""" + /* + |XXX> XXX> def f = 42 + | + |// Detected repl transcript paste: ctrl-D to finish. + | + |// Replaying 1 commands from transcript. + | + |XXX> def f = 42 + |f: Int + | + |XXX> :quit""" + */ + +} diff --git a/test/files/run/t9359.check b/test/files/run/t9359.check new file mode 100644 index 0000000000..8dcfe4f60a --- /dev/null +++ b/test/files/run/t9359.check @@ -0,0 +1,18 @@ + // access flags 0x4009 + public static enum INNERCLASS A_1$A1N A_1 A1N + + // access flags 0x4409 + public static abstract enum INNERCLASS A_1$A1N_ABSTRACT A_1 A1N_ABSTRACT + + // access flags 0x4019 + public final static enum INNERCLASS A_1$A1N_FINAL A_1 A1N_FINAL + + // access flags 0x4009 + public static enum INNERCLASS B_2$A1N B_2 A1N + + // access flags 0x4409 + public static abstract enum INNERCLASS B_2$A1N_ABSTRACT B_2 A1N_ABSTRACT + + // access flags 0x4019 + public final static enum INNERCLASS B_2$A1N_FINAL B_2 A1N_FINAL + diff --git a/test/files/run/t9359/A_1.java b/test/files/run/t9359/A_1.java new file mode 100644 index 0000000000..3ac82ed55f --- /dev/null +++ b/test/files/run/t9359/A_1.java @@ -0,0 +1,19 @@ +public class A_1 { + // nested final + public static enum A1N_FINAL { + A1N_FINAL_VAL + } + + // nested, non-final + public enum A1N { + A1N_VAL { } // value has a body, so a class extending A1N is generated + } + + // nested, non-final, abstract + public enum A1N_ABSTRACT { + A1N_ABSTRACT_VAL { + void foo() { return; } + }; + abstract void foo(); // abstract member makes the enum class abstract + } +} diff --git a/test/files/run/t9359/B_2.java b/test/files/run/t9359/B_2.java new file mode 100644 index 0000000000..d824facda9 --- /dev/null +++ b/test/files/run/t9359/B_2.java @@ -0,0 +1,19 @@ +public class B_2 { + // nested final + public enum A1N_FINAL { + A1N_FINAL_VAL + } + + // nested, non-final + public enum A1N { + A1N_VAL { } // value has a body, so a class extending A1N is generated + } + + // nested, non-final, abstract + public enum A1N_ABSTRACT { + A1N_ABSTRACT_VAL { + void foo() { return; } + }; + abstract void foo(); // abstract member makes the enum class abstract + } +} diff --git a/test/files/run/t9359/Test_2.scala b/test/files/run/t9359/Test_2.scala new file mode 100644 index 0000000000..869c51b619 --- /dev/null +++ b/test/files/run/t9359/Test_2.scala @@ -0,0 +1,28 @@ +import scala.tools.partest.BytecodeTest +import scala.tools.asm +import asm.tree.{ClassNode, InnerClassNode} +import asm.{Opcodes => Flags} +import scala.collection.JavaConverters._ + +class C { + def f1: A_1.A1N_FINAL = A_1.A1N_FINAL.A1N_FINAL_VAL + def f2: A_1.A1N = A_1.A1N.A1N_VAL + def f3: A_1.A1N_ABSTRACT = A_1.A1N_ABSTRACT.A1N_ABSTRACT_VAL + + def f4: B_2.A1N_FINAL = B_2.A1N_FINAL.A1N_FINAL_VAL + def f5: B_2.A1N = B_2.A1N.A1N_VAL + def f6: B_2.A1N_ABSTRACT = B_2.A1N_ABSTRACT.A1N_ABSTRACT_VAL +} + +object Test extends BytecodeTest { + def tost(n: InnerClassNode) = { + val t = new asm.util.Textifier + t.visitInnerClass(n.name, n.outerName, n.innerName, n.access) + t.getText.get(0); + } + def show(): Unit = { + for (n <- loadClassNode("C").innerClasses.asScala.toList.sortBy(_.name)) { + println(tost(n)) + } + } +} diff --git a/test/files/run/xMigration.check b/test/files/run/xMigration.check index 378f7bb6c3..304132a848 100644 --- a/test/files/run/xMigration.check +++ b/test/files/run/xMigration.check @@ -12,10 +12,10 @@ res1: Iterable[String] = MapLike(eis) scala> :setting -Xmigration:any scala> Map(1 -> "eis").values // warn -<console>:8: warning: method values in trait MapLike has changed semantics in version 2.8.0: +<console>:11: 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 - ^ + Map(1 -> "eis").values // warn + ^ res2: Iterable[String] = MapLike(eis) scala> :setting -Xmigration:2.8 @@ -26,10 +26,10 @@ res3: Iterable[String] = MapLike(eis) scala> :setting -Xmigration:2.7 scala> Map(1 -> "eis").values // warn -<console>:8: warning: method values in trait MapLike has changed semantics in version 2.8.0: +<console>:11: 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 - ^ + Map(1 -> "eis").values // warn + ^ res4: Iterable[String] = MapLike(eis) scala> :setting -Xmigration:2.11 @@ -40,10 +40,10 @@ res5: Iterable[String] = MapLike(eis) scala> :setting -Xmigration // same as :any scala> Map(1 -> "eis").values // warn -<console>:8: warning: method values in trait MapLike has changed semantics in version 2.8.0: +<console>:11: 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 - ^ + Map(1 -> "eis").values // warn + ^ res6: Iterable[String] = MapLike(eis) scala> :quit |