Skip to content

Add tutorial on how to debug the Scala 3 compiler #2757

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 27, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/arch-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Contexts
type: section
description: This page describes symbols in the Scala 3 compiler.
num: 14
num: 15
previous-page: arch-lifecycle
next-page: arch-phases
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/arch-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: High Level Architecture
type: chapter
description: This page introduces the high level architecture of the Scala 3 compiler.
num: 12
num: 13
previous-page: procedures-checklist
next-page: arch-lifecycle
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/arch-lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Compiler Overview
type: section
description: This page describes the lifecycle for the Scala 3 compiler.
num: 13
num: 14
previous-page: arch-intro
next-page: arch-context
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/arch-phases.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Compiler Phases
type: section
description: This page describes the phases for the Scala 3 compiler.
num: 15
num: 16
previous-page: arch-context
next-page: arch-types
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/arch-symbols.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Symbols
type: section
description: This page describes symbols in the Scala 3 compiler.
num: 18
num: 19
previous-page: arch-time
next-page:
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/arch-time.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Time in the Compiler
type: section
description: This page describes the concepts of time in the Scala 3 compiler.
num: 17
num: 18
previous-page: arch-types
next-page: arch-symbols
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/arch-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Compiler Types
type: section
description: This page discusses the representation of types in the compiler
num: 16
num: 17
previous-page: arch-phases
next-page: arch-time
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/procedures-areas.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Common Issue Locations
type: section
description: This page describes common areas of issues around the Scala 3 compiler.
num: 7
num: 8
previous-page: procedures-navigation
next-page: procedures-inspection
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/procedures-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Pull Request Checklist
type: section
description: This page describes a checklist before opening a Pull Request to the Scala 3 compiler.
num: 11
num: 12
previous-page: procedures-testing
next-page: arch-intro
---
Expand Down
194 changes: 194 additions & 0 deletions _overviews/scala3-contribution/procedures-debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
---
title: Debugging the Compiler
type: section
description: This page describes navigating around the Scala 3 compiler.
num: 7
previous-page: procedures-navigation
next-page: procedures-areas
---

The debugger is a powerful tool to navigate the internals of the compiler and track bugs.

