8000 implement suggestions · rysh/docs.scala-lang@459b5df · GitHub
[go: up one dir, main page]

10000
Skip to content

Commit 459b5df

Browse files
committed
implement suggestions
1 parent b9dd82b commit 459b5df

File tree

8 files changed

+103
-57
lines changed

8 files changed

+103
-57
lines changed

_overviews/scala3-contribution/arch-lifecycle.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,14 @@ every compilation unit before progressing to the next phase.
2626

2727
#### Phases
2828
A phase is an abstract transformation over a compilation unit, it is usually responsible
29-
for transforming the trees and types representing the code of a source file. The primary phases of
30-
the compiler are the `parser`, which converts text that matches Scala's
31-
[syntax][10] into abstract syntax trees, ASTs, and the `typer`, which checks that
32-
trees conform to expected types, and performs other operations such as implicit search.
29+
for transforming the trees and types representing the code of a source file. Some phases of
30+
the compiler include
31+
- `parser`, which converts text that matches Scala's
32+
[syntax][10] into abstract syntax trees, ASTs
33+
- `typer`, which checks that trees conform to expected types
34+
- `erasure`, which retypes a more simplified program into one that has the same types as the JVM.
35+
- `genBCode`, the JVM backend, which converts erased compiler trees into Java bytecode format.
36+
3337
[You can read more about phases here][9].
3438

3539
#### Drivers

_overviews/scala3-contribution/arch-phases.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,9 @@ such as `equals` and `hashCode` for case classes.
6161
These phases start with [pickler], which serializes typed trees
6262
produced by the `frontendPhases` into TASTy format. Following is [inlining],
6363
which expand calls to inline methods, and [postInlining] providing implementations
64-
of the Mirror framework for inlined calls.
64+
of the [Mirror] framework for inlined calls.
6565
Finally are [staging], which ensures that quotes conform to the
66-
Phase Consistency Principle (PCP), and [pickleQuotes] which converts quoted
66+
[Phase Consistency Principle (PCP)][PCP], and [pickleQuotes] which converts quoted
6767
trees to embedded TASTy strings.
6868

6969
### `transformPhases`
@@ -105,3 +105,5 @@ These map the transformed trees to Java classfiles or SJSIR files.
105105
[initChecker]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/init/Checker.scala
106106
[firstTransform]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/FirstTransform.scala
107107
[erasure]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/Erasure.scala
108+
[Mirror]: https://github.com/lampepfl/dotty/blob/master/library/src/scala/deriving/Mirror.scala
109+
[PCP]: {% link _scala3-reference/metaprogramming/macros.md %}#the-phase-consistency-principle

_overviews/scala3-contribution/procedures-areas.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,9 @@ Look in [RefinedPrinter] (or its parent class [PlainPrinter]) for the implementa
2020

2121
### Content of Error Messages
2222

23-
You can find most error messages defined in [messages] (with IDs defined in [ErrorMessageID]). If the message
24-
is not defined there, try the `-Ydebug-error` compiler flag, which will print a stack trace leading to the
23+
You can find the definitions of most error messages in [messages] (with IDs
24+
defined in [ErrorMessageID]). If the message is not defined there, try the
25+
`-Ydebug-error` compiler flag, which will print a stack trace leading to the
2526
production of the error, and the contents of the message.
2627

2728
### Compiler Generated Given Instances

_overviews/scala3-contribution/procedures-checklist.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ Make sure you have signed the [Scala CLA][cla], if not, sign it.
1919

2020
Before starting to work on a feature or a fix, it's good practice to ensure that:
2121
1. There is a ticket for your work in the project's [issue tracker][issues];
22-
2. The ticket has been discussed and prioritized by the team.
22+
2. The ticket has been discussed and there is desire for it to be implemented by the
23+
Scala 3 core maintainers.
2324

2425
### 3: Add Tests
2526
Add at least one test that replicates the problem in the issue, and that shows it is now resolved.

