![]() A "late specialization" of a type is an ability specialization that is not visible or needed until after type-specialization; i.e. during monomorphization. The `Inspect.toInspector` ability is special-cased for opaques that do not claim or explicitly implement `Inspect`. In such cases, they are treated as structural types, and given the immediate specialization of `Inpect.inspectOpaque`. However, prior to this commit, that special-casing would only be applied during early specialiation (i.e. specializations visible during generalized type inference). This commit applies the special case to late specialization as well - the specialization decision for an opaque type is always the specialization of the opaque type in the late case, but now, when we go to look up the ambient lambda set of the specialization, if it does not exist and corresponds to `Inspect.toInspector`, we fall back to the immediate. One concern I have here is that in a case like ``` Op := {} x = dbg (@Op {}) ``` the specialization of `Inspect.toInspector` for `Op` should be known early. Indeed, the program ``` Op := {} x = Inspect.toInspector (@Op {}) |> Inspect.apply (Inspect.init {}) |> Inspect.toDbgStr ``` Compiles fine without this change. This makes me suspect there is an issue with the implementation of `dbg`'s desugaring. If possible, this should be addressed sooner rather than later. Closes #6127 |
||
---|---|---|
.. | ||
alias_analysis | ||
arena_pool | ||
build | ||
builtins | ||
can | ||
checkmate | ||
checkmate_schema | ||
collections | ||
constrain | ||
debug_flags | ||
derive | ||
derive_key | ||
exhaustive | ||
fmt | ||
gen_dev | ||
gen_llvm | ||
gen_wasm | ||
ident | ||
late_solve | ||
load | ||
load_internal | ||
module | ||
mono | ||
parse | ||
problem | ||
region | ||
roc_target | ||
serialize | ||
solve | ||
solve_problem | ||
solve_schema | ||
test_derive | ||
test_gen | ||
test_mono | ||
test_mono_macros | ||
test_solve_helpers | ||
test_syntax | ||
types | ||
uitest | ||
unify | ||
DESIGN.md | ||
README.md |
The Roc Compiler
For an overview of the design and architecture of the compiler, see DESIGN.md. If you want to dive into the implementation or get some tips on debugging the compiler, see below
Getting started with the code
The compiler contains a lot of code! If you're new to the project it can be hard to know where to start. It's useful to have some sort of "main entry point", or at least a "good place to start" for each of the main phases.
After you get into the details, you'll discover that some parts of the compiler have more than one entry point. And things can be interwoven together in subtle and complex ways, for reasons to do with performance, edge case handling, etc. But if this is "day one" for you, and you're just trying to get familiar with things, this should be "good enough".
The compiler is invoked from the CLI via build_file
in cli/src/build.rs
Phase | Entry point / main functions |
---|---|
Compiler entry point | load/src/file.rs: load, load_and_monomorphize |
Parse header | parse/src/module.rs: parse_header |
Parse definitions | parse/src/module.rs: module_defs |
Canonicalize | can/src/def.rs: canonicalize_defs |
Type check | solve/src/module.rs: run_solve |
Gather types to specialize | mono/src/ir.rs: PartialProc::from_named_function |
Solve specialized types | mono/src/ir.rs: from_can, with_hole |
Insert reference counting | mono/src/ir.rs: Proc::insert_refcount_operations |
Code gen (optimized but slow) | gen_llvm/src/llvm/build.rs: build_procedures |
Code gen (unoptimized but fast, CPU) | gen_dev/src/object_builder.rs: build_module |
Code gen (unoptimized but fast, Wasm) | gen_wasm/src/lib.rs: build_module |
For a more detailed understanding of the compilation phases, see the Phase
, BuildTask
, and Msg
enums in load/src/file.rs
.
Debugging the compiler
Please see the debug flags for information on how to ask the compiler to emit debug information during various stages of compilation.
There are some goals for more sophisticated debugging tools:
- A nicer unification debugger, see https://github.com/roc-lang/roc/issues/2486. Any interest in helping out here is greatly appreciated.
General Tips
Miscompilations
If you observe a miscomplication, you may first want to check the generated mono
IR for your code - maybe there was a problem during specialization or layout
generation. One way to do this is to add a test to test_mono/src/tests.rs
and run the tests with cargo test -p test_mono
; this will write the mono
IR to a file.
Typechecking errors
First, try to minimize your reproduction into a test that fits in
solve_expr
.
Once you've done this, check out the ROC_PRINT_UNIFICATIONS
debug flag. It
will show you where type unification went right and wrong. This is usually
enough to figure out a fix for the bug.
If that doesn't work and you know your error has something to do with ranks,
you may want to instrument deep_copy_var_help
in solve.
If that doesn't work, chatting on Zulip is always a good strategy.