Is there any reason someone can think of why this line inside of the expr_to_pattern_help
function in parse/src/expr.rs could not or should not be implemented?
Expr::SpaceBefore(..) | Expr::SpaceAfter(..) | Expr::ParensAround(..) => unreachable!(),
Seems easy enough to translate into a pattern, but I want to make sure there isn't an invariant that I'm missing
I ask because this is often hit in the fuzzer and it causes a panic
I see why now.
For now, I'm going to wrap the fuzz_module function in a std::panic::catch_unwind so that it doesn't blow up on parse errors
Ok, that doesn't seem to be helping. But it seems like, as Joshua warned me, the problem is trying to extract spaces when there is a SpacesBefore inside a SpacesBefore or a SpacesAfter inside a SpacesAfter....
It seems to me that to do that would require the ExtractSpaces trait's extract_spaces
method to also take an arena as an arg.
So that they can be merged
Alright, I have this compiling. This is either my best idea, or the worst idea. Got rid of several todo!()
s though
Running the fuzzer
Does this make sense to anyone:
* * * Source code before formatting:
dbg(2ii/fi&fh
)
i
* * * Source code after formatting:
dbg 2ii / fi &fh
i
* * * AST before formatting:
Expr(
@0-15 SpaceAfter(
DbgStmt {
first: @4-13 SpaceAfter(
BinOps(
[
(
@4-7 Num(
"2ii",
),
@7-8 Slash,
),
],
@8-13 Apply(
@8-10 Var {
module_name: "",
ident: "fi",
},
[
@10-13 RecordUpdater(
"fh",
),
],
Space,
),
),
[
Newline,
],
),
extra_args: [],
continuation: @17-18 SpaceBefore(
Var {
module_name: "",
ident: "i",
},
[
Newline,
Newline,
],
),
},
[
Newline,
],
),
)
* * * AST after formatting:
Expr(
@0-19 Defs(
Defs {
tags: [
EitherIndex(2147483648),
],
regions: [
@0-16,
],
space_before: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
space_after: [
Slice<roc_parse::ast::CommentOrNewline> { start: 0, length: 0 },
],
spaces: [],
type_defs: [],
value_defs: [
Stmt(
@0-16 BinOps(
[
(
@0-7 Apply(
@0-3 Dbg,
[
@4-7 Num(
"2ii",
),
],
Space,
),
@8-9 Slash,
),
],
@10-16 Apply(
@10-12 Var {
module_name: "",
ident: "fi",
},
[
@13-16 RecordUpdater(
"fh",
),
],
Space,
),
),
),
],
},
@18-19 SpaceBefore(
Var {
module_name: "",
ident: "i",
},
[
Newline,
Newline,
],
),
),
)
I don't think I understand what a dbg statement continuation is
it's the rest of the program after the dbg
. for example
dbg(x)
1 + 2
1 + 2
is the continuation
Sure....why is that not just a separate expression?
is the AST not structured as nested expressions
it used to be, at least
It is, but I don't understand why a debug would contain a continuation....
I would think the grammar for a Dbg expression would be "dbg" <Expr>
I get it
because you need something to indicate what the rest of the expression after the debug is. So it's like dbg <Expr> <Expr>
. otherwise you would need a list as you mention but a nice property of nesting the next expression is that you can get the type of the whole expression just by looking at one node.
We don't have a separate Statement type. So something that is a statement needs to have a continuation that has the rest of the function
The problem here is we didn't print the parens around the binop when we formatted
So now it thinks we are applying dbg
to the number 2ii
and then that is the left-hand side of the binop
And that's because the original parse didn't capture the ParensAround
Let me know if that sounds correct to you @Ayaz Hafiz and thanks for talking sense into me
FIgured it out
One last issue and this should fix the last major fuzzer issue with PNC
I've made a few fixes for PNC issues locally (didn't notice this thread until after I them!)
Pushed a few of those here: https://github.com/roc-lang/roc/pull/7468
Anyway, one thing that I think can't be preserved in the current AST is comments in an empty PNC apply, e.g.:
foo(
#comment
)
I think this will require using a different variant for PncApply in the AST, something like:
PncApply(&'a Expr<'a>, Collection<'a, &'a Expr<'a>>),
Well the args use the collection helper so wouldn’t this apply to empty collections too?
Oh use the collection type instead of a slice?
That would be helpful
Yeah, collections explicitly keep trailing comments
Couldn’t we just move apply to use collection
Since WS apply is going away?
That adds a bunch of complexity to the ws apply case
That’s the exact issue I was trying to fix later
I would rather just have a new Expr variant for Pnc, and eventually delete the old WS one
Ok. That’s a bigger refactor than I’m willing to do for this PR
Especially after my extract spaces refactor
Which PR are you talking about?
The one I’m working on
Ah got it, not submitted yet
Not yet. I’m at the museum with my kids, but I’ll be able to push up what I got in a couple of hours
You’ll either love me or hate me for it
Nah no hating here :)
Read the above for context. Just made extract spaces take an arena so I could merge spaces recursively from SpacesBefore/SpacesAfter nodes
And get rid of six todos in source. Probably 16 after macro expansion
Great!
I think that probably resolves one of the panics I was looking at
I'm going to pull back the PNC-related fuzzing fixes I had in the PR I linked, to avoid conflicting with you
Thank you!
Joshua Warner said:
Anyway, one thing that I think can't be preserved in the current AST is comments in an empty PNC apply, e.g.:
foo( #comment )
I think this will require using a different variant for PncApply in the AST, something like:
PncApply(&'a Expr<'a>, Collection<'a, &'a Expr<'a>>),
I'm going to start on this tonight if you haven't
Go for it!
I am in a horrible back and forth where I have all of the tests passing, and then exceptions gone, but the fuzzer still fails relatively quickly
The latest thing is dbg
followed immediately by parens
Suggestion: the fuzzer is really useful for making sure we have coherent coverage for our syntax when it's stable, but is blocking us from progressing when we're making tons of syntax changes
Can we disable it until after PNC + ||
args and all are merged?
That's true
Not remove it, just comment it out in the CI
Here's an example that fails:
(L5(L5
0)
(
5)
(L5
0)
e
0)
dbg(L22
0)
Because we now have two separate nodes for Whitespace Apply and PNC apply
Up to you guys, but often I find it a mistake to disable fuzzers temporarily. Turning them back on is a huge pain and often never happens.
The fuzzer is catching real bugs in the new syntax. Even if they are ridiculous bugs.
As long as there is a definite plan of when work will be put in to re-enable it, I think it could be reasonable to disable temporarily. Especially if after removing old syntax it will be easier to fix.
I just don't want Anthony Bullard to put his computer in the garbage disposal one piece at a time
I'm avoiding touching parsing right now because it's no fun at the moment
Here's another beaut:
(L5(L5
0)
(
0)
(L5
0)
e
0)
dbg(L(
L5
0)
+
0asebg,L(
5is
if1)
e
0)
(21
0)
@Joshua Warner
@Anton already disabled it I thought?
I thought Josh was standing by with some fuzzer fixes until Anthony lands his change
I think we just ignore the fuzzer for now... if @Joshua Warner is ok with that. We can follow up with fixes in a separate PR
And by we I am thinking Josh... he seems to fix these bugs faster than I can find them (and I'm just running an automated tool)
As Brendan said, if we have a concrete plan to disable the fuzzer and how we can improve the parsing impl such that re-enabling the fuzzer puts us in a better spot, I think disabling it is good
If we have folks actively working on this (and we do!), I think temporarily disabling in CI is fine
But yes, if we just disable in indefinitely, that's a recipe for dead code
(L5(L5 0)(0)(L5 0)e 0)
dbg (L(L5 0) + 0asebg, L(5is ifl) e 0)
(21 0)
We should minimize these examples
I do
Hmm they don’t look very minimal?
What tool are you using to minimize?
I just ran cargo run --bin minimize expr
on the above and concur with Anthony... this is "minimal" according to our tool
Interesting
Here's this minimization
dbg()
:rofl::rofl::rofl::rofl::rofl::rofl::rofl::rofl::rofl::rofl::rofl::rofl::rofl::rofl:
Oh yeah that looks more minimal!
I have a fix for that one locally
Care to share?
So i can get past this?
I was thinking of returning a Malformed if the args were empty
I think this commit has the fix I made for that: https://github.com/roc-lang/roc/commit/8f48ced87974ff4b6b4a9fd703b437ac27ef8943
Ok, this isn't really compatible with the changes I've made
FWIW I eventually want to get rid of DbgStmt as a separate node (i.e. so this is just an apply in the syntax tree), so I would rather not go down the road of making a special Malformed node for this
Interesting; what incompatibilities are there?
I got rid of the ParensAndCommas CalledVia variant
I really dislike DbgStmt
Ayaz seemed to disagree with me about it
Yeah it's caused a bunch of trouble with making the formatter consistent
I just wish it was just collapsed into the Dbg Expr node
And have that just be a tuple variant that takes the Expr to be inspected
Anyway, I agree this commit will have conflicts with your PncApply refactor, but I think it should be possible to adapt
So should I just push it up with all the tests passing and go from there
This has been the most harrrowing PR I've done on this project
I don't quite follow?
Should I push my current PR?
Get it merged, and then get yours in after revving
Oh yeah sharing early+often sounds valuable
Don't have to fix everything all at once
Yeah, I was just trying to see if this approach was going to solve any problems
And it did fix the "final comments" issue with PNC
I think that's the primary and possibly only thing this fixes
One thing that will make you happy is that I did split a fmt_pnc_apply from fmt_apply
It was so much simpler since I could use the format_expr_collection
Oh thanks for that
Nice!
Yeah fmt_apply goes back to the way it was before PNC
I was running into issues formatting abilities that such a change would have solved
Sorry for all the dust
NP!
Thanks for helping out here!
I don't give a hoot, you're doing the hard work
Glad to see PNC live!
Collection and all the utilities around it are very nice
Threading the last arg after
and the final_comments together consistently made me so mad - solved problem with collection
@Joshua Warner https://github.com/roc-lang/roc/pull/7480
Nice; left a few review comments. Most (maybe all?) are things that can be fixed up in follow-up PRs.
I'm not too worried about this stuff going stale / not being actioned, so I'm generally fine either way.
There are a bunch of different changes we have out-standing right now and keeping the momentum feels important - so maybe bias towards action now?
You will have to fix those conflicts tho :/
(LMK if I can help with that!)
Anthony Bullard said:
Anton already disabled it I thought?
Yeah, to give some context; it was failing the ubuntu_x86_64.yml workflow very often, but you can never be sure that nothing else failed so you need to check every time. Also, the ubuntu_x86_64.yml is a required workflow so basically all PRs needed to be force merged. I think the fuzzer should be moved to a new standalone workflow that is not required to pass. So it can inform us but does not require a force merge by an admin.
I saw that and thought it was a good idea.. but wasn't sure how to implement it.
https://github.com/actions/runner/issues/2347
There's an issue to allow CI actions to fail and not block merging, but GH doesn't want to implement it, apparently
So we can probably just do run_fuzzer || true
in the shell command in the GH action definition
I'll take care of it, there's a way around it, you still get the red x but it's fine to merge
Awesome!
That's perfect
Anton said:
I'll take care of it, there's a way around it, you still get the red x but it's fine to merge
Last updated: Jul 06 2025 at 12:14 UTC