Skip to content

Commit 189a45d

Browse files
authored
Backport "Spec: Syntax changes." to LTS (#19040)
Backports #17943 to the LTS branch. PR submitted by the release tooling. [skip ci]
2 parents 01d5112 + baf2658 commit 189a45d

16 files changed

+181
-98
lines changed

docs/_spec/01-lexical-syntax.md

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ The principle of optional braces is that any keyword that can be followed by `{`
2727

2828
The lexical analyzer inserts `indent` and `outdent` tokens that represent regions of indented code [at certain points](./other-new-features/indentation.md).
2929

30-
´\color{red}{\text{TODO SCALA3: Port soft-modifier.md and link it here.}}´
31-
3230
In the context-free productions below we use the notation `<<< ts >>>` to indicate a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent`.
3331
Analogously, the notation `:<<< ts >>>` indicates a token sequence `ts` that is either enclosed in a pair of braces `{ ts }` or that constitutes an indented region `indent ts outdent` that follows a `colon` token.
3432

@@ -121,12 +119,35 @@ type val var while with yield
121119

122120
Additionally, the following soft keywords are reserved only in some situations.
123121

124-
´\color{red}{\text{TODO SCALA3: Port soft-modifier.md and link it here.}}´
125-
126122
```
127-
as derives end extension infix inline opaque open transparent using | * + -
123+
as derives end extension infix inline opaque
124+
open transparent using
125+
| * + -
128126
```
129127

128+
A soft modifier is one of the identifiers `infix`, `inline`, `opaque`, `open` and `transparent`.
129+
130+
A soft keyword is a soft modifier, or one of `as`, `derives`, `end`, `extension`, `using`, `|`, `+`, `-`, `*`.
131+
132+
A soft modifier is treated as an actual modifier of a definition if it is followed by a hard modifier or a keyword combination starting a definition (`def`, `val`, `var`, `type`, `given`, `class`, `trait`, `object`, `enum`, `case class`, `case object`).
133+
Between the two words, there may be a sequence of newline tokens and/or other soft modifiers.
134+
135+
Otherwise, soft keywords are treated as actual keywords in the following situations:
136+
137+
- `as`, if it appears in a renaming import clause.
138+
- `derives`, if it appears after an extension clause or after the name and possibly parameters of a class, trait, object, or enum definition.
139+
- `end`, if it appears at the start of a line following a statement (i.e. definition or toplevel expression) and is followed on the same line by a single non-comment token that is:
140+
- one of the keywords `for`, `given`, `if`, `match`, `new`, `this`, `throw`, `try`, `val`, `while`, or
141+
- an identifier.
142+
- `extension`, if it appears at the start of a statement and is followed by `(` or `[`.
143+
- `inline`, if it is followed by any token that can start an expression.
144+
- `using`, if it appears at the start of a parameter or argument list.
145+
- `|`, if it separates two patterns in an alternative.
146+
- `+`, `-`, if they appear in front of a type parameter.
147+
- `*`, if it appears in a wildcard import, or if it follows the type of a parameter, or if it appears in a vararg splice `x*`.
148+
149+
Everywhere else, a soft keyword is treated as a normal identifier.
150+
130151
<!-- -->
131152

132153
> When one needs to access Java identifiers that are reserved words in Scala, use backquote-enclosed strings.
@@ -143,7 +164,7 @@ Scala is a line-oriented language where statements may be terminated by semi-col
143164
A newline in a Scala source text is treated as the special token “nl” if the three following criteria are satisfied:
144165

145166
1. The token immediately preceding the newline can terminate a statement.
146-
1. The token immediately following the newline can begin a statement.
167+
1. The token immediately following the newline can begin a statement and is not a _leading infix operator_.
147168
1. The token appears in a region where newlines are enabled.
148169

149170
The tokens that can terminate a statement are: literals, identifiers and the following delimiters and reserved words:
@@ -164,6 +185,14 @@ with yield , . ; : = => <- <: <%
164185
A `case` token can begin a statement only if followed by a
165186
`class` or `object` token.
166187

188+
A _leading infix operator_ is a symbolic identifier such as `+`, or `approx_==`, or an identifier in backticks that:
189+
190+
- starts a new line, and
191+
- is not following a blank line, and
192+
- is followed by at least one whitespace character (including new lines) and a token that can start an expression.
193+
194+
Furthermore, if the operator appears on its own line, the next line must have at least the same indentation width as the operator.
195+
167196
Newlines are enabled in:
168197

169198
1. all of a Scala source file, except for nested regions where newlines are disabled, and

docs/_spec/02-identifiers-names-and-scopes.md

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ The compiler supplies imports in a preamble to every source file.
7474
This preamble conceptually has the following form, where braces indicate nested scopes:
7575

7676
```scala
77-
import java.lang._
77+
import java.lang.*
7878
{
79-
import scala._
79+
import scala.*
8080
{
81-
import Predef._
81+
import Predef.*
8282
{ /* source */ }
8383
}
8484
}
@@ -95,8 +95,8 @@ This allows redundant type aliases to be imported without introducing an ambigui
9595
object X { type T = annotation.tailrec }
9696
object Y { type T = annotation.tailrec }
9797
object Z {
98-
import X._, Y._, annotation.{tailrec => T} // OK, all T mean tailrec
99-
@T def f: Int = { f ; 42 } // error, f is not tail recursive
98+
import X.*, Y.*, annotation.tailrec as T // OK, all T mean tailrec
99+
@T def f: Int = { f ; 42 } // error, f is not tail recursive
100100
}
101101
```
102102

@@ -107,7 +107,7 @@ Similarly, imported aliases of names introduced by package statements are allowe
107107
package p { class C }
108108

109109
// xy.scala
110-
import p._
110+
import p.*
111111
package p { class X extends C }
112112
package q { class Y extends C }
113113
```
@@ -132,27 +132,32 @@ package q {
132132
The following program illustrates different kinds of bindings and precedences between them.
133133

134134
```scala
135-
package p { // `X' bound by package clause
136-
import Console._ // `println' bound by wildcard import
137-
object Y {
138-
println(s"L4: $X") // `X' refers to `p.X' here
139-
locally {
140-
import q._ // `X' bound by wildcard import
141-
println(s"L7: $X") // `X' refers to `q.X' here
142-
import X._ // `x' and `y' bound by wildcard import
143-
println(s"L9: $x") // `x' refers to `q.X.x' here
135+
package p { // `X' bound by package clause
136+
import Console.* // `println' bound by wildcard import
137+
object Y {
138+
println(s"L4: $X") // `X' refers to `p.X' here
144139
locally {
145-
val x = 3 // `x' bound by local definition
146-
println(s"L12: $x") // `x' refers to constant `3' here
140+
import q.* // `X' bound by wildcard import
141+
println(s"L7: $X") // `X' refers to `q.X' here
142+
import X.* // `x' and `y' bound by wildcard import
143+
println(s"L9: $x") // `x' refers to `q.X.x' here
147144
locally {
148-
import q.X._ // `x' and `y' bound by wildcard import
149-
// println(s"L15: $x") // reference to `x' is ambiguous here
150-
import X.y // `y' bound by explicit import
151-
println(s"L17: $y") // `y' refers to `q.X.y' here
145+
val x = 3 // `x' bound by local definition
146+
println(s"L12: $x") // `x' refers to constant `3' here
152147
locally {
153-
val x = "abc" // `x' bound by local definition
154-
import p.X._ // `x' and `y' bound by wildcard import
155-
// println(s"L21: $y") // reference to `y' is ambiguous here
156-
println(s"L22: $x") // `x' refers to string "abc" here
157-
}}}}}}
148+
import q.X.* // `x' and `y' bound by wildcard import
149+
// println(s"L15: $x") // reference to `x' is ambiguous here
150+
import X.y // `y' bound by explicit import
151+
println(s"L17: $y") // `y' refers to `q.X.y' here
152+
locally {
153+
val x = "abc" // `x' bound by local definition
154+
import p.X.* // `x' and `y' bound by wildcard import
155+
// println(s"L21: $y") // reference to `y' is ambiguous here
156+
println(s"L22: $x") // `x' refers to string "abc" here
157+
}
158+
}
159+
}
160+
}
161+
}
162+
}
158163
```

docs/_spec/03-types.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ Type operators ending in a colon ‘:’ are right-associative; all other operat
172172
In a sequence of consecutive type infix operations ´t_0 \, \mathit{op} \, t_1 \, \mathit{op_2} \, ... \, \mathit{op_n} \, t_n´, all operators ´\mathit{op}\_1, ..., \mathit{op}\_n´ must have the same associativity.
173173
If they are all left-associative, the sequence is interpreted as ´(... (t_0 \mathit{op_1} t_1) \mathit{op_2} ...) \mathit{op_n} t_n´, otherwise it is interpreted as ´t_0 \mathit{op_1} (t_1 \mathit{op_2} ( ... \mathit{op_n} t_n) ...)´.
174174

175+
Under `-source:future`, if the type name is alphanumeric and the target type is not marked [`infix`](./05-classes-and-objects.html#infix), a deprecation warning is emitted.
176+
175177
The type operators `|` and `&` are not really special.
176178
Nevertheless, unless shadowed, they resolve to [the fundamental type aliases `scala.|` and `scala.&`](./12-the-scala-standard-library.html#fundamental-type-aliases), which represent [union and intersection types](#union-and-intersection-types), respectively.
177179

@@ -493,6 +495,9 @@ All parameterized class types are value types.
493495
In the concrete syntax of wildcard type arguments, if both bounds are omitted, the real bounds are inferred from the bounds of the corresponding type parameter in the target type constructor (which must be concrete).
494496
If only one bound is omitted, `Nothing` or `Any` is used, as usual.
495497

498+
Also in the concrete syntax, `_` can be used instead of `?` for compatibility reasons, with the same meaning.
499+
This alternative will be deprecated in the future, and is already deprecated under `-source:future`.
500+
496501
#### Simplification Rules
497502

498503
Wildcard type arguments used in covariant or contravariant positions can always be simplified to regular types.

docs/_spec/04-basic-declarations-and-definitions.md

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ A variable definition `var ´p´ = ´e´` where ´p´ is a pattern other than a
164164

165165
The name of any declared or defined variable may not end in `_=`.
166166

167-
A variable definition `var ´x´: ´T´ = _` can appear only as a member of a template.
167+
The right-hand-side of a mutable variable definition that is a member of a template can be the special reference `scala.compiletime.uninitialized`: `var ´x´: ´T´ = scala.compiletime.uninitialized`.
168168
It introduces a mutable field with type ´T´ and a default initial value.
169169
The default value depends on the type ´T´ as follows:
170170

@@ -178,6 +178,9 @@ The default value depends on the type ´T´ as follows:
178178
|`()` | `Unit` |
179179
|`null` | all other types |
180180

181+
`scala.compiletime.uninitialized` can never appear anywhere else.
182+
For compatibility with Scala 2, the syntax `var ´x´: ´T´ = _` is accepted as equivalent to using `uninitialized`.
183+
181184
When they occur as members of a template, both forms of variable definition also introduce a getter method ´x´ which returns the value currently assigned to the variable, as well as a setter method `´x´_=` which changes the value currently assigned to the variable.
182185
The methods have the same signatures as for a variable declaration.
183186
The template then has these getter and setter methods as members, whereas the original variable cannot be accessed directly as a template member.
@@ -572,6 +575,9 @@ The scope of a type parameter includes the whole signature, including any of the
572575

573576
A _value parameter clause_ ´\mathit{ps}´ consists of zero or more formal parameter bindings such as `´x´: ´T´` or `´x: T = e´`, which bind value parameters and associate them with their types.
574577

578+
A unary operator must not have explicit parameter lists even if they are empty.
579+
A unary operator is a method named `"unary_´op´"` where ´op´ is one of `+`, `-`, `!`, or `~`.
580+
575581
### Default Arguments
576582

577583
Each value parameter declaration may optionally define a default argument.
@@ -729,64 +735,86 @@ completely. It is an error if the types of two alternatives ´T_i´ and
729735

730736
## Import Clauses
731737

732-
```ebnf
733-
Import ::= ‘import’ ImportExpr {‘,’ ImportExpr}
734-
ImportExpr ::= StableId ‘.’ (id | ‘_’ | ImportSelectors)
735-
ImportSelectors ::= ‘{’ {ImportSelector ‘,’}
736-
(ImportSelector | ‘_’) ‘}’
737-
ImportSelector ::= id [‘=>’ id |=>’ ‘_’]
738738
```
739+
Import ::= ‘import’ ImportExpr {‘,’ ImportExpr}
740+
ImportExpr ::= SimpleRef {‘.’ id} ‘.’ ImportSpecifier
741+
| SimpleRef `as` id
742+
ImportSpecifier ::= NamedSelector
743+
| WildcardSelector
744+
| ‘{’ ImportSelectors ‘}’
745+
NamedSelector ::= id [(‘as’ |=>’) (id | ‘_’)]
746+
WildcardSelector ::=*| ’_’ |given’ [InfixType]
747+
ImportSelectors ::= NamedSelector [‘,’ ImportSelectors]
748+
| WildCardSelector {‘,’ WildcardSelector}
749+
```
750+
751+
- In a `NamedSelector`, `=>` can only be used when inside an `ImportSelectors` and is then equivalent to `as`, to be deprecated in the future.
752+
- In a `WildcardSelector`, `_` is equivalent to `*`, to be deprecated in the future.
753+
754+
An `ImportSpecifier` that is a single `NamedSelector` or `WildcardSelector` is equivalent to an `‘{‘ ImportSelectors ‘}‘` list with that single selector.
755+
756+
An import clause with multiple import expressions `import ´p_1´.´I_1, ..., p_n´.´I_n´` is interpreted as a sequence of import clauses `import ´p_1´.´I_1´; ...; import ´p_n´.´I_n´`.
739757

