Skip to content

Commit 086979f

Browse files
committed
Update docs to reflect new role of with
1 parent 6f2073d commit 086979f

File tree

2 files changed

+88
-40
lines changed

2 files changed

+88
-40
lines changed

docs/docs/reference/other-new-features/control-syntax-new.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ The rules in detail are:
3636
- The enumerators of a `for`-expression can be written without enclosing parentheses or braces if they are followed by a `yield` or `do`.
3737
- A `do` in a `for`-expression expresses a `for`-loop.
3838

39-
4039
### Rewrites
4140

4241
The Dotty compiler can rewrite source code from old syntax and new syntax and back.

docs/docs/reference/other-new-features/indentation-new.md

Lines changed: 88 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ layout: doc-page
33
title: Optional Braces
44
---
55

6-
As an experimental feature, Scala 3 treats indentation as significant and allows
6+
As an experimental feature, Scala 3 enforces some rules on indentation and allows
77
some occurrences of braces `{...}` to be optional.
88

99
- First, some badly indented programs are ruled out, which means they are flagged with warnings.
@@ -12,7 +12,7 @@ some occurrences of braces `{...}` to be optional.
1212

1313
### Indentation Rules
1414

15-
The compiler enforces three rules for well-indented programs, flagging violations as warnings.
15+
The compiler enforces two rules for well-indented programs, flagging violations as warnings.
1616

1717
1. In a brace-delimited region, no statement is allowed to start to the left
1818
of the first statement after the opening brace that starts a new line.
@@ -35,14 +35,6 @@ The compiler enforces three rules for well-indented programs, flagging violation
3535
println(2) // error: missing `{`
3636
```
3737

38-
3. If significant indentation is turned off, code that follows a class or object definition (or similar) lacking a `{...}` body may not be indented more than that definition. This prevents misleading situations like:
39-
40-
```scala
41-
trait A
42-
case class B() extends A // error: indented too far to the right
43-
```
44-
It requires that the case class `C` to be written instead at the same level of indentation as the trait `A`.
45-
4638
These rules still leave a lot of leeway how programs should be indented. For instance, they do not impose
4739
any restrictions on indentation within expressions, nor do they require that all statements of an indentation block line up exactly.
4840

@@ -66,11 +58,10 @@ There are two rules:
6658
An indentation region can start
6759

6860
- after the condition of an `if-else`, or
69-
- at points where a set of definitions enclosed in braces is expected in a
70-
class, object, given, or enum definition, in an enum case, or after a package clause, or
61+
- after the leading parameter(s) of a given extension method clause, or
7162
- after one of the following tokens:
7263
```
73-
= => <- if then else while do try catch finally for yield match
64+
= => <- if then else while do try catch finally for yield match return with
7465
```
7566
If an `<indent>` is inserted, the indentation width of the token on the next line
7667
is pushed onto `IW`, which makes it the new current indentation width.
@@ -97,6 +88,66 @@ if x < 0
9788
Indentation tokens are only inserted in regions where newline statement separators are also inferred:
9889
at the toplevel, inside braces `{...}`, but not inside parentheses `(...)`, patterns or types.
9990

91+
### New Role of With
92+
93+
To make bracews optional for constructs like class bodies, the syntax of the language is changed so that a class body or similar construct may optionally be prefixed with `with`. Since `with` can start an indentation region, this means that all of the following syntaxes are allowed and are equivalent:
94+
```scala
95+
trait A {
96+
def f: Any
97+
}
98+
class C(x: Int) extends A {
99+
def f = x
100+
}
101+
type T = A {
102+
def f: Int
103+
}
104+
```
105+
---
106+
```scala
107+
trait A with {
108+
def f: Int
109+
}
110+
class C(x: Int) extends A with {
111+
def f = x
112+
}
113+
type T = A with {
114+
def f: Int
115+
}
116+
```
117+
---
118+
```scala
119+
trait A with
120+
def f: Int
121+
122+
class C(x: Int) extends A with
123+
def f = x
124+
125+
type T = A with
126+
def f: Int
127+
```
128+
129+
The syntax changes allowing this are as follows:
130+
```
131+
TemplateBody ::= [‘with’] ‘{’ [SelfType] TemplateStat {semi TemplateStat} ‘}’
132+
EnumBody ::= [‘with’] ‘{’ [SelfType] EnumStat {semi EnumStat} ‘}’
133+
Packaging ::= ‘package’ QualId [‘with’] ‘{’ TopStatSeq ‘}’
134+
RefinedType ::= AnnotType {[‘with’] Refinement}
135+
```
136+
It is assumed here that braces following a `with` can be transparently replaced by an
137+
indentation region.
138+
139+
With the new indentation rules, the previously allowed syntax
140+
```
141+
class A extends B with
142+
C
143+
```
144+
becomes illegal since `C` above would be terated as a nested statement inside `A`. More generally, a `with` that separates parent constructors cannot be at the end of a line. One has to write
145+
```
146+
class A extends B
147+
with C
148+
```
149+
instead (or replace the "`with`" by a "`,`"). When compiling in Scala-2 mode, a migration warning is issued for the illegal syntax and a (manual) rewrite is suggested.
150+
100151
### Spaces vs Tabs
101152

102153
Indentation prefixes can consist of spaces and/or tabs. Indentation widths are the indentation prefixes themselves, ordered by the string prefix relation. So, so for instance "2 tabs, followed by 4 spaces" is strictly less than "2 tabs, followed by 5 spaces", but "2 tabs, followed by 4 spaces" is incomparable to "6 tabs" or to "4 spaces, followed by 2 tabs". It is an error if the indentation width of some line is incomparable with the indentation width of the region that's current at that point. To avoid such errors, it is a good idea not to mix spaces and tabs in the same source file.
@@ -165,46 +216,44 @@ It is recommended that `end` markers are used for code where the extent of an in
165216
Here is a (somewhat meta-circular) example of code using indentation. It provides a concrete representation of indentation widths as defined above together with efficient operations for constructing and comparing indentation widths.
166217

167218
```scala
168-
enum IndentWidth
219+
enum IndentWidth with
169220
case Run(ch: Char, n: Int)
170221
case Conc(l: IndentWidth, r: Run)
171222

