How should I report a panic? The following code panicked after I added a couple of tests
module [match_all]
import Template exposing [parse_template]
import Match
match_all :
Str,
Str
-> Result
(Dict Str Str)
[
DoesNotMatch,
TemplateError [
MissingClosingBracket,
InvalidTokenLength Str,
InvalidTokenType Str,
TooManyTokenParts Str
]
]
match_all = |template_str, input_str|
specs =
template_str
|> parse_template
|> Result.map_err(TemplateError)?
input_str
|> Str.to_utf8
|> Match.all_specs(specs)
expect
# that `match_all` returns `Ok` with an empty dict
# when a template is a literal fully matching the input string
template_str = "text"
input_str = "text"
fields = match_all(template_str, input_str)
fields == Ok(Dict.empty({}))
expect
# that `match_all` returns `Ok` with a proper field and value
# when a template with named token matches the input string
template_str = "Three symbols: {result:s:6}."
input_str = "Three symbols: 123Abc."
fields = match_all(template_str, input_str)
fields == Ok(Dict.from_list([("result", "123Abc")]))
Output:
➜ just test
roc test src/main.roc
thread 'main' panicked at crates/compiler/mono/src/borrow.rs:361:34:
internal error: entered unreachable code:
No borrow signature for LambdaName { name: `Match.65`, niche: Niche(Captures([])) } layout.
Tip 1: This can happen when you call a function with fewer arguments than it expects.
Like `Arg.list!` instead of `Arg.list! {}`.
Tip 2: `roc check yourfile.roc` can sometimes give you a helpful error.
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: Recipe `test` failed on line 8 with exit code 101
And it diffidently has something to do with expect
. If I just drop this string top-level in a file everything is fine (apart from a warning regarding unused v
):
v = match_all("text", "text")
But in expect
the same code panics:
expect
v = match_all("text", "text")
Bool.true
If you can make an issue with a single file repro, that would be the most useful.
Also, occasionally adding types or running roc check
can resolve these kinds of issues or point to the root cause
I tried to put everything in one file and remove some code, which doesn't influence the panic, but now I face a Type Mismatch error. I would appreciate some help. Here is the code:
module [Spec, Matcher, all_specs, anything, literal]
Matcher a : List U8 -> Result (List U8) [DoesNotMatch]a
Spec a : {
field_name : [Anonymous, Named Str],
length : U64,
matcher : Matcher a,
}
anything : Matcher a
anything = |input|
Ok(input)
literal : List U8 -> Matcher a
literal = |value|
|input|
if input == value then
Ok(input)
else
Err(DoesNotMatch)
split_input_segment :
List U8,
{ length : U64 }*
-> Result { input_segment : List U8, rest_input : List U8 } [DoesNotMatch]
split_input_segment = |input, { length }|
{ before: input_segment, others: rest_input } = List.split_at(input, length)
if List.len(input_segment) < length then
Err(DoesNotMatch)
else
Ok({ input_segment, rest_input })
## See `all_specs` for the public API.
all_specs_recursive : List U8, List (Spec _), Dict Str Str -> Result (Dict Str Str) [DoesNotMatch]
all_specs_recursive = |input, specs, acc|
when specs is
[] ->
if input == [] then
Ok(acc)
else
Err(DoesNotMatch)
[spec, .. as rest_specs] ->
{ input_segment, rest_input } = split_input_segment(input, spec)?
# Even thought `field_value` is not always used,
# it's important to call `spec.matcher?` here
field_value =
input_segment
|> spec.matcher?
|> Str.from_utf8_lossy
all_specs_recursive(
rest_input,
rest_specs,
when spec.field_name is
Named(name) -> Dict.insert(acc, name, field_value)
Anonymous -> acc,
)
all_specs : List U8, List (Spec _) -> Result (Dict Str Str) [DoesNotMatch]
all_specs = |input, specs|
all_specs_recursive(input, specs, Dict.empty({}))
expect
actual = all_specs(
['B', 'u', 'z', 'z', 'F', 'u', 'z', 'z'],
[
{
field_name: Named("field1"),
length: 4,
matcher: literal(['B', 'u', 'z', 'z']),
},
],
)
actual == Ok(Dict.from_list([("field1", "Buzz"), ("field2", "Fuzz")]))
match_all :
Str,
Str
-> Result
(Dict Str Str)
[
DoesNotMatch,
TemplateError [
MissingClosingBracket,
InvalidTokenLength Str,
InvalidTokenType Str,
TooManyTokenParts Str,
],
]
match_all = |template_str, input_str|
# specs =
# template_str
# |> parse_template
# |> Result.map_err(TemplateError)?
specs = [
{
field_name: Named("field1"),
length: 10,
matcher: anything,
},
]
input_str
|> Str.to_utf8
|> all_specs(specs)
expect
# that `match_all` returns `Ok` with an empty dict
# when a template is a literal fully matching the input string
template_str = "text"
input_str = "text"
fields = match_all(template_str, input_str)
fields == Ok(Dict.empty({}))
The error is
── TYPE MISMATCH in ./Match.roc ────────────────────────────────────────────────
Something is off with the body of the match_all definition:
80│ Str,
81│ Str
82│ -> Result
83│ (Dict Str Str)
84│ [
85│ DoesNotMatch,
86│ TemplateError [
87│ MissingClosingBracket,
88│ InvalidTokenLength Str,
89│ InvalidTokenType Str,
90│ TooManyTokenParts Str,
91│ ],
92│ ]
93│ match_all = |template_str, input_str|
94│ # specs =
95│ # template_str
96│ # |> parse_template
97│ # |> Result.map_err(TemplateError)?
98│ specs = [{
99│ field_name: Named("field1"),
100│ length: 10,
101│ matcher: anything,
102│ }]
103│
104│> input_str
105│> |> Str.to_utf8
106│> |> all_specs(specs)
This all_specs call produces:
Result (Dict Str Str) […]a
But the type annotation on match_all says it should be:
Result (Dict Str Str) [TemplateError [
InvalidTokenLength Str,
InvalidTokenType Str,
MissingClosingBracket,
TooManyTokenParts Str,
], …]
Interesting enough if the match_all
function definition is in its own module, no type mismatch is raised.
If it is a different file, maybe it panics before getting to the type mismatch? Anyway, will take a look later today or tomorrow morning when I have more time.
Brendan Hansknecht said:
If it is a different file, maybe it panics before getting to the type mismatch?
I don’t think so. The compiler panics only if I call match_all
in an expect block. As a top-level call it works. Plus My editor (and roc check
) doesn’t complain when match_all
in a different file, but it does otherwise. I think it’s two different problems.
I think it's the fact that your type annotation says it returns TemplateError OR DoNotMatch, but the code that returns TemplateError is commented out. So it will only return DoNotMatch
Maybe @Anthony Bullard is right. The type mismatch doesn't happen if I remove TemplateError
. I'm still confused, by the fact it happens only if match_all
in the same file. Anyway it has not much to do with the panic itself. I created a ticket for the compiler panic with some details in link to this thread: https://github.com/roc-lang/roc/issues/7754.
At the end of the day the Rust version of the compiler just had too many panics
And not enough of them were At the Disco :drum:
(I'll see myself out :grinning_face_with_smiling_eyes:)
Last updated: Jul 06 2025 at 12:14 UTC