Skip to content
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
50 changes: 50 additions & 0 deletions .claude/skills/type-checker-tests/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Use this skill when adding new type checker functions or expanding behavior.
|--------|---------|
| Find next test number | `ls tests-integration/fixtures/checking/ \| tail -5` |
| Run a test or multiple tests | `just tc NNN` or `just tc 101 102` |
| Run with tracing enabled | `just tc --debug NNN` |
| Run all checking tests | `just tc` |
| Accept all pending snapshots | `cargo insta accept` |

Expand Down Expand Up @@ -162,6 +163,55 @@ When investigating a potential compiler bug:
```bash
# Focus on single test to reduce noise
just tc NNN

# Enable tracing to see type checker behaviour
just tc --debug NNN
```

### Trace Files

The `--debug` flag emits detailed type checker traces to `target/compiler-tracing/`.

**Trace file naming:** `{test_id}_{module_name}.jsonl`
- Example: `200_int_compare_transitive_Main.jsonl`

**Output format:** JSON Lines (one JSON object per line), containing:
- `timestamp` - when the event occurred
- `level` - DEBUG, INFO, or TRACE
- `fields` - trace data (e.g., types being unified)
- `target` - the module emitting the trace (e.g., `checking::algorithm::unification`)
- `span`/`spans` - current span and span stack

**Example trace line:**
```json
{"timestamp":"...","level":"DEBUG","fields":{"t1":"?0","t2":"Int"},"target":"checking::algorithm::unification","span":{"name":"unify"}}
```

When `--debug` is used, the trace file path is shown alongside pending snapshots:
```
UPDATED tests-integration/fixtures/checking/200_int_compare_transitive/Main.snap
TRACE target/compiler-tracing/200_int_compare_transitive_Main.jsonl
```

### Analysing Traces

Trace files can be large for complex tests. Use sampling and filtering:

```bash
# Check file size and line count
wc -l target/compiler-tracing/NNN_*.jsonl

# Sample random lines to get an overview
shuf -n 20 target/compiler-tracing/NNN_*.jsonl | jq .

# Filter by level
jq 'select(.level == "DEBUG")' target/compiler-tracing/NNN_*.jsonl

# Filter by target module
jq 'select(.target | contains("unification"))' target/compiler-tracing/NNN_*.jsonl

# Extract specific fields
jq '{level, target, fields}' target/compiler-tracing/NNN_*.jsonl
```

You should run `just tc` to check for regressions.
33 changes: 33 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions compiler-bin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ repository = "https://github.com/purefunctor/purescript-analyzer"
keywords = ["purescript", "language server"]
categories = ["compilers"]

[features]
default = []
no-tracing = ["checking/no-tracing"]

[dependencies]
checking = { version = "0.1.0", path = "../compiler-core/checking" }
analyzer = { version = "0.1.0", path = "../compiler-lsp/analyzer" }
async-lsp = "0.2.2"
clap = { version = "4.5.53", features = ["derive"] }
Expand Down
7 changes: 7 additions & 0 deletions compiler-bin/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ pub struct Config {
default_value("info")
)]
pub lsp_log: LevelFilter,
#[arg(
long,
value_name("LevelFilter"),
help("Log level for the type checker"),
default_value("off")
)]
pub checking_log: LevelFilter,
#[arg(
long,
help("Command to use to get source files"),
Expand Down
1 change: 1 addition & 0 deletions compiler-bin/src/logging.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub fn start(config: Arc<cli::Config>) {
let fmt_filter = filter::Targets::new()
.with_target("building::engine", config.query_log)
.with_target("purescript_analyzer::lsp", config.lsp_log)
.with_target("checking", config.checking_log)
.with_default(LevelFilter::INFO);
let fmt = fmt::layer().with_writer(file).with_filter(fmt_filter);

Expand Down
7 changes: 7 additions & 0 deletions compiler-core/checking/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,24 @@ name = "checking"
version = "0.1.0"
edition = "2024"

[features]
default = []
no-tracing = ["tracing/max_level_off"]

[dependencies]
tracing = "0.1.44"
building-types = { version = "0.1.0", path = "../building-types" }
files = { version = "0.1.0", path = "../files" }
indexing = { version = "0.1.0", path = "../indexing" }
indexmap = "2.12.1"
interner = { version = "0.1.0", path = "../interner" }
itertools = "0.14.0"
lowering = { version = "0.1.0", path = "../lowering" }
parsing = { version = "0.1.0", path = "../parsing" }
petgraph = "0.8.3"
pretty = "0.12"
resolving = { version = "0.1.0", path = "../resolving" }
rustc-hash = "2.1.1"
smol_str = "0.3.4"
stabilizing = { version = "0.1.0", path = "../stabilizing" }
sugar = { version = "0.1.0", path = "../sugar" }
Loading