nac3artiq: remove cached pyid_to_type if error

This commit is contained in:
ychenfo 2022-03-02 21:39:45 +08:00 committed by Gitea
parent 317eb80005
commit 84b4bd920b
1 changed files with 45 additions and 33 deletions

View File

@ -531,26 +531,30 @@ impl InnerResolver {
} }
(TypeEnum::TObj { params, fields, .. }, false) => { (TypeEnum::TObj { params, fields, .. }, false) => {
self.pyid_to_type.write().insert(ty_id, extracted_ty); self.pyid_to_type.write().insert(ty_id, extracted_ty);
let var_map = params let mut instantiate_obj = || {
.iter() let var_map = params
.map(|(id_var, ty)| { .iter()
if let TypeEnum::TVar { id, range, name, loc, .. } = &*unifier.get_ty(*ty) { .map(|(id_var, ty)| {
assert_eq!(*id, *id_var); if let TypeEnum::TVar { id, range, name, loc, .. } =
(*id, unifier.get_fresh_var_with_range(range, *name, *loc).0) &*unifier.get_ty(*ty)
{
assert_eq!(*id, *id_var);
(*id, unifier.get_fresh_var_with_range(range, *name, *loc).0)
} else {
unreachable!()
}
})
.collect::<HashMap<_, _>>();
// loop through non-function fields of the class to get the instantiated value
for field in fields.iter() {
let name: String = (*field.0).into();
if let TypeEnum::TFunc(..) = &*unifier.get_ty(field.1 .0) {
continue;
} else { } else {
unreachable!() let field_data = obj.getattr(&name)?;
} let ty = match self
}) .get_obj_type(py, field_data, unifier, defs, primitives)?
.collect::<HashMap<_, _>>(); {
// loop through non-function fields of the class to get the instantiated value
for field in fields.iter() {
let name: String = (*field.0).into();
if let TypeEnum::TFunc(..) = &*unifier.get_ty(field.1 .0) {
continue;
} else {
let field_data = obj.getattr(&name)?;
let ty =
match self.get_obj_type(py, field_data, unifier, defs, primitives)? {
Ok(t) => t, Ok(t) => t,
Err(e) => { Err(e) => {
return Ok(Err(format!( return Ok(Err(format!(
@ -559,24 +563,32 @@ impl InnerResolver {
))) )))
} }
}; };
let field_ty = unifier.subst(field.1 .0, &var_map).unwrap_or(field.1 .0); let field_ty =
if let Err(e) = unifier.unify(ty, field_ty) { unifier.subst(field.1 .0, &var_map).unwrap_or(field.1 .0);
// field type mismatch if let Err(e) = unifier.unify(ty, field_ty) {
return Ok(Err(format!( // field type mismatch
"error when getting type of field `{}` ({})", return Ok(Err(format!(
name, "error when getting type of field `{}` ({})",
e.to_display(unifier).to_string() name,
))); e.to_display(unifier).to_string()
)));
}
} }
} }
} for (_, ty) in var_map.iter() {
for (_, ty) in var_map.iter() { // must be concrete type
// must be concrete type if !unifier.is_concrete(*ty, &[]) {
if !unifier.is_concrete(*ty, &[]) { return Ok(Err("object is not of concrete type".into()));
return Ok(Err("object is not of concrete type".into())); }
} }
Ok(Ok(unifier.subst(extracted_ty, &var_map).unwrap_or(extracted_ty)))
};
let result = instantiate_obj();
// do not cache the type if there are errors
if matches!(result, Err(_) | Ok(Err(_))) {
self.pyid_to_type.write().remove(&ty_id);
} }
return Ok(Ok(unifier.subst(extracted_ty, &var_map).unwrap_or(extracted_ty))); result
} }
_ => Ok(Ok(extracted_ty)), _ => Ok(Ok(extracted_ty)),
}; };