Skip to content

Commit 04fb8f0

Browse files
committed
docs: apply snippet compiler on new types reference docs
This commit addresses a part of scala#12967. To make documents pass snippet checking, I modified some Scala code blocks while keeping original code as much as possible. Snippet check for docs raises "dotty.tools.dotc.MissingCoreLibraryException: Could not find package scala from compiler core libraries." on CI(not on my local machine), so I skip adding docs to Build.scala for now.
1 parent a9a75c1 commit 04fb8f0

9 files changed

+83
-61
lines changed

docs/_docs/reference/new-types/dependent-function-types-spec.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ methods with a dependent result type. Dependent function types desugar to
2525
refinement types of `scala.FunctionN`. A dependent function type
2626
`(x1: K1, ..., xN: KN) => R` of arity `N` translates to:
2727

28-
```scala
28+
```scala sc:nocompile
2929
FunctionN[K1, ..., Kn, R']:
3030
def apply(x1: K1, ..., xN: KN): R
3131
```

docs/_docs/reference/new-types/dependent-function-types.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ nightlyOf: https://docs.scala-lang.org/scala3/reference/new-types/dependent-func
77
A dependent function type is a function type whose result depends
88
on the function's parameters. For example:
99

10-
```scala
10+
```scala sc-name:entry
1111
trait Entry { type Key; val key: Key }
1212

1313
def extractKey(e: Entry): e.Key = e.key // a dependent method
@@ -28,7 +28,7 @@ because there was no type that could describe them.
2828

2929
In Scala 3 this is now possible. The type of the `extractor` value above is
3030

31-
```scala
31+
```scala sc:nocompile
3232
(e: Entry) => e.Key
3333
```
3434

@@ -41,9 +41,9 @@ instance of the [`Function1` trait](https://scala-lang.org/api/3.x/scala/Functio
4141
are also represented as instances of these traits, but they get an additional
4242
refinement. In fact, the dependent function type above is just syntactic sugar for
4343

44-
```scala
45-
Function1[Entry, Entry#Key]:
46-
def apply(e: Entry): e.Key
44+
```scala sc:nocompile
45+
new Function1[Entry, Entry#Key]:
46+
def apply(e: Entry): e.Key = ???
4747
```
4848

4949
[More details](./dependent-function-types-spec.md)

docs/_docs/reference/new-types/intersection-types.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ has member methods `reset` and `add`.
3434
If a member appears in both `A` and `B`, its type in `A & B` is the intersection
3535
of its type in `A` and its type in `B`. For instance, assume the definitions:
3636

37-
```scala
37+
```scala sc:nocompile
3838
trait A:
3939
def children: List[A]
4040

@@ -59,7 +59,7 @@ must make sure that all inherited members are correctly defined.
5959
So if one defines a class `C` that inherits `A` and `B`, one needs
6060
to give at that point a definition of a `children` method with the required type.
6161

62-
```scala
62+
```scala sc:nocompile
6363
class C extends A, B:
6464
def children: List[A & B] = ???
6565
```

docs/_docs/reference/new-types/match-types.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ type Elem[X] = X match
1616

1717
This defines a type that reduces as follows:
1818

19-
```scala
19+
```scala sc:nocompile
2020
Elem[String] =:= Char
2121
Elem[Array[Int]] =:= Int
2222
Elem[List[Float]] =:= Float
@@ -28,7 +28,7 @@ subtypes of each other.
2828

2929
In general, a match type is of the form
3030

31-
```scala
31+
```scala sc:nocompile
3232
S match { P1 => T1 ... Pn => Tn }
3333
```
3434

@@ -37,7 +37,7 @@ variables in patterns start with a lower case letter, as usual.
3737

3838
Match types can form part of recursive type definitions. Example:
3939

40-
```scala
40+
```scala sc-name:leafelm
4141
type LeafElem[X] = X match
4242
case String => Char
4343
case Array[t] => LeafElem[t]
@@ -47,7 +47,7 @@ type LeafElem[X] = X match
4747

4848
Recursive match type definitions can also be given an upper bound, like this:
4949

50-
```scala
50+
```scala sc
5151
type Concat[Xs <: Tuple, +Ys <: Tuple] <: Tuple = Xs match
5252
case EmptyTuple => Ys
5353
case x *: xs => x *: Concat[xs, Ys]
@@ -64,7 +64,7 @@ Match types can be used to define dependently typed methods. For instance, here
6464
is the value level counterpart to the `LeafElem` type defined above (note the
6565
use of the match type as the return type):
6666

67-
```scala
67+
```scala sc-compile-with:leafelm
6868
def leafElem[X](x: X): LeafElem[X] = x match
6969
case x: String => x.charAt(0)
7070
case x: Array[t] => leafElem(x(0))
@@ -198,14 +198,14 @@ Since reduction is linked to subtyping, we already have a cycle detection
198198
mechanism in place. As a result, the following will already give a reasonable
199199
error message:
200200

201-
```scala
201+
```scala sc:nocompile
202202
type L[X] = X match
203203
case Int => L[X]
204204

205205
def g[X]: L[X] = ???
206206
```
207207

208-
```scala
208+
```scala sc:nocompile
209209
| val x: Int = g[Int]
210210
| ^
211211
|Recursion limit exceeded.

docs/_docs/reference/new-types/polymorphic-function-types.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def foo[A](xs: List[A]): List[A] = xs.reverse
1515
val bar: [A] => List[A] => List[A]
1616
// ^^^^^^^^^^^^^^^^^^^^^^^^^
1717
// a polymorphic function type
18-
= [A] => (xs: List[A]) => foo[A](xs)
18+
= [a] => (xs: List[a]) => foo[a](xs)
1919
```
2020

2121
Scala already has _polymorphic methods_, i.e. methods which accepts type parameters.
@@ -26,7 +26,7 @@ which can be passed as parameters to other functions, or returned as results.
2626

2727
In Scala 3 this is now possible. The type of the `bar` value above is
2828

29-
```scala
29+
```scala sc:nocompile
3030
[A] => List[A] => List[A]
3131
```
3232

@@ -48,7 +48,7 @@ a data type to represent the expressions of a simple language
4848
(consisting only of variables and function applications)
4949
in a strongly-typed way:
5050

51-
```scala
51+
```scala sc-name:expr
5252
enum Expr[A]:
5353
case Var(name: String)
5454
case Apply[A, B](fun: Expr[B => A], arg: Expr[B]) extends Expr[A]
@@ -60,7 +60,8 @@ This requires the given function to be polymorphic,
6060
since each subexpression may have a different type.
6161
Here is how to implement this using polymorphic function types:
6262

63-
```scala
63+
```scala sc-compile-with:expr sc-name:mapsubexpr
64+
import Expr.*
6465
def mapSubexpressions[A](e: Expr[A])(f: [B] => Expr[B] => Expr[B]): Expr[A] =
6566
e match
6667
case Apply(fun, arg) => Apply(f(fun), f(arg))
@@ -71,7 +72,7 @@ And here is how to use this function to _wrap_ each subexpression
7172
in a given expression with a call to some `wrap` function,
7273
defined as a variable:
7374

74-
```scala
75+
```scala sc-compile-with:mapsubexpr
7576
val e0 = Apply(Var("f"), Var("a"))
7677
val e1 = mapSubexpressions(e0)(
7778
[B] => (se: Expr[B]) => Apply(Var[B => B]("wrap"), se))

docs/_docs/reference/new-types/type-lambdas-spec.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ Only the upper bound `U` can be F-bounded, i.e. `X` can appear in it.
2222
## Subtyping Rules
2323

2424
Assume two type lambdas
25-
```scala
25+
```scala sc:nocompile
2626
type TL1 = [X >: L1 <: U1] =>> R1
2727
type TL2 = [X >: L2 <: U2] =>> R2
2828
```
@@ -40,11 +40,11 @@ its eta expansion. I.e, `List = [X] =>> List[X]`. This allows type constructors
4040
## Relationship with Parameterized Type Definitions
4141

4242
A parameterized type definition
43-
```scala
43+
```scala sc:nocompile
4444
type T[X] = R
4545
```
4646
is regarded as a shorthand for an unparameterized definition with a type lambda as right-hand side:
47-
```scala
47+
```scala sc:nocompile
4848
type T = [X] =>> R
4949
```
5050
If the type definition carries `+` or `-` variance annotations,
@@ -60,15 +60,15 @@ type F2 = [A, B] =>> A => B
6060
and at the same time it is checked that the parameter `B` appears covariantly in `A => B`.
6161

6262
A parameterized abstract type
63-
```scala
63+
```scala sc:nocompile
6464
type T[X] >: L <: U
6565
```
6666
is regarded as shorthand for an unparameterized abstract type with type lambdas as bounds.
67-
```scala
67+
```scala sc:nocompile
6868
type T >: ([X] =>> L) <: ([X] =>> U)
6969
```
7070
However, if `L` is `Nothing` it is not parameterized, since `Nothing` is treated as a bottom type for all kinds. For instance,
71-
```scala
71+
```scala sc:nocompile
7272
type T[X] <: X => X
7373
```
7474
is expanded to
@@ -81,20 +81,20 @@ type T >: ([X] =>> Nothing) <: ([X] =>> X => X)
8181
```
8282

8383
The same expansions apply to type parameters. For instance,
84-
```scala
84+
```scala sc:nocompile
8585
[F[X] <: Coll[X]]
8686
```
8787
is treated as a shorthand for
88-
```scala
88+
```scala sc:nocompile
8989
[F >: Nothing <: [X] =>> Coll[X]]
9090
```
9191
Abstract types and opaque type aliases remember the variances they were created with. So the type
92-
```scala
92+
```scala sc:nocompile
9393
type F2[-A, +B]
9494
```
9595
is known to be contravariant in `A` and covariant in `B` and can be instantiated only
9696
with types that satisfy these constraints. Likewise
97-
```scala
97+
```scala sc:nocompile
9898
opaque type O[X] = List[X]
9999
```
100100
`O` is known to be invariant (and not covariant, as its right-hand side would suggest). On the other hand, a transparent alias

docs/_docs/reference/new-types/type-lambdas.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ nightlyOf: https://docs.scala-lang.org/scala3/reference/new-types/type-lambdas.h
77
A _type lambda_ lets one express a higher-kinded type directly, without
88
a type definition.
99

10-
```scala
10+
```scala sc:nocompile
1111
[X, Y] =>> Map[Y, X]
1212
```
1313

docs/_docs/reference/new-types/union-types-spec.md

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,19 @@ Syntactically, unions follow the same rules as intersections, but have a lower p
1313
`|` is also used in pattern matching to separate pattern alternatives and has
1414
lower precedence than `:` as used in typed patterns, this means that:
1515

16-
```scala
16+
```scala sc:nocompile
1717
case _: A | B => ...
1818
```
1919

2020
is still equivalent to:
2121

22-
```scala
22+
```scala sc:nocompile
2323
case (_: A) | B => ...
2424
```
2525

2626
and not to:
2727

28-
```scala
28+
```scala sc:nocompile
2929
case _: (A | B) => ...
3030
```
3131

@@ -36,14 +36,17 @@ case _: (A | B) => ...
3636
- Like `&`, `|` is commutative and associative:
3737

3838
```scala
39-
A | B =:= B | A
40-
A | (B | C) =:= (A | B) | C
39+
// A | B =:= B |A
40+
def commutative[A,B] = summon[(A|B) =:= (B|A)]
41+
// A | (B | C) =:= (A | B) | C
42+
def associative[A,B,C] = summon[(A | (B | C)) =:= ((A | B) | C)]
4143
```
4244

4345
- `&` is distributive over `|`:
4446

4547
```scala
46-
A & (B | C) =:= A & B | A & C
48+
// A & (B | C) =:= A & B | A & C
49+
def distributive[A,B,C] = summon[(A & (B | C)) =:= (A & B | A & C)]
4750
```
4851

4952
From these rules it follows that the _least upper bound_ (LUB) of a set of types
@@ -95,18 +98,19 @@ The join of `A | B` is `C[A | B] & D & X` and the visible join of `A | B` is `C[
9598

9699
We distinguish between hard and soft union types. A _hard_ union type is a union type that's explicitly
97100
written in the source. For instance, in
98-
```scala
99-
val x: Int | String = ...
101+
```scala sc-name:hardunion
102+
val x: Int | String = ???
100103
```
101104
`Int | String` would be a hard union type. A _soft_ union type is a type that arises from type checking
102105
an alternative of expressions. For instance, the type of the expression
103-
```scala
106+
```scala sc-name:softunion
104107
val x = 1
105108
val y = "abc"
106-
if cond then x else y
109+
val cond: Boolean = ???
110+
val xy = if cond then x else y
107111
```
108112
is the soft unon type `Int | String`. Similarly for match expressions. The type of
109-
```scala
113+
```scala sc-compile-with:softunion
110114
x match
111115
case 1 => x
112116
case 2 => "abc"
@@ -152,7 +156,7 @@ The members of a union type are the members of its join.
152156
The following code does not typecheck, because method `hello` is not a member of
153157
`AnyRef` which is the join of `A | B`.
154158

155-
```scala
159+
```scala sc:fail
156160
trait A { def hello: String }
157161
trait B { def hello: String }
158162

@@ -162,6 +166,9 @@ def test(x: A | B) = x.hello // error: value `hello` is not a member of A | B
162166
On the other hand, the following would be allowed
163167

164168
```scala
169+
trait D
170+
trait E
171+
165172
trait C { def hello: String }
166173
trait A extends C with D
167174
trait B extends C with E

0 commit comments

Comments
 (0)