1
0
forked from M-Labs/nac3

nac3core: fix handling on rigid typevar

This commit is contained in:
ychenfo 2021-11-11 20:25:33 +08:00
parent a9635f0979
commit a50df6560e
2 changed files with 41 additions and 16 deletions

View File

@ -280,7 +280,13 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>(
// this should be unification between variables and concrete types // this should be unification between variables and concrete types
// and should not cause any problem... // and should not cause any problem...
let b = task.store.to_unifier_type(&mut unifier, &primitives, *b, &mut cache); let b = task.store.to_unifier_type(&mut unifier, &primitives, *b, &mut cache);
unifier.unify(*a, b).unwrap(); unifier.unify(*a, b).or_else(|err| {
if matches!(&*unifier.get_ty(*a), TypeEnum::TRigidVar { .. }) {
Ok(unifier.replace_rigid_var(*a, b))
} else {
Err(err)
}
}).unwrap()
} }
// rebuild primitive store with unique representatives // rebuild primitive store with unique representatives

View File

@ -1171,8 +1171,17 @@ impl TopLevelComposer {
primitives_store.none primitives_store.none
} }
}; };
var_id.extend_from_slice( var_id.extend_from_slice(function_var_map
function_var_map.keys().into_iter().copied().collect_vec().as_slice(), .iter()
.filter_map(|(id, ty)| {
if matches!(&*unifier.get_ty(*ty), TypeEnum::TVar { range, .. } if range.borrow().is_empty()) {
None
} else {
Some(*id)
}
})
.collect_vec()
.as_slice()
); );
let function_ty = unifier.add_ty(TypeEnum::TFunc( let function_ty = unifier.add_ty(TypeEnum::TFunc(
FunSignature { args: arg_types, ret: return_ty, vars: function_var_map } FunSignature { args: arg_types, ret: return_ty, vars: function_var_map }
@ -1375,9 +1384,20 @@ impl TopLevelComposer {
if let TopLevelDef::Function { var_id, .. } = if let TopLevelDef::Function { var_id, .. } =
temp_def_list.get(method_id.0).unwrap().write().deref_mut() temp_def_list.get(method_id.0).unwrap().write().deref_mut()
{ {
var_id.extend_from_slice( var_id.extend_from_slice(method_var_map
method_var_map.keys().into_iter().copied().collect_vec().as_slice(), .iter()
.filter_map(|(id, ty)| {
if matches!(&*unifier.get_ty(*ty), TypeEnum::TVar { range, .. } if range.borrow().is_empty()) {
None
} else {
Some(*id)
}
})
.collect_vec()
.as_slice()
); );
} else {
unreachable!()
} }
let method_type = unifier.add_ty(TypeEnum::TFunc( let method_type = unifier.add_ty(TypeEnum::TFunc(
FunSignature { args: arg_types, ret: ret_type, vars: method_var_map } FunSignature { args: arg_types, ret: ret_type, vars: method_var_map }
@ -1649,6 +1669,7 @@ impl TopLevelComposer {
simple_name, simple_name,
signature, signature,
resolver, resolver,
var_id: insted_vars,
.. ..
} = &mut *function_def } = &mut *function_def
{ {
@ -1675,20 +1696,20 @@ impl TopLevelComposer {
None None
} }
}; };
// carefully handle those with bounds, without bounds and no typevars
// if class methods, `vars` also contains all class typevars here
let (type_var_subst_comb, no_range_vars) = { let (type_var_subst_comb, no_range_vars) = {
let unifier = &mut self.unifier; let unifier = &mut self.unifier;
let mut no_ranges: Vec<Type> = Vec::new(); let mut no_ranges: Vec<Type> = Vec::new();
let var_ids = vars.iter().map(|(id, ty)| { let var_ids = vars.keys().copied().collect_vec();
if matches!(unifier.get_ty(*ty).as_ref(), TypeEnum::TVar { range, .. } if range.borrow().is_empty()) {
no_ranges.push(*ty);
}
*id
})
.collect_vec();
let var_combs = vars let var_combs = vars
.iter() .iter()
.map(|(_, ty)| { .map(|(_, ty)| {
unifier.get_instantiations(*ty).unwrap_or_else(|| vec![*ty]) unifier.get_instantiations(*ty).unwrap_or_else(|| {
let rigid = unifier.get_fresh_rigid_var().0;
no_ranges.push(rigid);
vec![rigid]
})
}) })
.multi_cartesian_product() .multi_cartesian_product()
.collect_vec(); .collect_vec();
@ -1835,13 +1856,11 @@ impl TopLevelComposer {
} }
instance_to_stmt.insert( instance_to_stmt.insert(
// NOTE: refer to codegen/expr/get_subst_key function
get_subst_key( get_subst_key(
&mut self.unifier, &mut self.unifier,
self_type, self_type,
&subst, &subst,
None Some(insted_vars),
), ),
FunInstance { FunInstance {
body: Arc::new(fun_body), body: Arc::new(fun_body),