Allow naming type variables with a basis hint

I think this makes it easier to read type variables when they come from
flex/rigid vars with pre-existing names, just give them a number suffix
to differentiate them.
This commit is contained in:
Ayaz Hafiz 2022-07-29 15:32:44 -04:00
parent 27927590cb
commit 02d5d0ec92
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
3 changed files with 55 additions and 8 deletions

View file

@ -2,7 +2,7 @@ use crate::subs::{
self, AliasVariables, Content, FlatType, GetSubsSlice, Label, Subs, SubsIndex, UnionLabels,
UnionTags, UnsortedUnionLabels, Variable,
};
use crate::types::{name_type_var, RecordField, Uls};
use crate::types::{name_type_var, name_type_var_with_hint, RecordField, Uls};
use roc_collections::all::MutMap;
use roc_module::ident::{Lowercase, TagName};
use roc_module::symbol::{Interns, ModuleId, Symbol};
@ -455,10 +455,34 @@ fn name_root(
subs: &mut Subs,
taken: &mut MutMap<Lowercase, Variable>,
) -> u32 {
let (generated_name, new_letters_used) =
name_type_var(letters_used, &mut taken.keys(), |var, str| {
let (generated_name, new_letters_used) = match subs.get_content_unchecked(root) {
Content::FlexVar(Some(name))
| Content::RigidVar(name)
| Content::FlexAbleVar(Some(name), _)
| Content::RigidAbleVar(name, _)
| Content::RecursionVar {
opt_name: Some(name),
..
} => {
let name_hint = &subs[*name];
if name_hint.as_str() == "*" {
// Give a proper name to named wildcards!
name_type_var(letters_used, &mut taken.keys(), |var, str| {
var.as_str() == str
})
} else {
let generated =
name_type_var_with_hint(name_hint.as_str(), &mut taken.keys(), |var, str| {
var.as_str() == str
});
(generated, letters_used)
}
}
_ => name_type_var(letters_used, &mut taken.keys(), |var, str| {
var.as_str() == str
});
}),
};
taken.insert(generated_name.clone(), root);

View file

@ -2566,6 +2566,7 @@ fn write_type_ext(ext: TypeExt, buf: &mut String) {
static THE_LETTER_A: u32 = 'a' as u32;
/// Generates a fresh type variable name, composed of lowercase alphabetic characters in sequence.
pub fn name_type_var<I, F: FnMut(&I, &str) -> bool>(
letters_used: u32,
taken: &mut impl Iterator<Item = I>,
@ -2596,6 +2597,28 @@ pub fn name_type_var<I, F: FnMut(&I, &str) -> bool>(
}
}
/// Generates a fresh type variable name given a hint, composed of the hint as a prefix and a
/// number as a suffix. For example, given hint `a` we'll name the variable `a`, `a1`, or `a27`.
pub fn name_type_var_with_hint<I, F: FnMut(&I, &str) -> bool>(
hint: &str,
taken: &mut impl Iterator<Item = I>,
mut predicate: F,
) -> Lowercase {
if !taken.any(|item| predicate(&item, hint)) {
return hint.into();
}
let mut i = 0;
loop {
i += 1;
let cand = format!("{}{}", hint, i);
if !taken.any(|item| predicate(&item, &cand)) {
return cand.into();
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct RecordFieldsError;