mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-01 15:51:12 +00:00
Fix generated type var order
This commit is contained in:
parent
47fdedc63e
commit
036a72e6e5
3 changed files with 56 additions and 12 deletions
|
@ -1,3 +1,4 @@
|
|||
use collections::MutMap;
|
||||
use subs::{Content, FlatType, Subs, Variable};
|
||||
use types;
|
||||
|
||||
|
@ -26,25 +27,52 @@ enum Parens {
|
|||
Unnecessary,
|
||||
}
|
||||
|
||||
/// How many times a root variable appeared in Subs.
|
||||
///
|
||||
/// We only care about whether it was a single time or multiple times,
|
||||
/// because single appearances get a wildcard (*) and multiple times
|
||||
/// get a generated letter ("a" etc).
|
||||
enum Appearances {
|
||||
Single,
|
||||
Multiple,
|
||||
}
|
||||
|
||||
/// Generate names for all type variables, replacing FlexVar(None) with
|
||||
/// FlexVar(Some(name)) where appropriate. Example: for the identity
|
||||
/// function, generate a name of "a" for both its argument and return
|
||||
/// type variables.
|
||||
pub fn name_all_type_vars(letters_used: u32, variable: Variable, subs: &mut Subs) -> u32 {
|
||||
///
|
||||
/// It's important that we track insertion order, which is why
|
||||
/// names_needed is a Vec. We also want to count how many times a root
|
||||
/// appears, because we should only generate a name for it if it appears
|
||||
/// more than once.
|
||||
fn find_names_needed(
|
||||
variable: Variable,
|
||||
subs: &mut Subs,
|
||||
roots: &mut Vec<Variable>,
|
||||
root_appearances: &mut MutMap<Variable, Appearances>,
|
||||
) {
|
||||
use subs::Content::*;
|
||||
use subs::FlatType::*;
|
||||
|
||||
let mut letters_used = letters_used;
|
||||
|
||||
match subs.get(variable).content {
|
||||
FlexVar(None) => {
|
||||
let root = subs.get_root_key(variable);
|
||||
|
||||
// If this var is *not* its own root, then the
|
||||
// root var necessarily appears in multiple places.
|
||||
// Generate a name for it!
|
||||
if variable != root {
|
||||
letters_used = name_root(letters_used, root, subs);
|
||||
// We need a name for it!
|
||||
match root_appearances.get(&root) {
|
||||
Some(Appearances::Single) => {
|
||||
root_appearances.insert(root, Appearances::Multiple);
|
||||
}
|
||||
Some(Appearances::Multiple) => {
|
||||
// It's already multiple, so do nothing!
|
||||
}
|
||||
None => {
|
||||
roots.push(root);
|
||||
root_appearances.insert(root, Appearances::Single);
|
||||
}
|
||||
}
|
||||
}
|
||||
FlexVar(Some(_)) => {
|
||||
|
@ -56,20 +84,36 @@ pub fn name_all_type_vars(letters_used: u32, variable: Variable, subs: &mut Subs
|
|||
args,
|
||||
}) => {
|
||||
for var in args {
|
||||
letters_used = name_all_type_vars(letters_used, var, subs);
|
||||
find_names_needed(var, subs, roots, root_appearances);
|
||||
}
|
||||
}
|
||||
Structure(Func(arg_vars, ret_var)) => {
|
||||
for var in arg_vars {
|
||||
letters_used = name_all_type_vars(letters_used, var, subs);
|
||||
find_names_needed(var, subs, roots, root_appearances);
|
||||
}
|
||||
|
||||
letters_used = name_all_type_vars(letters_used, ret_var, subs);
|
||||
find_names_needed(ret_var, subs, roots, root_appearances);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
letters_used
|
||||
pub fn name_all_type_vars(variable: Variable, subs: &mut Subs) {
|
||||
let mut roots = Vec::new();
|
||||
let mut letters_used = 0;
|
||||
let mut appearances = MutMap::default();
|
||||
|
||||
// Populate names_needed
|
||||
find_names_needed(variable, subs, &mut roots, &mut appearances);
|
||||
|
||||
for root in roots {
|
||||
match appearances.get(&root) {
|
||||
Some(Appearances::Multiple) => {
|
||||
letters_used = name_root(letters_used, root, subs);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn name_root(letters_used: u32, root: Variable, subs: &mut Subs) -> u32 {
|
||||
|
|
|
@ -8,7 +8,7 @@ pub struct Subs {
|
|||
utable: UnificationTable<InPlace<Variable>>,
|
||||
}
|
||||
|
||||
#[derive(Copy, PartialEq, Eq, Clone)]
|
||||
#[derive(Copy, PartialEq, Eq, Clone, Hash)]
|
||||
pub struct Variable(u32);
|
||||
|
||||
impl Variable {
|
||||
|
|
|
@ -21,7 +21,7 @@ mod test_infer {
|
|||
|
||||
let content = infer_expr(&mut subs, procedures, &output.constraint, variable);
|
||||
|
||||
name_all_type_vars(0, variable, &mut subs);
|
||||
name_all_type_vars(variable, &mut subs);
|
||||
|
||||
let actual_str = content_to_string(content, &mut subs);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue