mirror of
https://github.com/roc-lang/roc.git
synced 2025-09-26 13:29:12 +00:00
Canonicalize multiple abilities bound to a type variable
This commit is contained in:
parent
97dbac1631
commit
6bb97c92b9
9 changed files with 84 additions and 77 deletions
|
@ -105,10 +105,10 @@ impl OwnedNamedOrAble {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn opt_ability(&self) -> Option<Symbol> {
|
||||
pub fn opt_abilities(&self) -> Option<&[Symbol]> {
|
||||
match self {
|
||||
OwnedNamedOrAble::Named(_) => None,
|
||||
OwnedNamedOrAble::Able(av) => Some(av.ability),
|
||||
OwnedNamedOrAble::Able(av) => Some(&av.abilities),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,7 +127,7 @@ pub struct NamedVariable {
|
|||
pub struct AbleVariable {
|
||||
pub variable: Variable,
|
||||
pub name: Lowercase,
|
||||
pub ability: Symbol,
|
||||
pub abilities: Vec<Symbol>,
|
||||
// NB: there may be multiple occurrences of a variable
|
||||
pub first_seen: Region,
|
||||
}
|
||||
|
@ -166,12 +166,12 @@ impl IntroducedVariables {
|
|||
self.named.insert(named_variable);
|
||||
}
|
||||
|
||||
pub fn insert_able(&mut self, name: Lowercase, var: Loc<Variable>, ability: Symbol) {
|
||||
pub fn insert_able(&mut self, name: Lowercase, var: Loc<Variable>, abilities: Vec<Symbol>) {
|
||||
self.debug_assert_not_already_present(var.value);
|
||||
|
||||
let able_variable = AbleVariable {
|
||||
name,
|
||||
ability,
|
||||
abilities,
|
||||
variable: var.value,
|
||||
first_seen: var.region,
|
||||
};
|
||||
|
@ -450,8 +450,9 @@ pub fn find_type_def_symbols(
|
|||
stack.push(&annotation.value);
|
||||
|
||||
for has_clause in clauses.iter() {
|
||||
// TODO(abilities)
|
||||
stack.push(&has_clause.value.abilities[0].value);
|
||||
for ab in has_clause.value.abilities {
|
||||
stack.push(&ab.value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Inferred | Wildcard | Malformed(_) => {}
|
||||
|
@ -538,7 +539,7 @@ fn can_annotation_help(
|
|||
|
||||
// Generate an variable bound to the ability so we can keep compiling.
|
||||
let var = var_store.fresh();
|
||||
introduced_variables.insert_able(fresh_ty_var, Loc::at(region, var), symbol);
|
||||
introduced_variables.insert_able(fresh_ty_var, Loc::at(region, var), vec![symbol]);
|
||||
return Type::Variable(var);
|
||||
}
|
||||
|
||||
|
@ -579,7 +580,7 @@ fn can_annotation_help(
|
|||
arg_ann.region,
|
||||
OptAbleType {
|
||||
typ: arg_ann.value,
|
||||
opt_ability: alias_arg.value.opt_bound_ability,
|
||||
opt_abilities: alias_arg.value.opt_bound_abilities.clone(),
|
||||
},
|
||||
));
|
||||
}
|
||||
|
@ -674,7 +675,7 @@ fn can_annotation_help(
|
|||
AliasVar {
|
||||
name: var_name,
|
||||
var,
|
||||
opt_bound_ability: None,
|
||||
opt_bound_abilities: None,
|
||||
},
|
||||
));
|
||||
} else {
|
||||
|
@ -689,7 +690,7 @@ fn can_annotation_help(
|
|||
AliasVar {
|
||||
name: var_name,
|
||||
var,
|
||||
opt_bound_ability: None,
|
||||
opt_bound_abilities: None,
|
||||
},
|
||||
));
|
||||
}
|
||||
|
@ -769,10 +770,7 @@ fn can_annotation_help(
|
|||
symbol,
|
||||
type_arguments: vars
|
||||
.into_iter()
|
||||
.map(|typ| OptAbleType {
|
||||
typ,
|
||||
opt_ability: None,
|
||||
})
|
||||
.map(|typ| OptAbleType::unbound(typ))
|
||||
.collect(),
|
||||
lambda_set_variables: alias.lambda_set_variables.clone(),
|
||||
actual: Box::new(alias.typ.clone()),
|
||||
|
@ -932,31 +930,33 @@ fn canonicalize_has_clause(
|
|||
);
|
||||
let var_name = Lowercase::from(var_name);
|
||||
|
||||
// TODO(abilities)
|
||||
let ability = abilities[0];
|
||||
let ability = match ability.value {
|
||||
TypeAnnotation::Apply(module_name, ident, _type_arguments) => {
|
||||
let symbol = make_apply_symbol(env, ability.region, scope, module_name, ident)?;
|
||||
let mut can_abilities = Vec::with_capacity(abilities.len());
|
||||
for ability in *abilities {
|
||||
let ability = match ability.value {
|
||||
TypeAnnotation::Apply(module_name, ident, _type_arguments) => {
|
||||
let symbol = make_apply_symbol(env, ability.region, scope, module_name, ident)?;
|
||||
|
||||
// Ability defined locally, whose members we are constructing right now...
|
||||
if !pending_abilities_in_scope.contains_key(&symbol)
|
||||
// Ability defined locally, whose members we are constructing right now...
|
||||
if !pending_abilities_in_scope.contains_key(&symbol)
|
||||
// or an ability that was imported from elsewhere
|
||||
&& !scope.abilities_store.is_ability(symbol)
|
||||
{
|
||||
{
|
||||
let region = ability.region;
|
||||
env.problem(roc_problem::can::Problem::HasClauseIsNotAbility { region });
|
||||
return Err(Type::Erroneous(Problem::HasClauseIsNotAbility(region)));
|
||||
}
|
||||
symbol
|
||||
}
|
||||
_ => {
|
||||
let region = ability.region;
|
||||
env.problem(roc_problem::can::Problem::HasClauseIsNotAbility { region });
|
||||
return Err(Type::Erroneous(Problem::HasClauseIsNotAbility(region)));
|
||||
}
|
||||
symbol
|
||||
}
|
||||
_ => {
|
||||
let region = ability.region;
|
||||
env.problem(roc_problem::can::Problem::HasClauseIsNotAbility { region });
|
||||
return Err(Type::Erroneous(Problem::HasClauseIsNotAbility(region)));
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
references.insert(ability);
|
||||
references.insert(ability);
|
||||
can_abilities.push(ability);
|
||||
}
|
||||
|
||||
if let Some(shadowing) = introduced_variables.named_var_by_name(&var_name) {
|
||||
let var_name_ident = var_name.to_string().into();
|
||||
|
@ -974,7 +974,7 @@ fn canonicalize_has_clause(
|
|||
|
||||
let var = var_store.fresh();
|
||||
|
||||
introduced_variables.insert_able(var_name, Loc::at(region, var), ability);
|
||||
introduced_variables.insert_able(var_name, Loc::at(region, var), can_abilities);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1126,7 +1126,7 @@ pub fn freshen_opaque_def(
|
|||
.iter()
|
||||
.map(|alias_var| OptAbleVar {
|
||||
var: var_store.fresh(),
|
||||
opt_ability: alias_var.value.opt_bound_ability,
|
||||
opt_abilities: alias_var.value.opt_bound_abilities.clone(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
|
|
@ -357,14 +357,14 @@ fn canonicalize_alias<'a>(
|
|||
// This is a valid lowercase rigid var for the type def.
|
||||
let named_variable = named.swap_remove(index);
|
||||
let var = named_variable.variable();
|
||||
let opt_bound_ability = named_variable.opt_ability();
|
||||
let opt_bound_abilities = named_variable.opt_abilities().map(ToOwned::to_owned);
|
||||
let name = named_variable.name();
|
||||
|
||||
can_vars.push(Loc {
|
||||
value: AliasVar {
|
||||
name,
|
||||
var,
|
||||
opt_bound_ability,
|
||||
opt_bound_abilities,
|
||||
},
|
||||
region: loc_lowercase.region,
|
||||
});
|
||||
|
@ -386,7 +386,7 @@ fn canonicalize_alias<'a>(
|
|||
value: AliasVar {
|
||||
name: loc_lowercase.value.clone(),
|
||||
var: var_store.fresh(),
|
||||
opt_bound_ability: None,
|
||||
opt_bound_abilities: None,
|
||||
},
|
||||
region: loc_lowercase.region,
|
||||
});
|
||||
|
@ -859,7 +859,7 @@ fn canonicalize_opaque<'a>(
|
|||
alias_var.region,
|
||||
OptAbleType {
|
||||
typ: Type::Variable(var_store.fresh()),
|
||||
opt_ability: alias_var.value.opt_bound_ability,
|
||||
opt_abilities: alias_var.value.opt_bound_abilities.clone(),
|
||||
},
|
||||
)
|
||||
})
|
||||
|
@ -1345,7 +1345,7 @@ fn resolve_abilities<'a>(
|
|||
.introduced_variables
|
||||
.able
|
||||
.iter()
|
||||
.partition(|av| av.ability == ability);
|
||||
.partition(|av| av.abilities.iter().any(|ab| *ab == ability));
|
||||
|
||||
let var_bound_to_ability = match variables_bound_to_ability.as_slice() {
|
||||
[one] => one.variable,
|
||||
|
@ -2872,7 +2872,7 @@ fn make_tag_union_of_alias_recursive<'a>(
|
|||
|
||||
let alias_opt_able_vars = alias.type_variables.iter().map(|l| OptAbleType {
|
||||
typ: Type::Variable(l.value.var),
|
||||
opt_ability: l.value.opt_bound_ability,
|
||||
opt_abilities: l.value.opt_bound_abilities.clone(),
|
||||
});
|
||||
|
||||
let lambda_set_vars = alias.lambda_set_variables.iter();
|
||||
|
|
|
@ -1552,7 +1552,7 @@ fn build_fresh_opaque_variables(
|
|||
);
|
||||
let type_arguments = vec![OptAbleVar {
|
||||
var: a_var,
|
||||
opt_ability: None,
|
||||
opt_abilities: None,
|
||||
}];
|
||||
let lambda_set_variables = vec![roc_types::types::LambdaSet(Type::Variable(closure_var))];
|
||||
|
||||
|
|
|
@ -136,7 +136,7 @@ pub struct Module {
|
|||
#[derive(Debug, Default)]
|
||||
pub struct RigidVariables {
|
||||
pub named: MutMap<Variable, Lowercase>,
|
||||
pub able: MutMap<Variable, (Lowercase, Symbol)>,
|
||||
pub able: MutMap<Variable, (Lowercase, Vec<Symbol>)>,
|
||||
pub wildcards: VecSet<Variable>,
|
||||
}
|
||||
|
||||
|
@ -387,7 +387,7 @@ pub fn canonicalize_module_defs<'a>(
|
|||
for able in output.introduced_variables.able {
|
||||
rigid_variables
|
||||
.able
|
||||
.insert(able.variable, (able.name, able.ability));
|
||||
.insert(able.variable, (able.name, able.abilities));
|
||||
}
|
||||
|
||||
for var in output.introduced_variables.wildcards {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue