If you use dbg
in a package's interface
file, the compiler throws the following error and hangs:
Thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', crates/compiler/mono/src/ir.rs:6826:18
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
Apparently, env.expectation_subs
is None
here: https://github.com/roc-lang/roc/blob/24e2c661870d9d7c54a5aa8750c334a837af1966/crates/compiler/mono/src/ir.rs#L6808-L6812
I wonder if that is interface specific. I have seen similar errors a lot. That and sometimes debug just not printing. Definitely one of the easier to break features. I think i notice it most in rather nested code, especially if related to tasks.
Oh. I haven't noticed that. In this case the app
's main
is directly calling the function from the package's interface
with the dbg
usage in it.
At least in my absolute minimal repro, it is working in an interface
:
interface Interface
exposes [someFunc]
imports []
someFunc = \x ->
dbg x
x
So maybe not interface specific. Are you able to share example code where this happens or a repro?
Oh, nevermind, I can repro.
It takes an interface in a package specifically, not an interface in general.
submitted #5185 as a minimal repro.
Nice
Found the root cause of the None
in env.expectaction_subs
: https://github.com/roc-lang/roc/blob/24e2c661870d9d7c54a5aa8750c334a837af1966/crates/compiler/load_internal/src/file.rs#L2748-L2753
let should_include_expects = (!loc_expects.is_empty() || !loc_dbgs.is_empty()) && {
let modules = state.arc_modules.lock();
modules
.package_eq(module_id, state.root_id)
.expect("root or this module is not yet known - that's a bug!")
};
!loc_dbgs.is_empty()
is true
because the dbg
exists
but .package_eq(module_id, state.root_id)
evaluates to false
because the module is in a different package
When building applications, you probably don't want to include expects from packages, so that makes sense
However, we still need a way to use dbg
and expect
when building packages. Maybe this can be a CLI option?
Also, in normal operation, it shouldn't crash because a package contains a dbg
or expect
this is an interesting design question...I've gone back and forth on this in the past, but what makes sense to me right now is:
dbg
no matter where it comes from. This way if you're debugging a local package on your filesystem, it Just Works.dbg
(just take them out before you publish, don't annoy people with your own debugging logic!)expect
is trickier because on the one hand it could be annoying if I get a third-party package that's crashing due to failed expect
s all the time...but on the other hand, wouldn't it be better if I could report that to them? :thinking:
my default thinking is that expect
should just always work the same way no matter whether it's a package, and then we can revisit that if it's annoying in practice
Ah cool. So we just need to get rid of that package_eq
check, then.
I tried it last night and dbg
just started working from packages
Should I make a PR with that change?
sounds good to me! @Folkert de Vries any concerns?
The one annoyance with this is that this will also mean “roc test” will run all tests under a package and all its dependencies, not just local to the module.
That could be made into a separate check though
hm, aren't those separate?
like roc test
doesn't have to run top-level expect
s in other packages
even if it still runs inline expect
s
Right. I just mean that the implementation, I don't think it is enough to only get rid of the package_eq
check.
Yeah, if I get rid of that check, roc test
includes expect
s from packages
and this weird bug shows up if I have both dbg
s and expect
s in a package, roc test
hangs, but it works fine if only have one kind :oh_no:
Agus Zubiaga said:
Yeah, if I get rid of that check,
roc test
includesexpect
s from packages
oh ok, so then the problem is that right after that code we're using should_include_expects
to decide whether to include dbg
s too
so that line could be used in the else
branch too, just with expectations:
being empty
could go even further to have that under an else if !loc_dbgs.is_empty() {
so we don't bother cloning solved_subs
etc if there happen to be no dbg
s
Last updated: Jul 06 2025 at 12:14 UTC