Obligation checking layers on extra abilities bound to a variable

This commit is contained in:
Ayaz Hafiz 2022-10-12 16:03:24 -05:00
parent db7fe48d1c
commit 9c88534758
No known key found for this signature in database
GPG Key ID: 0E2A37416A25EF58
2 changed files with 14 additions and 21 deletions

View File

@ -494,19 +494,6 @@ trait DerivableVisitor {
false
}
#[inline(always)]
fn visit_flex_able(var: Variable, abilities: &[Symbol]) -> Result<(), NotDerivable> {
// TODO(multi-abilities) flex-able can inherit other abilities
if abilities != [Self::ABILITY] {
Err(NotDerivable {
var,
context: NotDerivableContext::NoContext,
})
} else {
Ok(())
}
}
#[inline(always)]
fn visit_rigid_able(var: Variable, abilities: &[Symbol]) -> Result<(), NotDerivable> {
if abilities != [Self::ABILITY] {
@ -647,8 +634,14 @@ trait DerivableVisitor {
context: NotDerivableContext::NoContext,
})
}
FlexAbleVar(_, abilities) => {
Self::visit_flex_able(var, subs.get_subs_slice(abilities))?
FlexAbleVar(opt_name, abilities) => {
// This flex var inherits the ability.
let merged_abilites = roc_unify::unify::merged_ability_slices(
subs,
abilities,
Self::ABILITY_SLICE,
);
subs.set_content(var, Content::FlexAbleVar(opt_name, merged_abilites));
}
RigidAbleVar(_, abilities) => {
Self::visit_rigid_able(var, subs.get_subs_slice(abilities))?

View File

@ -3008,14 +3008,14 @@ fn is_sorted_dedup<T: Ord>(l: &[T]) -> bool {
}
#[inline(always)]
fn merged_ability_slices(
env: &mut Env,
pub fn merged_ability_slices(
subs: &mut Subs,
left_slice: SubsSlice<Symbol>,
right_slice: SubsSlice<Symbol>,
) -> SubsSlice<Symbol> {
// INVARIANT: abilities slices are inserted sorted into subs
let left = env.subs.get_subs_slice(left_slice);
let right = env.subs.get_subs_slice(right_slice);
let left = subs.get_subs_slice(left_slice);
let right = subs.get_subs_slice(right_slice);
debug_assert!(is_sorted_dedup(left));
debug_assert!(is_sorted_dedup(right));
@ -3031,7 +3031,7 @@ fn merged_ability_slices(
let merged = merge_sorted_keys(left.iter().copied(), right.iter().copied());
// TODO: check if there's an existing run in subs rather than re-inserting
SubsSlice::extend_new(&mut env.subs.symbol_names, merged)
SubsSlice::extend_new(&mut subs.symbol_names, merged)
}
#[inline(always)]
@ -3055,7 +3055,7 @@ fn unify_flex_able<M: MetaCollector>(
let opt_name = (opt_other_name).or(*opt_name);
let merged_abilities =
merged_ability_slices(env, abilities_slice, *other_abilities_slice);
merged_ability_slices(env.subs, abilities_slice, *other_abilities_slice);
merge(env, ctx, FlexAbleVar(opt_name, merged_abilities))
}