172-
def <= (that: IndentWidth): Boolean =
173-
this match
174-
case Run(ch1, n1) =>
175-
that match
176-
case Run(ch2, n2) => n1 <= n2 && (ch1 == ch2 || n1 == 0)
177-
case Conc(l, r) => this <= l
178-
case Conc(l1, r1) =>
179-
that match
180-
case Conc(l2, r2) => l1 == l2 && r1 <= r2
181-
case _ => false
223+
def <= (that: IndentWidth): Boolean = this match
224+
case Run(ch1, n1) =>
225+
that match
226+
case Run(ch2, n2) => n1 <= n2 && (ch1 == ch2 || n1 == 0)
227+
case Conc(l, r) => this <= l
228+
case Conc(l1, r1) =>
229+
that match
230+
case Conc(l2, r2) => l1 == l2 && r1 <= r2
231+
case _ => false
182232

183233
def < (that: IndentWidth): Boolean =
184234
this <= that && !(that <= this)
185235

186-
override def toString: String =
187-
this match
188-
case Run(ch, n) =>
189-
val kind = ch match
190-
case ' ' => "space"
191-
case '\t' => "tab"
192-
case _ => s"'$ch'-character"
193-
val suffix = if n == 1 then "" else "s"
194-
s"$n $kind$suffix"
195-
case Conc(l, r) =>
196-
s"$l, $r"
197-
198-
object IndentWidth
236+
override def toString: String = this match
237+
case Run(ch, n) =>
238+
val kind = ch match
239+
case ' ' => "space"
240+
case '\t' => "tab"
241+
case _ => s"'$ch'-character"
242+
val suffix = if n == 1 then "" else "s"
243+
s"$n $kind$suffix"
244+
case Conc(l, r) =>
245+
s"$l, $r"
246+
247+
object IndentWidth with
199248
private inline val MaxCached = 40
200249

201250
private val spaces = IArray.tabulate(MaxCached + 1)(new Run(' ', _))
202251
private val tabs = IArray.tabulate(MaxCached + 1)(new Run('\t', _))
203252

204253
def Run(ch: Char, n: Int): Run =
205-
if n <= MaxCached && ch == ' '
254+
if n <= MaxCached && ch == ' ' then
206255
spaces(n)
207-
else if n <= MaxCached && ch == '\t'
256+
else if n <= MaxCached && ch == '\t' then
208257
tabs(n)
209258
else
210259
new Run(ch, n)

0 commit comments

Comments
 (0)