_overviews/scala3-contribution/procedures-inspection.md

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Often, it is sufficient to use `println`.
1818
When printing a variable, it's always a good idea to call `show` on that variable: `println(x.show)`.
1919
Many objects of the compiler define `show`, returning a human-readable string.
2020
e.g. if called on a tree, the output will be the tree's representation as source code, rather than
21-
the raw data underlying.
21+
the underlying raw data.
2222

2323
Sometimes you need to print flags. Flags are metadata attached to [symbols] containing information such as whether a
2424
class is abstract, comes from Java, what modifiers a variable has (private, protected etc) and so on.
@@ -49,19 +49,18 @@ Here is a table of explanations for their use:
4949

5050
## Obtaining debug output from the compiler
5151

52-
There are many compiler options that provide verbose debug output when compiling a file.
53-
You can find the full list in [ScalaSettings.scala] file. A particularly useful one
54-
is `-Xprint:<phase-name>` or `-Xprint:all`. It prints trees after a given phase or after
55-
all phases. As described in the [compiler lifecycle][3] each phase transforms the trees
56-
and types that represent your code in a certain way. This flag allows you to see exactly how.
52+
As explained in [navigation], we can debug the code being generated as it is transformed
53+
through the compiler. As well as plain tree output, there are many compiler options that
54+
add extra debug information to trees when compiling a file; you can find the full list
55+
in [ScalaSettings].
5756

5857
## Stopping the compiler early
5958
Sometimes you may want to stop the compiler after a certain phase, for example to prevent
6059
knock-on errors from occurring from a bug in an earlier phase. Use the flag
6160
`-Ystop-after:<phase-name>` to prevent any phases executing afterwards.
6261

6362
> e.g. `-Xprint:<phase>` where `phase` is a miniphase, will print after
64-
> the whole phase group is complete, which may several miniphases after `phase`.
63+
> the whole phase group is complete, which may be several miniphases after `phase`.
6564
> Instead you can use `-Ystop-after:<phase> -Xprint:<phase>` to stop
6665
> immediately after the miniphase and see the trees that you intended.
6766
@@ -97,7 +96,7 @@ Names:
9796
```
9897
and so on.
9998

100-
## Inspecting representation of types
99+
## Inspecting The Representation of Types
101100

102101
> [click here][2] to learn more about types in `dotc`.
103102
@@ -142,15 +141,15 @@ sbt:scala3> scala3-compiler/Test/runMain
142141
TypeRef(TypeRef(ThisType(TypeRef(NoPrefix,module class <empty>)),class Box),type X) [class dotty.tools.dotc.core.Types$CachedTypeRef]
143142
```
144143

145-
Here are some other examples you can follow:
144+
Here are some other examples you can try:
146145
- `...printTypes "" "class" "[T] extends Seq[T] {}"`
147146
- `...printTypes "" "method" "(x: Int): x.type"`
148147
- `...printTypes "" "type" "<: Int" "= [T] =>> List[T]"`
149148

150149
### Don't just print: extracting further information
151150

152-
`dotty.tools.printTypes` is useful to to at a glance see the representation
153-
of a type, but sometimes you want to extract more. Instead, you can use the
151+
`dotty.tools.printTypes` is useful to to see the representation
152+
of a type at a glance, but sometimes you want to extract more. Instead, you can use the
154153
method `dotty.tools.DottyTypeStealer.stealType`. With the same inputs as `printTypes`,
155154
it returns both a `Context` containing the definitions passed, along with the list of types.
156155

@@ -182,6 +181,7 @@ class StealBox:
182181
[1]: https://github.com/lampepfl/dotty/blob/master/compiler/test/dotty/tools/DottyTypeStealer.scala
183182
[2]: {% link _overviews/scala3-contribution/arch-types.md %}
184183
[3]: {% link _overviews/scala3-contribution/arch-lifecycle.md %}#phases
185-
[ScalaSettings.scala]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
184+
[ScalaSettings]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
186185
[symbols]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/SymDenotations.scala
187186
[reproduce]: {% link _overviews/scala3-contribution/procedures-reproduce.md %}#dotty-issue-workspace
187+
[navigation]: {% link _overviews/scala3-contribution/procedures-navigation.md %}#what-phase-generated-a-particular-tree

