mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-03 16:44:33 +00:00
Deep copy var
This commit is contained in:
parent
94cc22f9ca
commit
aa24cdbef3
2 changed files with 91 additions and 3 deletions
31
src/solve.rs
31
src/solve.rs
|
@ -120,7 +120,23 @@ fn solve(
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let actual = var;
|
// Deep copy the vars associated with this symbol before unifying them.
|
||||||
|
// Otherwise, suppose we have this:
|
||||||
|
//
|
||||||
|
// identity = \a -> a
|
||||||
|
//
|
||||||
|
// x = identity 5
|
||||||
|
//
|
||||||
|
// When we call (identity 5), it's important that we not unify
|
||||||
|
// on identity's original vars. If we do, the type of `identity` will be
|
||||||
|
// mutated to be `Int -> Int` instead of `a -> `, which would be incorrect;
|
||||||
|
// the type of `identity` is more general than that!
|
||||||
|
//
|
||||||
|
// Instead, we want to unify on a *copy* of its vars. If the copy unifies
|
||||||
|
// successfully (in this case, to `Int -> Int`), we can use that to
|
||||||
|
// infer the type of this lookup (in this case, `Int`) without ever
|
||||||
|
// having mutated the original.
|
||||||
|
let actual = deep_copy_var(subs, rank, pools, var);
|
||||||
let expected = type_to_var(subs, rank, pools, expected_type.clone().get_type());
|
let expected = type_to_var(subs, rank, pools, expected_type.clone().get_type());
|
||||||
|
|
||||||
// TODO use region when reporting a problem
|
// TODO use region when reporting a problem
|
||||||
|
@ -501,9 +517,18 @@ fn pool_to_rank_table(
|
||||||
|
|
||||||
// Sort the variables into buckets by rank.
|
// Sort the variables into buckets by rank.
|
||||||
for &var in young_vars.iter() {
|
for &var in young_vars.iter() {
|
||||||
let rank = subs.get(var).rank;
|
let desc = subs.get(var);
|
||||||
|
let rank = desc.rank;
|
||||||
|
|
||||||
subs.set_mark(var, young_mark);
|
subs.set(
|
||||||
|
var,
|
||||||
|
Descriptor {
|
||||||
|
rank,
|
||||||
|
mark: young_mark,
|
||||||
|
content: desc.content,
|
||||||
|
copy: desc.copy,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
pools.get_mut(rank).push(var);
|
pools.get_mut(rank).push(var);
|
||||||
}
|
}
|
||||||
|
|
63
src/subs.rs
63
src/subs.rs
|
@ -239,6 +239,26 @@ impl Subs {
|
||||||
|
|
||||||
var_to_err_type(self, &mut state, var)
|
var_to_err_type(self, &mut state, var)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn restore(&mut self, var: Variable) {
|
||||||
|
let desc = self.get(var);
|
||||||
|
|
||||||
|
if desc.copy.is_some() {
|
||||||
|
let content = desc.content;
|
||||||
|
|
||||||
|
self.set(
|
||||||
|
var,
|
||||||
|
Descriptor {
|
||||||
|
content: content.clone(),
|
||||||
|
rank: Rank::none(),
|
||||||
|
mark: Mark::none(),
|
||||||
|
copy: None,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
restore_content(self, &content);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
@ -644,3 +664,46 @@ fn get_fresh_var_name(state: &mut NameState) -> Lowercase {
|
||||||
|
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn restore_content(subs: &mut Subs, content: &Content) {
|
||||||
|
use crate::subs::Content::*;
|
||||||
|
use crate::subs::FlatType::*;
|
||||||
|
|
||||||
|
match content {
|
||||||
|
FlexVar(_) | RigidVar(_) | Error(_) => (),
|
||||||
|
|
||||||
|
Structure(flat_type) => match flat_type {
|
||||||
|
Apply { args, .. } => {
|
||||||
|
for &var in args {
|
||||||
|
subs.restore(var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Func(arg_vars, ret_var) => {
|
||||||
|
for &var in arg_vars {
|
||||||
|
subs.restore(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
subs.restore(*ret_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
EmptyRecord => (),
|
||||||
|
|
||||||
|
Record(fields, ext_var) => {
|
||||||
|
for (_, var) in fields {
|
||||||
|
subs.restore(*var);
|
||||||
|
}
|
||||||
|
|
||||||
|
subs.restore(*ext_var);
|
||||||
|
}
|
||||||
|
Erroneous(_) => (),
|
||||||
|
},
|
||||||
|
Alias(_, _, args, var) => {
|
||||||
|
for (_, arg_var) in args {
|
||||||
|
subs.restore(*arg_var);
|
||||||
|
}
|
||||||
|
|
||||||
|
subs.restore(*var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue