I started debugging glue on basic-cli. When I run it on main.roc
, it's falling into this unreachable!
because it finds a Result
but type is Layout::Struct
.
I believe it should be Layout::Union
so that it matches this case.
I'm trying to figure out how to get the position in the source code
Layout::Struct
is generated for Result
s if either the ok or error type is void, for example Result Foo []
can only ever be Ok Foo
, so we compile it to just the layout of Foo
Unfortunately there is presently not enough debug information to trace you back to the source code position
however, if you print out the types reached to that position (dbg!(subs.dbg(var))
) it might give you enough hints to contextualize where the type was defined
Oh, I see. So we should be handling this case then.
Ayaz Hafiz said:
however, if you print out the types reached to that position (
dbg!(subs.dbg(var))
) it might give you enough hints to contextualize where the type was defined
Ok, it's a Result {} []
somewhere
Weirdly I can't seem to find one like that in basic-cli
. There are a few Result {} {}
but I believe that would be Layout::Union
following your logic.
Ah, Task
holds a Result
and main.roc
has a Task {} []
Ok, all is clear then. This is a real case and we have to handle Layout::Struct
Result
.
I added that case and now it doesn't crash, but it also doesn't generate anything
It's finding only what's under main.roc and not all the other modules such as Effect
and its dependencies.
it crawls from the type of mainForHost
(or should, anyway)
Right, I think it is. However, mainForHost
references Task
which references InternalTask
which references Effect
and it doesn't seem to find any of those.
more specifically, no rust code is generated for those types?
Correct. This is all it generates:
// ⚠️ GENERATED CODE ⚠️ - this entire file was generated by the `roc glue` CLI command
#![allow(unused_unsafe)]
#![allow(dead_code)]
#![allow(unused_mut)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
#![allow(clippy::undocumented_unsafe_blocks)]
#![allow(clippy::redundant_static_lifetimes)]
#![allow(clippy::unused_unit)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::let_and_return)]
#![allow(clippy::missing_safety_doc)]
#![allow(clippy::redundant_static_lifetimes)]
#![allow(clippy::needless_borrow)]
#![allow(clippy::clone_on_copy)]
Which makes sense because these are all the types it finds:
types: [
Unit,
EmptyTagUnion,
RocResult(
TypeId(
0,
),
TypeId(
1,
),
),
Function {
name: "TODO_roc_function_71",
args: [
TypeId(
0,
),
],
ret: TypeId(
2,
),
},
],
Just the stuff on main.roc if I'm reading correctly
and all of those are skipped here: https://github.com/roc-lang/roc/blob/3b5f6ef8285fb4177f24c7094c807ca9fb6485ec/crates/glue/src/rust_glue.rs#L282-L299
mainForHost
returns a Task
though, I think the debug output above says it returns a Result
. I guess that's getting optimized away?
I see, I think this makes sense.
an effect is internally generated as a thunk (Effect a := {} -> a
). I'm assuming you're looking at our main
branch, and there we don't generate anything for functions yet
we have an experimental branch that does handle functions
but some other stuff is still broken on that branch
Oh. Yes, I'm on main
. Do you mean glue
can generate functions in that experimental branch?
it can generate glue for function types, yes
our actual compilation scheme for functions is a bit involved
I see. I wonder if the existing glue code in basic-cli was generated using glue on that branch.
Maybe that's all I need to do
(the branch with functions is glue-getters-rtfeldman
, but it's in an unfinished state)
well that glue file does not contain anything for Task
or Effect
Yeah, so that might not be the issue then. What I wanted to generate was error types like these: https://github.com/roc-lang/basic-cli/blob/main/src/InternalFile.roc
Which were somehow generated here: https://github.com/roc-lang/basic-cli/blob/main/src/src/file_glue.rs
right, but from what I know that type needs to be reachable from the type of mainForHost
and it isn't because glue stops when it hits a function type and it always does for basic-cli
so I'm not sure how that glue was generated
Right, that's what I understood from you. Maybe at some point there was a version of glue that generated all the types that Task
and Effect
reference but nothing for themselves?
Sorry if I'm saying something stupid, this is my first endeavor into the compiler :D
yeah no clearly at some point this glue was generated.
Richard will know all of the details
Tried running it on that branch and it hit the same unreachable!()
for the Layout::Struct
Result
. I added that case and it generated some code for function as you said it would but still nothing for the types.
I'll wait for Richard to give me some more context
In case it helps, my workaround for the fact that glue doesn't handle functions, is to just define a constant of each type you care about! This works as long as the types don't have lambdas inside them!
At least that used to work a few months ago
in the main.roc
you mean?
yeah
whatever Roc file you pass to the glue generator
Just tried that but it failed because of the unused constant:
thread 'main' panicked at 'not yet implemented: Gracefully report compilation problems during glue generation:
[UnusedDef(`16.IdentId(2)`, @233-240)], []', crates/glue/src/load.rs:125:9
you might be able to get away with adding
main =
when someConstant is
_ -> rest of main
Ooh, that did work! Thanks
It still doesn't work as it is on main
because of the unreachable crash for Result
, but it does if handle that case
you can make a PR for handling that result case
then we'll merge it in everywhere
Yeah but I think that Roc programs would still crash becase the memory layout won't line up for things returning Result _ []
I think roc_std
is always using the union layout for Result
ah, yes that is correct
so that needs some special handling
which is maybe why the file example is marked as "broken" in basic-cli
right
Should roc_std
expose a NoErrorResult
or something like that?
hmm I'm not sure
You could mess up and use it when you're supposed to use the normal Result
. However, you can also mess up by returning any other invalid type.
Will glue eventually expose a trait for the implementation of the roc_fx_
functions so that you get type errors in the platform?
well the alternative is to generate "hidden" glue for the "noerrorresult" (which is just another roc value) and then expose it after wrapping in a normal RocResult
Not sure I follow how that would work in practice. Would you generate a type per Effect function?
roc_fx_
functions should be going away when glue gets more powerful
They will be replaced with tag union, state machine based effects
Richard has talked about the new approach in some previous meetups.
Maybe roc_fx_
functions were not directly mentioned, but they should become redundant like the hosted module and I believe Effect
in general
Also, for the glue gen you want, can you make a dummy main file that just has a return type of the types you want generated. No tasks at all?
Yeah, that’ll probably work as I’m not returning any Result _ []
. Will give it a try tonight!
Thanks
Working on https://github.com/roc-lang/basic-cli/issues/145 I think I ran into a similar issue, basically; how do I regenerate the glue for basic-cli?
roc glue ../roc/crates/glue/src/RustGlue.roc platform/src/ platform/main.roc
outputs an entirely different file structure than the existing one with file_glue.rs, dir_glue.rs, command_glue.rs
mod.rs, aarch64.rs, wasm32.rs
- and the files are not updated. (@Luke Boswell refers to converting it to use RustGlue
here: https://roc.zulipchat.com/#narrow/stream/316715-contributing/topic/basic-cli.20glue/near/397443629)
Glue for basic-cli has basically been manually put together rn. I have a WIP PR to make it so we can regenerate using a script, but I cant remember where I got to with that.
Are you trying to add new features? If so you can make a fake platform and then just include the types you want and glue can generate for those types you need.
This is the PR I'm refrring to https://github.com/roc-lang/basic-cli/pull/135
Luke Boswell said:
Are you trying to add new features? If so you can make a fake platform and then just include the types you want and glue can generate for those types you need.
Yes, I am adding Path.x
methods in this issue https://github.com/roc-lang/basic-cli/issues/145
I've been updating that PR, it looks like it should be all OK to me, but for some reason it is getting stuck in CI creating a directory.
I did update examples/dir.roc
to make it clearer, but I don't see how this change is affecting tests in CI.
I'll check it out
I submitted a PR if any of you would like to dissect further: :smiley: https://github.com/roc-lang/basic-cli/pull/150
This is caused by #5924, everybody seems to be hitting it now, I'm working on it today.
Last updated: Jul 06 2025 at 12:14 UTC