Freshly instantiate nested recursion variables under an opaque type

This commit is contained in:
Ayaz Hafiz 2023-04-12 14:31:19 -05:00
parent 3d6353dbd2
commit d3ab9ab926
No known key found for this signature in database
GPG key ID: 0E2A37416A25EF58
3 changed files with 24 additions and 15 deletions

View file

@ -1258,33 +1258,35 @@ fn shallow_dealias_with_scope<'a>(scope: &'a mut Scope, typ: &'a Type) -> &'a Ty
result result
} }
pub fn instantiate_and_freshen_alias_type( struct FreshenedAlias {
new_lambda_set_variables: Vec<LambdaSet>,
actual_type: Type,
}
fn instantiate_and_freshen_alias_type(
var_store: &mut VarStore, var_store: &mut VarStore,
introduced_variables: &mut IntroducedVariables, introduced_variables: &mut IntroducedVariables,
type_variables: &[Loc<AliasVar>], type_variables: &[Loc<AliasVar>],
type_arguments: Vec<Type>, type_arguments: Vec<Type>,
recursion_variables: impl IntoIterator<Item = Variable>,
lambda_set_variables: &[LambdaSet], lambda_set_variables: &[LambdaSet],
mut actual_type: Type, mut actual_type: Type,
) -> (Vec<(Lowercase, Type)>, Vec<LambdaSet>, Type) { ) -> FreshenedAlias {
let mut substitutions = ImMap::default(); let mut substitutions = ImMap::default();
let mut type_var_to_arg = Vec::new();
for (loc_var, arg_ann) in type_variables.iter().zip(type_arguments.into_iter()) { for (loc_var, arg_ann) in type_variables.iter().zip(type_arguments.into_iter()) {
let name = loc_var.value.name.clone();
let var = loc_var.value.var; let var = loc_var.value.var;
substitutions.insert(var, arg_ann.clone()); substitutions.insert(var, arg_ann.clone());
type_var_to_arg.push((name.clone(), arg_ann));
} }
// make sure the recursion variable is freshly instantiated // make sure all nested recursion variables is freshly instantiated
if let Type::RecursiveTagUnion(rvar, _, _) = &mut actual_type { for rec_var in recursion_variables {
let new = var_store.fresh(); let new = var_store.fresh();
substitutions.insert(*rvar, Type::Variable(new)); substitutions.insert(rec_var, Type::Variable(new));
*rvar = new;
} }
// make sure hidden variables are freshly instantiated // make sure all nested lambda set variables are freshly instantiated
let mut new_lambda_set_variables = Vec::with_capacity(lambda_set_variables.len()); let mut new_lambda_set_variables = Vec::with_capacity(lambda_set_variables.len());
for typ in lambda_set_variables.iter() { for typ in lambda_set_variables.iter() {
if let Type::Variable(var) = typ.0 { if let Type::Variable(var) = typ.0 {
@ -1300,7 +1302,10 @@ pub fn instantiate_and_freshen_alias_type(
// instantiate variables // instantiate variables
actual_type.substitute(&substitutions); actual_type.substitute(&substitutions);
(type_var_to_arg, new_lambda_set_variables, actual_type) FreshenedAlias {
new_lambda_set_variables,
actual_type,
}
} }
pub fn freshen_opaque_def( pub fn freshen_opaque_def(
@ -1327,16 +1332,20 @@ pub fn freshen_opaque_def(
// NB: If there are bugs, check whether this is a problem! // NB: If there are bugs, check whether this is a problem!
let mut introduced_variables = IntroducedVariables::default(); let mut introduced_variables = IntroducedVariables::default();
let (_fresh_type_arguments, fresh_lambda_set, fresh_type) = instantiate_and_freshen_alias_type( let FreshenedAlias {
new_lambda_set_variables,
actual_type,
} = instantiate_and_freshen_alias_type(
var_store, var_store,
&mut introduced_variables, &mut introduced_variables,
&opaque.type_variables, &opaque.type_variables,
fresh_type_arguments, fresh_type_arguments,
opaque.recursion_variables.iter().copied(),
&opaque.lambda_set_variables, &opaque.lambda_set_variables,
opaque.typ.clone(), opaque.typ.clone(),
); );
(fresh_variables, fresh_lambda_set, fresh_type) (fresh_variables, new_lambda_set_variables, actual_type)
} }
fn insertion_sort_by<T, F>(arr: &mut [T], mut compare: F) fn insertion_sort_by<T, F>(arr: &mut [T], mut compare: F)

View file

@ -2316,7 +2316,7 @@ impl Type {
RecursiveTagUnion(rec, tags, ext) => { RecursiveTagUnion(rec, tags, ext) => {
if let Some(replacement) = substitutions.get(rec) { if let Some(replacement) = substitutions.get(rec) {
let new_rec_var = match replacement { let new_rec_var = match replacement {
Type::Variable(v) => v.clone(), Type::Variable(v) => *v,
_ => panic!("Recursion var substitution must be a variable"), _ => panic!("Recursion var substitution must be a variable"),
}; };

View file

@ -7,7 +7,7 @@ LL a : [Nil, Cons a (LL a)]
LinkedList a := LL a LinkedList a := LL a
single = \item -> @LinkedList (Cons item Nil) single = \item -> @LinkedList (Cons item Nil)
#^^^^^^{-1} a -[[single(0)]]-> [Cons a ([Cons * b, Nil] as b), Nil] as [Cons * b, Nil] as b #^^^^^^{-1} a -[[single(0)]]-> [Cons a b, Nil] as b
walk = \@LinkedList list, state, fn -> walk = \@LinkedList list, state, fn ->
#^^^^{-1} [Cons a b, Nil] as b, c, (c, a -[[]]-> c) -[[walk(3)]]-> c #^^^^{-1} [Cons a b, Nil] as b, c, (c, a -[[]]-> c) -[[walk(3)]]-> c