740-
An import clause has the form `import ´p´.´I´` where ´p´ is a [stable identifier](03-types.html#paths) and ´I´ is an import expression.
741-
The import expression determines a set of names of importable members of ´p´ which are made available without qualification.
758+
An import clause with a single import expression has the form `import ´p´.´I´` where ´p´ is a [prefix](03-types.html#designator-types) and ´I´ is an import specifier.
759+
The import specifier determines a set of names of importable members of ´p´ which are made available without qualification as well as a set of importable `given` members which are made available in the implicit scope.
742760
A member ´m´ of ´p´ is _importable_ if it is [accessible](05-classes-and-objects.html#modifiers).
743-
The most general form of an import expression is a list of _import selectors_
761+
The most general form of an import specifier is a list of _import selectors_
744762

745763
```scala
746-
{ ´x_1´ => ´y_1, ..., x_n´ => ´y_n´, _ }
764+
{ ´x_1´ as ´y_1, ..., x_n´ as ´y_n´, *, given ´T_1´, ..., given ´T_m´, given }
747765
```
748766

749-
for ´n \geq 0´, where the final wildcard `‘_’` may be absent.
750-
It makes available each importable member `´p´.´x_i´` under the unqualified name ´y_i´. I.e. every import selector `´x_i´ => ´y_i´` renames `´p´.´x_i´` to
751-
´y_i´.
752-
If a final wildcard is present, all importable members ´z´ of ´p´ other than `´x_1, ..., x_n,y_1, ..., y_n´` are also made available under their own unqualified names.
767+
for ´n \geq 0´ and ´m \geq 0´, where the wildcards `‘*’` and `’given’` may be absent.
768+
They are decomposed into non-given selectors and given selectors.
769+
770+
### Non-given Imports
753771

754-
Import selectors work in the same way for type and term members.
755-
For instance, an import clause `import ´p´.{´x´ => ´y\,´}` renames the term
756-
name `´p´.´x´` to the term name ´y´ and the type name `´p´.´x´` to the type name ´y´.
772+
Non-given selectors make available each importable member `´p´.´x_i´` under the unqualified name ´y_i´.
773+
In other words, every import selector `´x_i´ as ´y_i´` renames `´p´.´x_i´` to ´y_i´.
774+
When `as ´y_i´` is omitted, ´y_i´ is assumed to be ´x_i´.
775+
If a final wildcard `‘*’` is present, all non-`given` importable members ´z´ of ´p´ other than `´x_1, ..., x_n, y_1, ..., y_n´` are also made available under their own unqualified names.
776+
777+
Non-given import selectors work in the same way for type and term members.
778+
For instance, an import clause `import ´p´.´x´ as ´y´` renames the term name `´p´.´x´` to the term name ´y´ and the type name `´p´.´x´` to the type name ´y´.
757779
At least one of these two names must reference an importable member of ´p´.
758780

759-
If the target in an import selector is a wildcard, the import selector hides access to the source member.
760-
For instance, the import selector `´x´ => _`renames” ´x´ to the wildcard symbol (which is unaccessible as a name in user programs), and thereby effectively prevents unqualified access to ´x´.
781+
If the target in an import selector is an underscore `as _`, the import selector hides access to the source member instead of importing it.
782+
For instance, the import selector `´x´ as _`renames” ´x´ to the underscore symbol (which is not accessible as a name in user programs), and thereby effectively prevents unqualified access to ´x´.
761783
This is useful if there is a final wildcard in the same import selector list, which imports all members not mentioned in previous import selectors.
762784

763-
The scope of a binding introduced by an import-clause starts immediately after the import clause and extends to the end of the enclosing block, template, package clause, or compilation unit, whichever comes first.
785+
The scope of a binding introduced by a non-given import clause starts immediately after the import clause and extends to the end of the enclosing block, template, package clause, or compilation unit, whichever comes first.
764786

765-
Several shorthands exist. An import selector may be just a simple name ´x´.
766-
In this case, ´x´ is imported without renaming, so the import selector is equivalent to `´x´ => ´x´`.
767-
Furthermore, it is possible to replace the whole import selector list by a single identifier or wildcard.
768-
The import clause `import ´p´.´x´` is equivalent to `import ´p´.{´x\,´}`, i.e. it makes available without qualification the member ´x´ of ´p´. The import clause `import ´p´._` is equivalent to `import ´p´.{_}`, i.e. it makes available without qualification all members of ´p´ (this is analogous to `import ´p´.*` in Java).
787+
### Given Imports
769788

770-
An import clause with multiple import expressions `import ´p_1´.´I_1, ..., p_n´.´I_n´` is interpreted as a sequence of import clauses `import ´p_1´.´I_1´; ...; import ´p_n´.´I_n´`.
789+
Given selectors make available in the implicit scope all the importable `given` and `implicit` members `´p´.´x´` such that `´p.x´` is a subtype of ´T_i´.
790+
A bare `given` selector without type is equivalent to `given scala.Any`.
791+
792+
The names of the given members are irrelevant for the selection, and are not made available in the normal scope of unqualified names.
771793

772794
###### Example
773795
Consider the object definition:
774796

775797
```scala
776798
object M {
777-
def z = 0, one = 1
799+
def z = 0
800+
def one = 1
778801
def add(x: Int, y: Int): Int = x + y
779802
}
780803
```
781804

782805
Then the block
783806

784807
```scala
785-
{ import M.{one, z => zero, _}; add(zero, one) }
808+
{
809+
import M.{one, z as zero, *}
810+
add(zero, one)
811+
}
786812
```
787813

788814
is equivalent to the block
789815

790816
```scala
791-
{ M.add(M.z, M.one) }
817+
{
818+
M.add(M.z, M.one)
819+
}
792820
```

0 commit comments

Comments
 (0)