_overviews/scala3-contribution/procedures-navigation.md

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,45 @@ next-page: procedures-areas
99

1010
In this section, you will be able to answer questions such as:
1111
- where does an error happen in a codebase?
12+
- when during compilation was a particular tree introduced?
1213
- where is a particular object created?
1314
- where is a particular value assigned to a variable?
1415

1516
> You may be able to quickly find the source responsible for an issue by consulting [common issue locations][areas]
1617
18+
## What phase generated a particular tree?
19+
20+
As described in the [compiler lifecycle][lifecycle], each phase transforms the trees
21+
and types that represent your code in a certain way.
22+
23+
To print the code as it is transformed through the compiler, use the compiler flag `-Xprint:all`.
24+
After each phase group is completed, you will see the resulting trees representing the code.
25+
26+
> It is recommended to test `-Xprint:all` on a single, small file, otherwise a lot of unnecessary
27+
> output will be generated.
28+
29+
### Trace a Tree Creation Site
30+
31+
When you see a problematic tree appear after a certain phase group, you know to isolate the rest of
32+
your search to the code of that phase. For example if you found a problematic tree after phase
33+
`posttyper`, the problem most likely appears in the code of [PostTyper]. We can trace the exact point
34+
the tree was generated by looking for its unique ID, and then generating a stack trace at its creation:
35+
36+
1. Run the compiler with `-Xprint:posttyper` and `-Yshow-tree-ids` flags.
37+
This will only print the trees of the `posttyper` phase. This time you should see the tree
38+
in question be printed alongside its ID. You'll see something like `println#223("Hello World"#37)`.
39+
2. Copy the ID of the desired tree.
40+
3. Run the compiler with `-Ydebug-tree-with-id <tree-id>` flag. The compiler will print a stack trace
41+
pointing to the creation site of the tree with the provided ID.
42+
43+
### Enhanced Tree Printing
44+
45+
As seen above `-Xprint:<phase>` can be enhanced with further configuration flags, found in
46+
[ScalaSettings]. For example, you can additionally print the type of a tree with `-Xprint-types`.
47+
1748
## Increasing Logging Output
18-
Sometimes you can detect erroneous states that produce an error by analysing logging output that is not
19-
normally visible:
49+
Once you have identified the phase that generated a certain tree, you can then increase
50+
logging in that phase, to try and detect erroneous states:
2051

2152
- general logging within a phase can be enabled with the `-Ylog` compiler flag, such as
2253
- `-Ylog:<phase1>,<phase2>,...` for individual phases
@@ -27,28 +58,35 @@ normally visible:
2758

2859
## Navigating to Where an Error is Generated
2960

30-
Add the `-Ydebug-error` compiler flag, e.g. `scala3/scalac -Ydebug-error Test.scala`.
61+
The compiler issues user facing errors for code that is not valid, such as the type mismatch
62+
of assigning an `Int` to a `Boolean` value. Sometimes these errors do not match what is expected, which could be a bug.
63+
64+
To discover why such a *spurious* error is generated, you can trace the code that generated the error by
65+
adding the `-Ydebug-error` compiler flag, e.g. `scala3/scalac -Ydebug-error Test.scala`.
3166
This flag forces a stack trace to be printed each time an error happens, from the site where it occurred.
3267

3368
Analysing the trace will give you a clue about the objects involved in producing the error.
69+
For example, you can add some debug statements before the error is issued to discover
70+
the state of the compiler. [See some useful ways to debug values.][inspect]
3471

35-
## Where was a particular object created?
72+
### Where was a particular object created?
3673

