Bug reports are filed as GitHub issues at github.com/jjstwerff/loft/issues. A good report makes the difference between a quick fix and a problem that sits unresolved because it cannot be reproduced.
Before reporting
Check whether the issue is already known:
- Search the open issues for a few keywords from your error message.
- Read the relevant language page — some behaviours that look like bugs are documented design choices. For example,
n / 0returns null rather than crashing;not nullfields default to zero rather than null.
If you are not sure whether what you have found is a bug, open an issue anyway with the label question. It is better to ask than to sit with a broken program.
What to include
A report needs four things to be actionable. Missing any of them makes the problem much harder to fix.
1. Loft version and platform
Run loft --version and include the output. Also include your operating system and architecture (e.g. macOS 14 on Apple Silicon, Ubuntu 22.04 on x86-64, Windows 11).
$ loft --version
loft 0.1.0
If you built from source, include the commit hash:
$ git -C "$(dirname $(which loft))" rev-parse HEAD 2>/dev/null || git log -1 --format=%H
2. A minimal reproducer
Paste the smallest loft program that demonstrates the problem. Aim for under 20 lines. Remove everything that is not necessary to trigger the bug — unused structs, unrelated functions, extra print statements. The smaller the program, the faster it gets fixed.
A useful template:
fn main() {
// the smallest code that shows the problem
}
If the problem only appears with large data (e.g. a crash with 10 000 elements but not 10), say so and include the generation code rather than a literal list.
If the program reads a file, either include the file contents inline as a string literal, or attach the file to the issue.
3. What actually happens
Include the exact output. For a compiler error, paste the full error message and the line it points at. For a wrong result, show the value that was printed. For a crash, include the panic message and, if available, the backtrace:
$ RUST_BACKTRACE=1 loft my_program.loft
If the program produces no output and exits silently, say so explicitly — "no output, exit code 0" is useful information.
4. What you expected instead
State clearly what the correct result should be. "It should print 42" or "it should compile without error" is more useful than "it is wrong". If your expectation is based on a specific section of the documentation, link to it.
Types of problems
Unexpected compiler error
The compiler rejects a program you believe is valid. Include:
- The full error message with file, line, and column.
- Your reading of the language rules that led you to believe the program is correct.
Error: Cannot add elements to 'v' while it is being iterated
--> my_program.loft:8:5
Missing compiler error
The compiler accepts a program that it should reject. Include:
- The program and the rule you think it violates.
- What the program does at runtime (since it compiled and ran).
Wrong result
The program compiles and runs but produces incorrect output. Include:
- The program, the actual output, and the expected output side by side.
- Whether the problem is consistent or intermittent. Intermittent failures often indicate a parallel execution issue.
Expected: 55
Actual: 0
Crash or panic
The interpreter panics or segfaults. Include the full panic message. Run the debug build for a clearer error — release builds sometimes produce a silent crash where the debug build gives a Rust panic with a location:
$ cargo build --bin loft # builds the debug binary
$ ./target/debug/loft my_program.loft
If you installed a release binary, try building from source to get the debug binary. Crashes in the debug build always include enough information to locate the problem.
Unexpected warning
The compiler emits a warning for code you believe is correct. Include the warning message and why you think the code is intentional.
Reducing to a minimal example
If your original program is large, reduce it before reporting. The process is mechanical:
- Delete any function or struct that is not involved in triggering the problem. Run after each deletion to confirm the bug is still present.
- Replace complex expressions with simpler ones — literals instead of computed values, small constants instead of large ones.
- If the problem only appears in a
forloop, try to reproduce it with a plain assignment instead. - Stop when removing anything else makes the bug disappear.
A 5-line reproducer gets a fix in minutes. A 500-line reproducer may sit in the queue for weeks.
Feature requests and design questions
Use the GitHub issue tracker for feature requests too, with the label enhancement. Describe the problem you are trying to solve, not just the solution you have in mind — the best implementation may differ from what you imagined, and the problem description helps evaluate trade-offs.
For questions about language behaviour ("is this a bug or by design?"), use the question label.