This had me scratching my head for a while:
module []
i = Num.toI32 1
# f1 is all fine
f1 = \{ a, b ? "DEFAULT" } -> (a < i, b)
expect f1 { a: 1 } == (Bool.false, "DEFAULT")
expect f1 { a: 1, b: "foo" } == (Bool.false, "foo")
# for f2, the first expect does not compile if the second expect exists
# unless the record parameter is open
f2 : { a : I32, b ? Str } -> (Bool, Str)
f2 = \{ a, b ? "DEFAULT" } -> (a < i, b)
expect f2 { a: 1 } == (Bool.false, "DEFAULT")
expect f2 { a: 1, b: "foo" } == (Bool.false, "foo")
gives:
This 1st argument to f2 has an unexpected type:
17│ expect f2 { a: 1 } == (Bool.false, "DEFAULT")
^^^^^^^^
The argument is a record of type:
{ … }
But f2 needs its 1st argument to be:
{ b : Str, … }
Tip: Looks like the b field is missing.
It works if I change the type to open record f2 : { a : I32, b ? Str }* -> (Bool, Str)
. This was quite surprising to me based on what the tutorial says about default values.
This is a specialization bug in the compiler
...or, it might not technically be specialization, but definitely a compiler bug
I think there is an issue filed for this, but would need to do some searchin
I had a quick look in the issues and nothing seemed to match, but perhaps I don't know what terminology to look for. Anyway, I'm happy to create an issue if that's useful.
Lachlan O'Dea has marked this topic as resolved.
Yeah, please make one. Someone can dedupe if there happens to be another match
https://github.com/roc-lang/roc/issues/6750
Last updated: Jul 06 2025 at 12:14 UTC