37-
This question arises, e.g., if you realised there's an object on the error site that shouldn't be there, most probably causing the error. So, in attempt to rectify the offending object, you want to know where it was created.
74+
If you navigate to the site of the error, and discover a problematic object, you will want to know
75+
why it exists in such a state, as it could be the cause of the error. You can discover the
76+
creation site of that object to understand the logic that created it.
3877

3978
You can do this by injecting a *tracer* into the class of an instance in question.
4079
A tracer is the following variable:
4180
```scala
4281
val tracer = Thread.currentThread.getStackTrace.mkString("\n")
4382
```
44-
When placed as a top-level definition at a class, it will contain a stack trace pointing at where exactly
45-
its particular instance was created. This is because, as a top-level `val`, it will be evaluated on
46-
construction of the instance in question.
83+
When placed as a member definition at a class, it will contain a stack trace pointing at where exactly
84+
its particular instance was created.
4785

4886
Once you've injected a tracer into a class, you can `println` that tracer from the error site or
4987
other site you've found the object in question.
5088

51-
### Procedure
89+
#### Procedure
5290

5391
1. Determine the type of the object in question. You can use one of the following techniques to do so:
5492
- Use an IDE to get the type of an expression, or save the expression to a `val`
@@ -60,19 +98,9 @@ other site you've found the object in question.
6098
encountered the object. This will give you the stack trace pointing to the place where the
6199
constructor of that object was invoked.
62100

63-
### Trace a Tree Creation Site
64-
65-
A special case of finding an object's creation site is for a Tree, this is supported directly in the compiler,
66-
as trees have an associated unique ID:
67-
68-
1. Run the compiler with `-Xprint:<phase-name>` and `-Yshow-tree-ids` flags. You should see the tree in question
69-
be printed, alongside its ID. You'll see something like `println#223("Hello World"#37)`.
70-
2. Copy the ID of the desired tree.
71-
3. Run the compiler with `-Ydebug-tree-with-id <tree-id>` flag. The compiler will print a stack trace pointing to the creation site of the tree the ID provided.
72-
73-
## Where was a particular value assigned to a variable?
101+
### Where was a particular value assigned to a variable?
74102