You can start the Scala debugger in VSCode using [Metals](https://scalameta.org/metals/).
In this page you will learn how to configure it, and how to use it.

## Importing the project in VSCode using Metals

The first step is to import the build in Metals, if it has not yet been imported.

To do so you can open the [lampefl/dotty][lampepfl/dotty] repository in VSCode and click `Import build` in Metals view.
It may take a few minutes to import, compile and index the full project.

![Import build](/resources/images/scala3-contribution/import-build.jpg)

If you have any trouble with importing, you can try to switch the build server from Bloop to sbt,
by running the `Metals: Switch build server` command from VSCode command palette.

## Configuring the debugger

To configure the debugger in VSCode, you can go to the `Run and Debug` view and click `create a launch.json file`.
It creates the `launch.json` file in the `.vscode` folder, in which we will define the debug configurations.

![Create launch.json file](/resources/images/scala3-contribution/launch-config-file.jpg)

To create a debug configuration:
- Open the `.vscode/launch.json` file
- Click the `Add Configuration` button
- Go down the list of templates and select `Scala: Run main class`

![Create configuration](/resources/images/scala3-contribution/create-config.jpg)

The added configuration should look like this:
```json
{
"type": "scala",
"request": "launch",
"name": "Untitled",
"mainClass": "???",
"args": [],
"jvmOptions": [],
"env": {}
}
```

This is a template that you need to fill out.
First You can give a `name` to your configuration, for instance `Debug Scala 3 Compiler`.

The two most important parameters, to debug the compiler, are `mainClass` and `args`.
The `mainClass` of the compiler is `dotty.tools.dotc.Main`.
In the `args` you need to specify the compiler arguments, which must contain at least a `.scala` file to compile and a `-classpath` option.

To start with, we can compile the `../tests/pos/HelloWorld.scala` file.
In the classpath, we always need at least the `scala-library_2.13` and the bootstrapped `scala3-library_3`.
To locate them on your filesystem you can run the `show scala3-library-bootstrapped/fullClasspath` command in sbt.

```
$ sbt
> show scala3-library-bootstrapped/fullClasspath
[info] * Attributed(/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes)
[info] * Attributed(/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar)
[success] Total time: 1 s, completed Mar 10, 2023, 4:37:43 PM
```

Note that it is important to use the bootstrapped version of the `scala3-library` to get the correct TASTy version.

Additionally you can add the `["-color", "never"]` arguments to prevent the compiler from printing ANSI codes as strings in the debug console.

Here is the final configuration:
```json
{
"type": "scala",
"request": "launch",
"name": "Debug Scala 3 Compiler",
"mainClass": "dotty.tools.dotc.Main",
"args": [
"../tests/pos/HelloWorld.scala",
"-classpath",
// to replace with your own paths
"/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar",
"-color",
"never"
],
"jvmOptions": [],
"env": {}
}
```

## Customizing the debug configurations

### Compiling several files at once

You can compile more than one Scala file, by adding them in the `args`:
```json
"args": [
"file1.scala",
"file2.scala",
"-classpath",
"/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar"
]
```

### Depending on a library

To add a dependency to an external library you need to download it and all its transitive dependencies, and to add them in the classpath.
The Coursier CLI can help you to do that.
For instance to add a dependency to cats you can run:
```
$ cs fetch org.typelevel::cats-core:2.+ --classpath --scala-version 3 --exclude org.scala-lang:scala-library --exclude org.scala-lang:scala3-library
/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-core_3/2.9.0/cats-core_3-2.9.0.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-kernel_3/2.9.0/cats-kernel_3-2.9.0.jar
```

And concatenate the output into the classpath argument, which should already contain the scala-library_2.13 and the bootstrapped scala3-library:

```json
"args": [
"using-cats.scala",
"-classpath",
"/home/user/lampepfl/dotty/out/bootstrap/scala3-library-bootstrapped/scala-3.3.1-RC1-bin-SNAPSHOT-nonbootstrapped/classes:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/scala-lang/scala-library/2.13.10/scala-library-2.13.10.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-core_3/2.9.0/cats-core_3-2.9.0.jar:/home/user/.cache/coursier/v1/https/repo1.maven.org/maven2/org/typelevel/cats-kernel_3/2.9.0/cats-kernel_3-2.9.0.jar"
]
```

### Add more compiler options

In the `args` you can add any additional compiler option you want.

For instance you can add `-Xprint:all` to print all the generated trees after each mega phase.

Run `scalac -help` to get an overview of the available compiler options.

### Defining more than one launch configuration

You can create as many debug configurations as you need: to compile different files, with different compiler options or different classpaths.

## Starting the debugger

Before starting the debugger you need to put a breakpoint in the part of the code that you want to debug.
If you don't know where to start, you can put a breakpoint in the `main` method of the `dotty.tools.dotc.Driver` trait.

![First breakpoint](/resources/images/scala3-contribution/breakpoint.jpg)

Now to start the debugger, open the debug view, find the drop-down list of all the debug configurations and click on yours.
The debugger should start and pause on your breakpoint.

![Start debugger](/resources/images/scala3-contribution/start-debugger.jpg)

## Using the debugger

### Navigating the call stack

When the debugger has paused, you can see the current call stack in the `Debug and Run` view.
Each frame of the call stack contains different variables, whose values you can see in the `Variables` section of the `Debug and Run` view.

![Call stack](/resources/images/scala3-contribution/call-stack.jpg)

Analysing the call stack and the variables can help you understand the path taken by the compiler to reach that state.

### The debugging steps

The debug toolbar contains the `Continue / Pause`, `Step Over`, `Step Into`, `Step Out`, `Restart` and `Stop` buttons.

![Debugging steps](/resources/images/scala3-contribution/toolbar.jpg)

You can use the step buttons to execute the code step by step and get a precise understanding of the program.

### The debug console

When the debugger has paused, you can evaluate any Scala 3 expression in the debug console.
This is useful to inspect some values or to execute some parts of the code.

For instance, you can evaluate `tree.show` to pretty-print a tree.

![Import build](/resources/images/scala3-contribution/debug-console.jpg)

### Conditional breakpoints

In a breakpoint you can define a condition, in the form of a Boolean expression written in Scala.
The program will stop on the breakpoint as soon as the condition is met.

To add a condition, right-click on a breakpoint and pick `Edit breakpoint...`.

For instance, if you know that a bug happens on typing a method `foo`, you can use the condition `tree.symbol.name.show == "foo"` in a breakpoint in the `Typer`.

![Import build](/resources/images/scala3-contribution/conditional-breakpoint.jpg)

[lampepfl/dotty]: https://github.com/lampepfl/dotty
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/procedures-efficiency.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Improving Your Workflow
type: section
description: This page describes improving efficiency of debugging the Scala 3 compiler.
num: 9
num: 10
previous-page: procedures-inspection
next-page: procedures-testing
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/procedures-inspection.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: How to Inspect Values
type: section
description: This page describes inspecting semantic values in the Scala 3 compiler.
num: 8
num: 9
previous-page: procedures-areas
next-page: procedures-efficiency
---
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/procedures-navigation.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ type: section
description: This page describes navigating around the Scala 3 compiler.
num: 6
previous-page: procedures-reproduce
next-page: procedures-areas
next-page: procedures-debugging
---

In this section, you will be able to answer questions such as:
Expand Down
2 changes: 1 addition & 1 deletion _overviews/scala3-contribution/procedures-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
title: Testing Your Changes
type: section
description: This page describes test procedures in the Scala 3 compiler.
num: 10
num: 11
previous-page: procedures-efficiency
next-page: procedures-checklist
---
Expand Down
4 changes: 2 additions & 2 deletions _overviews/scala3-contribution/start-intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ never a bad idea to check.

#### Nice To Have

An IDE, such as [Metals] will help you develop in Scala 3 with features such as goto-definition,
and with the [VS Code][vs-code] text editor you can even create interactive worksheets for an
An IDE, such as [Metals] will help you develop in Scala 3 with features such as autocompletion or goto-definition,
and with the [VS Code][vs-code] text editor you can even use the Scala debugger, or create interactive worksheets for an
iterative workflow.

### Clone the Code
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added resources/images/scala3-contribution/toolbar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.