This change also means we must update the interface of `Dict.empty` and
`Set.empty` from
```
Dict.empty : Dict k v
```
to
```
Dict.empty : {} -> Dict k v
```
* Unify parsing of string literals and scalar literals, to (e.g.) ensure escapes are handled uniformly. Notably, this makes unicode escapes valid in scalar literals.
* Add a variety of custom error messages about specific failure cases of parsing string/scalar literals. For example, if we're expecting a string (e.g. a package name in the header) and the user tried using single quotes, give a clear message about that.
* Fix formatting of unicode escapes (they previously used {}, now correctly use () to match roc strings)
This patch provides errors for defs that are used only in
possibly-mutual recursion, and are not reachable outside of their
recursive closures. For example:
```
test_report!(
mutual_recursion_not_reached_nested,
indoc!(
r#"
app "test" provides [main] to "./platform"
main =
f = \{} -> if Bool.true then "" else g {}
g = \{} -> if Bool.true then "" else f {}
""
"#
),
@r###"
── DEFINITIONs ONLY USED IN RECURSION ──────────────────── /code/proj/Main.roc ─
These 2 definitions are only used in mutual recursion with themselves:
4│> f = \{} -> if Bool.true then "" else g {}
5│> g = \{} -> if Bool.true then "" else f {}
If you don't intend to use or export any of them, they should all be
removed!
"###
);
```
Also change some tests with newly relaxed indentation requirements, and remove an irrelevant test (since unindented close parens are now perfectly valid, the test is no longer useful).
As previously discovered with #4464, it's easy to accidentally mis-use the State value returned on the Err path.
There were mixed assumptions about what that State represents: (1) the State where the error occurred, or (2) the State at the beginning of the thing we were just parsing.
I fixed this up to always mean (2) - at which point we don't actually need to return the State at all - so it's impossible for further discrepency to creep in.
I also took the liberty to refactor a few more methods to be purely combinator-based, rather than calling `parse` directly.
My concern with the previous wording is that:
- Beginners will be confused by "these are always open"
- Users advanced enough to understand what that actually means won't benefit from seeing it in this warning message!