75-
Say you have a certain [type][types] assigned to a [Denotation] and you would like to know why it is that
103+
Say you have a certain [type][types] assigned to a [Denotation] and you would like to know why it has that
76104
specific type. The type of a denotation is defined by `var myInfo: Type`, and can be assigned multiple times.
77105
In this case, knowing the creation site of that `Type`, as described above, is not useful; instead, you need to
78106
know the *assignment* (not *creation*) site.
@@ -89,3 +117,7 @@ def myInfo_=(x: Type) = { tracer = Thread.currentThread.getStackTrace.mkString("
89117
[areas]: {% link _overviews/scala3-contribution/procedures-areas.md %}
90118
[Denotation]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/core/Denotations.scala
91119
[types]: {% link _overviews/scala3-contribution/arch-types.md %}
120+
[lifecycle]: {% link _overviews/scala3-contribution/arch-lifecycle.md %}#phases
121+
[PostTyper]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/transform/PostTyper.scala
122+
[ScalaSettings]: https://github.com/lampepfl/dotty/blob/master/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
123+
[inspect]: {% link _overviews/scala3-contribution/procedures-inspection.md %}

_overviews/scala3-contribution/procedures-reproduce.md

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ sbt:scala3> scala3/scalac -d local/out local/i7710.scala
2424
> Here, the `-d` flag specifies a directory `local/out` where generated code will be output.
2525
2626
You can then verify that the local reproduction has the same behaviour as originally reported in the issue.
27-
If so, then you can get to trying to fix it, else, perhaps the issue is out of date, or
27+
If so, then you can start to try and fix it. Otherwise, perhaps the issue is out of date, or
2828
is missing information about how to accurately reproduce the issue.
2929

3030
## Dotty Issue Workspace
@@ -36,7 +36,7 @@ file and then run them from the Dotty project's sbt console.
3636
### Try an Example Issue
3737

3838
Let's use [dotty-issue-workspace] to reproduce issue [#7710]:
39-
1. Follow [steps in README][workspace-readme] to install the plugin.
39+
1. Follow [the steps in the README][workspace-readme] to install the plugin.
4040
2. In your Issue Workspace directory (as defined in the plugin's README file,
4141
"Getting Started" section, step 2), create a subdirectory for the
4242
issue: `mkdir i7710`.
@@ -68,11 +68,11 @@ Let's use [dotty-issue-workspace] to reproduce issue [#7710]:
6868
6969
### Using Script Arguments
7070
71-
You can use script arguments inside `launch.iss` to reduce steps when
71+
You can use script arguments inside `launch.iss` to reduce the number of steps when
7272
working with issues.
7373
74-
Say you have an issue `foo`, with two alternative files that are very similar
75-
`original.scala`, which reproduces the issue and `alt.scala`, which does not,
74+
Say you have an issue `foo`, with two alternative files that are very similar:
75+
`original.scala`, which reproduces the issue, and `alt.scala`, which does not,
7676
and you want to compile them selectively?
7777
7878
You can achieve this via the following `launch.iss`:
@@ -92,13 +92,18 @@ the dollar notation: `$1` for the first argument, `$2` for the second and so on.
9292
9393
### Multiline Commands
9494
95-
`launch.iss` files support putting commands accross multiple lines, which is useful for
96-
toggling lines by using a comment.
95+
Inside a `launch.iss` file, one command can be spread accross multiple lines. For example,
96+
if your command has multiple arguments, you can put each argument on a new line.
9797
98-
The following `launch.iss` file is a useful template for issues that run code after
99-
compilation, it also includes some debug compiler flags, commented out.
100-
The advantage of having them is, if you need one them, you can enable it quickly by
101-
uncommenting it – as opposed to looking it up and typing it in your existing command.
98+
Multiline commands can even have comments inbetween lines. This is useful
99+
if you want to try variants of a command with optional arguments (such as configuration).
100+
You can put the optional arguments on separate lines, and then decide when they are passed to
101+
the command by placing `#` in front to convert it to a comment (i.e. the argument will
102+
not be passed). This saves typing the same arguments each time you want to use them.
103+
104+
The following `launch.iss` file is an example of how you can use multiline commands as a
105+
template for solving issues that [run compiled code][run]. It demonstrates configuring the
106+
`scala3/scalac` command using compiler flags, which are commented out.
102107
Put your favourite flags there for quick usage.
103108
104109
```bash
@@ -115,7 +120,7 @@ scala3/scalac # Invoke the compiler task defined by the Dotty sbt project
115120
# -Ycheck:all
116121
$here/$1.scala # Invoke the compiler on the file passed as the second argument to the `issue` command. E.g. `issue foo Hello` will compile `Hello.scala` assuming the issue folder name is `foo`.
117122
118-
scala3/scala -classpath $here/out Test # Run the class `Test` generated by the compiler run (assuming the compiled issue contains such an entry point, otherwise comment this line)
123+
scala3/scala -classpath $here/out Test # Run main method of `Test` generated by the compiler run.
119124
```
120125
121126
## Conclusion
@@ -128,3 +133,4 @@ how to try and detect its root cause.
128133
[dotty-issue-workspace]: https://github.com/anatoliykmetyuk/dotty-issue-workspace
129134
[workspace-readme]: https://github.com/anatoliykmetyuk/dotty-issue-workspace#getting-started
130135
[clone]: {% link _overviews/scala3-contribution/start-intro.md %}#clone-the-code
136+
[run]: {% link _overviews/scala3-contribution/procedures-testing.md %}#checking-program-output

0 commit comments

Comments
 (0)
0