Represent "able" variables with slices of abilities

This commit is contained in:
Ayaz Hafiz 2022-10-12 14:52:38 -05:00
parent 0f0678ce73
commit 229548571b
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
10 changed files with 163 additions and 85 deletions

View file

@ -105,7 +105,7 @@ impl OwnedNamedOrAble {
}
}
pub fn opt_abilities(&self) -> Option<&[Symbol]> {
pub fn opt_abilities(&self) -> Option<&VecSet<Symbol>> {
match self {
OwnedNamedOrAble::Named(_) => None,
OwnedNamedOrAble::Able(av) => Some(&av.abilities),
@ -127,6 +127,8 @@ pub struct NamedVariable {
pub struct AbleVariable {
pub variable: Variable,
pub name: Lowercase,
/// Abilities bound to this type variable.
/// INVARIANT: sorted and de-duplicated.
pub abilities: VecSet<Symbol>,
// NB: there may be multiple occurrences of a variable
pub first_seen: Region,
@ -984,6 +986,11 @@ fn canonicalize_has_clause(
let var = var_store.fresh();
let can_abilities = {
let mut vec = can_abilities.into_vec();
vec.sort();
VecSet::from_iter(vec)
};
introduced_variables.insert_able(var_name, Loc::at(region, var), can_abilities);
Ok(())

View file

@ -1044,8 +1044,8 @@ mod test {
use roc_region::all::Loc;
use roc_types::{
subs::{
self, Content, Content::*, Descriptor, FlatType, Mark, OptVariable, Rank, Subs,
SubsIndex, SubsSlice, Variable,
self, Content, Content::*, Descriptor, FlatType, GetSubsSlice, Mark, OptVariable, Rank,
Subs, SubsIndex, SubsSlice, Variable,
},
types::Uls,
};
@ -1107,7 +1107,8 @@ mod test {
let mut subs = Subs::new();
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
let var = new_var(&mut subs, FlexAbleVar(Some(field_name), Symbol::UNDERSCORE));
let abilities = SubsSlice::extend_new(&mut subs.symbol_names, [Symbol::UNDERSCORE]);
let var = new_var(&mut subs, FlexAbleVar(Some(field_name), abilities));
let mut copied = vec![];
@ -1116,8 +1117,9 @@ mod test {
assert_ne!(var, copy);
match subs.get_content_without_compacting(var) {
FlexAbleVar(Some(name), Symbol::UNDERSCORE) => {
FlexAbleVar(Some(name), abilities) => {
assert_eq!(subs[*name].as_str(), "a");
assert_eq!(subs.get_subs_slice(*abilities), [Symbol::UNDERSCORE]);
}
it => unreachable!("{:?}", it),
}
@ -1128,7 +1130,8 @@ mod test {
let mut subs = Subs::new();
let field_name = SubsIndex::push_new(&mut subs.field_names, "a".into());
let var = new_var(&mut subs, RigidAbleVar(field_name, Symbol::UNDERSCORE));
let abilities = SubsSlice::extend_new(&mut subs.symbol_names, [Symbol::UNDERSCORE]);
let var = new_var(&mut subs, RigidAbleVar(field_name, abilities));
let mut copied = vec![];
@ -1136,8 +1139,9 @@ mod test {
assert_ne!(var, copy);
match subs.get_content_without_compacting(var) {
RigidAbleVar(name, Symbol::UNDERSCORE) => {
RigidAbleVar(name, abilities) => {
assert_eq!(subs[*name].as_str(), "a");
assert_eq!(subs.get_subs_slice(*abilities), [Symbol::UNDERSCORE]);
}
it => internal_error!("{:?}", it),
}