Skip to content

Commit 94982dd

Browse files
authored
Merge pull request #10288 from ShapelessCat/fix-docs
2 parents bece01e + 7e33160 commit 94982dd

File tree

3 files changed

+26
-12
lines changed

3 files changed

+26
-12
lines changed

docs/docs/reference/other-new-features/safe-initialization.md

+1-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ The checker will report:
2929

3030
``` scala
3131
-- Warning: tests/init/neg/AbstractFile.scala:7:4 ------------------------------
32-
7 | val localFile: String = url.hashCode + ".tmp" // error
32+
7 | val localFile: String = s"${url.##}.tmp" // error: usage of `localFile` before it's initialized
3333
| ^
3434
| Access non-initialized field value localFile. Calling trace:
3535
| -> val extension: String = name.substring(4) [ AbstractFile.scala:3 ]
@@ -183,7 +183,6 @@ are transitively initialized, so is the result.
183183

184184
With the established principles and design goals, following rules are imposed:
185185

186-
187186
1. In an assignment `o.x = e`, the expression `e` may only point to transitively initialized objects.
188187

189188
This is how monotonicity is enforced in the system. Note that in an

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

+24-9
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,21 @@ title: The @targetName annotation
44
---
55

66
A `@targetName` annotation on a definition defines an alternate name for the implementation of that definition. Example:
7+
78
```scala
89
import scala.annotation.targetName
910

1011
object VecOps {
1112
@targetName("append") def (xs: Vec[T]) ++= [T] (ys: Vec[T]): Vec[T] = ...
1213
}
1314
```
15+
1416
Here, the `++=` operation is implemented (in Byte code or native code) under the name `append`. The implementation name affects the code that is generated, and is the name under which code from other languages can call the method. For instance, `++=` could be invoked from Java like this:
15-
```
17+
18+
```java
1619
VecOps.append(vec1, vec2)
1720
```
21+
1822
The `@targetName` annotation has no bearing on Scala usages. Any application of that method in Scala has to use `++=`, not `append`.
1923

2024
### Details
@@ -38,58 +42,69 @@ The `@targetName` annotation has no bearing on Scala usages. Any application of
3842

3943
`@targetName` annotations are significant for matching two method definitions to decide whether they conflict or override each other. Two method definitions match if they have the same name, signature, and erased name. Here,
4044

41-
- The _signature_ of a definition consists of the names of the erased types of all (value-) parameters and the method's result type.
42-
- The _erased name_ of a method definition is its target name if a `@targetName`
43-
annotation is given and its defined name otherwise.
45+
- The _signature_ of a definition consists of the names of the erased types of all (value-) parameters and the method's result type.
46+
- The _erased name_ of a method definition is its target name if a `@targetName`
47+
annotation is given and its defined name otherwise.
4448

4549
This means that `@targetName` annotations can be used to disambiguate two method definitions that would otherwise clash. For instance.
50+
4651
```scala
4752
def f(x: => String): Int = x.length
4853
def f(x: => Int): Int = x + 1 // error: double definition
4954
```
55+
5056
The two definitions above clash since their erased parameter types are both `Function0`, which is the type of the translation of a by-name-parameter. Hence
5157
they have the same names and signatures. But we can avoid the clash by adding a `@targetName` annotation to either method or to both of them. E.g.
58+
5259
```scala
5360
@targetName("f_string")
5461
def f(x: => String): Int = x.length
5562
def f(x: => Int): Int = x + 1 // OK
5663
```
64+
5765
This will produce methods `f_string` and `f` in the generated code.
5866

5967
However, `@targetName` annotations are not allowed to break overriding relationships
6068
between two definitions that have otherwise the same names and types. So the following would be in error:
69+
6170
```scala
6271
import annotation.targetName
6372
class A:
6473
def f(): Int = 1
6574
class B extends A:
66-
targetName("g") def f(): Int = 2
75+
@targetName("g") def f(): Int = 2
6776
```
77+
6878
The compiler reports here:
79+
6980
```
7081
-- Error: test.scala:6:23 ------------------------------------------------------
7182
6 | @targetName("g") def f(): Int = 2
7283
| ^
7384
|error overriding method f in class A of type (): Int;
7485
| method f of type (): Int should not have a @targetName annotation since the overridden member hasn't one either
7586
```
87+
7688
The relevant overriding rules can be summarized as follows:
7789

78-
- Two members can override each other if their names and signatures are the same,
79-
and they either have the same erased names or the same types.
80-
- If two members override, then both their erased names and their types must be the same.
90+
- Two members can override each other if their names and signatures are the same,
91+
and they either have the same erased names or the same types.
92+
- If two members override, then both their erased names and their types must be the same.
8193

8294
As usual, any overriding relationship in the generated code must also
8395
be present in the original code. So the following example would also be in error:
96+
8497
```scala
8598
import annotation.targetName
8699
class A:
87100
def f(): Int = 1
88101
class B extends A:
89-
targetName("f") def g(): Int = 2
102+
@targetName("f") def g(): Int = 2
90103
```
104+
91105
Here, the original methods `g` and `f` do not override each other since they have
92106
different names. But once we switch to target names, there is a clash that is reported by the compiler:
107+
93108
```
94109
-- [E120] Naming Error: test.scala:4:6 -----------------------------------------
95110
4 |class B extends A:

tests/init/neg/AbstractFile.scala

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@ abstract class AbstractFile {
44
}
55

66
class RemoteFile(url: String) extends AbstractFile {
7-
val localFile: String = url.hashCode + ".tmp" // error
7+
val localFile: String = s"${url.##}.tmp" // error: usage of `localFile` before it's initialized
88
def name: String = localFile
99
}

0 commit comments

Comments
 (0)