mirror of
https://github.com/roc-lang/roc.git
synced 2025-10-02 08:11:12 +00:00
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:
parent
27927590cb
commit
02d5d0ec92
3 changed files with 55 additions and 8 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue