Make sure records don't de-generalize function types, fixing ability let-generalization

Closes #3641
This commit is contained in:
Ayaz Hafiz 2022-07-26 13:08:07 -04:00
parent ce8c8f7264
commit f145f29b1b
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
2 changed files with 11 additions and 16 deletions

View file

@ -3141,9 +3141,17 @@ fn adjust_rank_content(
EmptyRecord => {
// from elm-compiler: THEORY: an empty record never needs to get generalized
Rank::toplevel()
//
// But for us, that theory does not hold, because there might be type variables hidden
// inside a lambda set but not on the left or right of an arrow, and records should not
// force de-generalization in such cases.
//
// See https://github.com/rtfeldman/roc/issues/3641 for a longer discussion and
// example.
group_rank
}
// THEORY: an empty tag never needs to get generalized
EmptyTagUnion => Rank::toplevel(),
Record(fields, ext_var) => {

View file

@ -7255,24 +7255,11 @@ mod solve_expr {
# ^
"#
),
// TODO SERIOUS: Let generalization is broken here, and this is NOT correct!!
// Two problems:
// - 1. `{}` always has its rank adjusted to the toplevel, which forces the rest
// of the type to the toplevel, but that is NOT correct here!
// - 2. During solving lambda set compaction cannot happen until an entire module
// is solved, which forces resolved-but-not-yet-compacted lambdas in
// unspecialized lambda sets to pull the rank into a lower, non-generalized
// rank. Special-casing for that is a TERRIBLE HACK that interferes very
// poorly with (1)
//
// We are BLOCKED on https://github.com/rtfeldman/roc/issues/3207 to make this work
// correctly!
// See also https://github.com/rtfeldman/roc/pull/3175, a separate, but similar problem.
@r###"
Fo#f(7) : Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) | b has G
Go#g(8) : Go -[[g(8)]]-> {}
h : Go -[[g(8)]]-> {}
Fo#f(7) : Fo -[[f(7)]]-> (Go -[[g(8)]]-> {})
h : b -[[] + b:g(4):1]-> {} | b has G
Fo#f(7) : Fo -[[f(7)]]-> (b -[[] + b:g(4):1]-> {}) | b has G
h : Go -[[g(8)]]-> {}
"###
);