I was hoping to add nested datatypes into the language, but it turns out
doing so is quite tricky and not all that useful with Roc's current
compilation model. Basically every implementation strategy I could think
of ended up requiring a uniform representation for the data layout
(or some ugly workaround). Furhermore it increased the complexity of the
checker/mono IR generator a little bit - basically, we must always pass
around the alias definitions of nested datatypes and instantiate them
at usage sites, rather than being able to unroll aliases as we currently
do during canonicalization.
So, especially because we don't support polymorphic recursion anyway, I
think it may be better to simply disallow any kind of nested datatypes
in the language. In any case, Stephanie Weirich [seems to think nested
datatypes are not needed](https://www.cis.upenn.edu/~plclub/blog/2020-12-04-nested-datatypes/).
Closes#2293
By emitting a runtime error rather than panicking when we can't layout
a record, we help programs like
```
main =
get = \{a} -> a
get {b: "hello world"}
```
execute as
```
Mismatch in compiler/unify/src/unify.rs Line 1071 Column 13
Trying to unify two flat types that are incompatible: EmptyRecord ~ { 'a' : Demanded(122), }<130>
🔨 Rebuilding host...
── TYPE MISMATCH ───────────────────────────────────────────────────────────────
The 1st argument to get is not what I expect:
8│ get {b: "hello world"}
^^^^^^^^^^^^^^^^^^
This argument is a record of type:
{ b : Str }
But get needs the 1st argument to be:
{ a : a }b
Tip: Seems like a record field typo. Maybe a should be b?
Tip: Can more type annotations be added? Type annotations always help
me give more specific messages, and I think they could help a lot in
this case
────────────────────────────────────────────────────────────────────────────────
'+fast-variable-shuffle' is not a recognized feature for this target (ignoring feature)
'+fast-variable-shuffle' is not a recognized feature for this target (ignoring feature)
Done!
Application crashed with message
Can't create record with improper layout
Shutting down
```
rather than the hanging
```
Mismatch in compiler/unify/src/unify.rs Line 1071 Column 13
Trying to unify two flat types that are incompatible: EmptyRecord ~ { 'a' : Demanded(122), }<130>
thread '<unnamed>' panicked at 'invalid layout from var: UnresolvedTypeVar(104)', compiler/mono/s
rc/layout.rs:1510:52
```
that was previously produced.
Part of #2227
This reverts commit 6e4fd5f06a1ae6138659b0073b4e2b375a499588.
This idea didn't work out because cloning the type and storing it on a
variable still resulted in the solver trying to uify the variable with
the type. When there were errors, which there certainly would be if we
tried to unify the variable with a structure that had nested flex/rigid
vars, the nested flex/rigid vars would inherit those errors, and the
program wouldn't typecheck.
Since the motivation here was to expose the signature type to
`reporting` so that we could modify it with suggestions, we should
instead pass that information along in something analogous to the
`Expected` struct.
There is still a potential for conflicts here, because we don't look at
type variables introduced _prior_ to this annotation. However, this
should be okay in most cases.
To provide better error messages and suggestions related to changing
type annotations, we now pass annotation type signatures all the way
down through the constraint solver. At constraint generation we
associate the type signature with a unique variable, and during error
reporting, we pull out an `ErrorType` corresponding to the original type
signature, by looking up the unique variable. This gives us two nice
things:
1. It means we don't have to pass the original, AST-like type
annotation, which can be quite large, to everyone who looks at an
expectation.
2. It gives us a translation from a `Type` to an `ErrorType` for free
using the existing translation procedure in `roc_types::subs`,
without having to create a new translation function.
This makes it easier for error reporting to find the relevant
annotations that were part of a type error, and display that in the
error message presented to a user.