Optional record fields can't be used in two different ways
Simple repro, run roc check on this code:
app "helloWorld"
packages { pf: "https://github.com/roc-lang/basic-cli/releases/download/0.7.1/Icc3xJoIixF3hCcfXrDwLCu4wQHtNdPyoJkEbkgIElA.tar.br" }
imports [pf.Stdout]
provides [main] to pf
add : { a : U64, b ? U64 } -> U64
add = \{ a, b ? 1} -> a + b
main =
x = add { a : 7, b: 8 }
y = add { a : 7 }
Stdout.line "$(Num.toStr x),$(Num.toStr y)"
Some reason, we can use add both with/without the optional field as add { a : 7, b: 8 } and add { a : 7 }.
Error message:
── TYPE MISMATCH in examples/helloWorld.roc ────────────────────────────────────
This 1st argument to add has an unexpected type:
11│ y = add { a : 7 }
^^^^^^^^^
The argument is a record of type:
{ … }
But add needs its 1st argument to be:
{ b : Int Unsigned64, … }
Tip: Looks like the b field is missing.
────────────────────────────────────────────────────────────────────────────────
In some cases, omitting optional record fields can also cause a compiler panic. Example can be found here
Panic message example:
thread 'main' panicked at 'Error in alias analysis: error in module ModName("UserApp"), function definition FuncName("\x11\x00\x00\x00\x02\x00\x00\x00\xcbr?\x05\x92\xae\x19\x92"), definition of value binding ValueId(3): expected type '(((), (), ()),)', found type '((),)'', crates/compiler/gen_llvm/src/llvm/build.rs:5761:19
For people looking for a workaround: You can use:
Xml : {
declaration : [Some Str, None],
root : Str,
}
Instead of:
Xml : {
xmlDeclaration ? Str,
root : Str,
}
Another workaround: if you move the definition add into a separate module, then everything works fine.
A couple other reproductions in https://github.com/roc-lang/roc/issues/6101 and https://github.com/roc-lang/roc/issues/5444
5444 has a comment with some investigation: https://github.com/roc-lang/roc/issues/5444#issuecomment-1831507861