From a50df6560e05cb512e18830d4e26ee7ab9a98e57 Mon Sep 17 00:00:00 2001 From: ychenfo Date: Thu, 11 Nov 2021 20:25:33 +0800 Subject: [PATCH] nac3core: fix handling on rigid typevar --- nac3core/src/codegen/mod.rs | 8 ++++- nac3core/src/toplevel/composer.rs | 49 +++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 16 deletions(-) diff --git a/nac3core/src/codegen/mod.rs b/nac3core/src/codegen/mod.rs index d64212b68..68dc804ac 100644 --- a/nac3core/src/codegen/mod.rs +++ b/nac3core/src/codegen/mod.rs @@ -280,7 +280,13 @@ pub fn gen_func<'ctx, G: CodeGenerator + ?Sized>( // this should be unification between variables and concrete types // and should not cause any problem... 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 diff --git a/nac3core/src/toplevel/composer.rs b/nac3core/src/toplevel/composer.rs index 8dd5404c9..9c23930e6 100644 --- a/nac3core/src/toplevel/composer.rs +++ b/nac3core/src/toplevel/composer.rs @@ -1171,8 +1171,17 @@ impl TopLevelComposer { primitives_store.none } }; - var_id.extend_from_slice( - function_var_map.keys().into_iter().copied().collect_vec().as_slice(), + var_id.extend_from_slice(function_var_map + .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( FunSignature { args: arg_types, ret: return_ty, vars: function_var_map } @@ -1375,9 +1384,20 @@ impl TopLevelComposer { if let TopLevelDef::Function { var_id, .. } = temp_def_list.get(method_id.0).unwrap().write().deref_mut() { - var_id.extend_from_slice( - method_var_map.keys().into_iter().copied().collect_vec().as_slice(), + var_id.extend_from_slice(method_var_map + .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( FunSignature { args: arg_types, ret: ret_type, vars: method_var_map } @@ -1649,6 +1669,7 @@ impl TopLevelComposer { simple_name, signature, resolver, + var_id: insted_vars, .. } = &mut *function_def { @@ -1675,20 +1696,20 @@ impl TopLevelComposer { 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 unifier = &mut self.unifier; let mut no_ranges: Vec = Vec::new(); - let var_ids = vars.iter().map(|(id, ty)| { - 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_ids = vars.keys().copied().collect_vec(); let var_combs = vars .iter() .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() .collect_vec(); @@ -1835,13 +1856,11 @@ impl TopLevelComposer { } instance_to_stmt.insert( - // NOTE: refer to codegen/expr/get_subst_key function - get_subst_key( &mut self.unifier, self_type, &subst, - None + Some(insted_vars), ), FunInstance { body: Arc::new(fun_body),