Skip to content
Snippets Groups Projects
Commit f4beb7ba authored by Lennard Gäher's avatar Lennard Gäher
Browse files

Merge branch 'ci/better-error-msg' into 'main'

improve error messages, rollback ADT registry when encountering a translation error

See merge request !11
parents 15f4ee56 ecc80003
No related branches found
No related tags found
1 merge request!11improve error messages, rollback ADT registry when encountering a translation error
Pipeline #96674 canceled
...@@ -56,3 +56,23 @@ impl EvenInt { ...@@ -56,3 +56,23 @@ impl EvenInt {
self.add(); self.add();
} }
} }
pub struct Foo {}
impl Foo {
#[rr::params("x", "γ")]
#[rr::args("(#x, γ)")]
#[rr::returns("()")]
pub fn a(&mut self) {
assert!(true);
}
#[rr::params("x", "γ")]
#[rr::args("(#x, γ)")]
#[rr::returns("()")]
pub fn b(&mut self) {
assert!(true);
}
}
...@@ -629,17 +629,17 @@ fn translate_functions<'rcx, 'tcx>(vcx: &mut VerificationCtxt<'tcx, 'rcx>) { ...@@ -629,17 +629,17 @@ fn translate_functions<'rcx, 'tcx>(vcx: &mut VerificationCtxt<'tcx, 'rcx>) {
// Only generate a spec // Only generate a spec
match translator.and_then(|t| t.generate_spec()) { match translator.and_then(|t| t.generate_spec()) {
Ok(spec) => { Ok(spec) => {
info!("Successfully generated spec for {}", fname); println!("Successfully generated spec for {}", fname);
vcx.procedure_registry.provide_specced_function(&f.to_def_id(), spec); vcx.procedure_registry.provide_specced_function(&f.to_def_id(), spec);
}, },
Err(function_body::TranslationError::FatalError(err)) => { Err(function_body::TranslationError::FatalError(err)) => {
error!("Encountered fatal cross-function error in translation: {:?}", err); println!("Encountered fatal cross-function error in translation: {:?}", err);
error!("Aborting..."); println!("Aborting...");
return; return;
}, },
Err(err) => { Err(err) => {
warn!("Encountered error: {:?}", err); println!("Encountered error: {:?}", err);
warn!("Skipping function {}", fname); println!("Skipping function {}", fname);
if !rrconfig::skip_unsupported_features() { if !rrconfig::skip_unsupported_features() {
exit_with_error(&format!("Encountered error when translating function {}, stopping...", fname)); exit_with_error(&format!("Encountered error when translating function {}, stopping...", fname));
} }
...@@ -650,17 +650,17 @@ fn translate_functions<'rcx, 'tcx>(vcx: &mut VerificationCtxt<'tcx, 'rcx>) { ...@@ -650,17 +650,17 @@ fn translate_functions<'rcx, 'tcx>(vcx: &mut VerificationCtxt<'tcx, 'rcx>) {
// Fully translate the function // Fully translate the function
match translator.and_then(|t| t.translate()) { match translator.and_then(|t| t.translate()) {
Ok(fun) => { Ok(fun) => {
info!("Successfully translated {}", fname); println!("Successfully translated {}", fname);
vcx.procedure_registry.provide_translated_function(&f.to_def_id(), fun); vcx.procedure_registry.provide_translated_function(&f.to_def_id(), fun);
}, },
Err(function_body::TranslationError::FatalError(err)) => { Err(function_body::TranslationError::FatalError(err)) => {
error!("Encountered fatal cross-function error in translation: {:?}", err); println!("Encountered fatal cross-function error in translation: {:?}", err);
error!("Aborting..."); println!("Aborting...");
return; return;
}, },
Err(err) => { Err(err) => {
warn!("Encountered error: {:?}", err); println!("Encountered error: {:?}", err);
warn!("Skipping function {}", fname); println!("Skipping function {}", fname);
if !rrconfig::skip_unsupported_features() { if !rrconfig::skip_unsupported_features() {
exit_with_error(&format!("Encountered error when translating function {}, stopping...", fname)); exit_with_error(&format!("Encountered error when translating function {}, stopping...", fname));
} }
......
...@@ -393,19 +393,23 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> { ...@@ -393,19 +393,23 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> {
let mut generic_syntys = Vec::new(); let mut generic_syntys = Vec::new();
for arg in args.into_iter() { for arg in args.into_iter() {
let arg_ty = arg.expect_ty(); if let Some(arg_ty) = arg.as_type() {
let mut translated_ty; let mut translated_ty;
if let Some(ref mut adt_deps) = adt_deps { if let Some(ref mut adt_deps) = adt_deps {
translated_ty = self.translate_type_with_deps(&arg_ty, Some(&mut *adt_deps))?; translated_ty = self.translate_type_with_deps(&arg_ty, Some(&mut *adt_deps))?;
}
else {
translated_ty = self.translate_type_with_deps(&arg_ty, None)?;
}
// we need to substitute in the variables according to the function scope
translated_ty.subst(generic_env.as_slice());
//translated_ty.subst
generic_syntys.push(translated_ty.get_syn_type());
params.push(translated_ty);
} }
else { else {
translated_ty = self.translate_type_with_deps(&arg_ty, None)?; return Err(TranslationError::UnsupportedFeature{ description: "structs with lifetime parameters are not supported".to_string()})
} }
// we need to substitute in the variables according to the function scope
translated_ty.subst(generic_env.as_slice());
//translated_ty.subst
generic_syntys.push(translated_ty.get_syn_type());
params.push(translated_ty);
} }
let struct_use = radium::AbstractStructUse::new(struct_ref, params, radium::TypeIsRaw::No); let struct_use = radium::AbstractStructUse::new(struct_ref, params, radium::TypeIsRaw::No);
...@@ -580,27 +584,35 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> { ...@@ -580,27 +584,35 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> {
let struct_name = strip_coq_ident(&ty.ident(tcx).to_string()); let struct_name = strip_coq_ident(&ty.ident(tcx).to_string());
self.variant_registry.borrow_mut().insert(ty.def_id, (struct_name.clone(), &*struct_def_init, ty, false)); self.variant_registry.borrow_mut().insert(ty.def_id, (struct_name.clone(), &*struct_def_init, ty, false));
let struct_name = strip_coq_ident(&ty.ident(tcx).to_string()); let translate_adt = || {
let (variant_def, invariant_def) = self.make_adt_variant(&struct_name, ty, adt, &ty_param_defs, &st_params, Some(&mut adt_deps))?; let struct_name = strip_coq_ident(&ty.ident(tcx).to_string());
let (variant_def, invariant_def) = self.make_adt_variant(&struct_name, ty, adt, &ty_param_defs, &st_params, Some(&mut adt_deps))?;
let mut struct_def = radium::AbstractStruct::new(variant_def, ty_param_defs, st_params);
if let Some(invariant_def) = invariant_def {
struct_def.add_invariant(invariant_def);
}
// TODO for generating the semtype definition, we will also need to track dependencies let mut struct_def = radium::AbstractStruct::new(variant_def, ty_param_defs, st_params);
// between structs so that we know when we need recursive types etc. if let Some(invariant_def) = invariant_def {
struct_def.add_invariant(invariant_def);
}
Ok(struct_def)
};
// finalize the definition match translate_adt() {
{ Ok(struct_def) => {
let mut struct_def_ref = struct_def_init.borrow_mut(); // finalize the definition
*struct_def_ref = Some(struct_def); // TODO for generating the semtype definition, we will also need to track dependencies
// between structs so that we know when we need recursive types etc.
let mut struct_def_ref = struct_def_init.borrow_mut();
*struct_def_ref = Some(struct_def);
let mut deps_ref = self.adt_deps.borrow_mut(); let mut deps_ref = self.adt_deps.borrow_mut();
deps_ref.insert(adt.did(), adt_deps); deps_ref.insert(adt.did(), adt_deps);
Ok(())
}
Err(err) => {
// remove the partial definition
self.variant_registry.borrow_mut().remove(&ty.def_id);
Err(err)
}
} }
Ok(())
} }
/// Make an ADT variant. /// Make an ADT variant.
...@@ -881,7 +893,6 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> { ...@@ -881,7 +893,6 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> {
// TODO: currently a hack, I don't know how to query the name properly // TODO: currently a hack, I don't know how to query the name properly
let enum_name = strip_coq_ident(format!("{:?}", def).as_str()); let enum_name = strip_coq_ident(format!("{:?}", def).as_str());
self.enum_registry.borrow_mut().insert(def.did(), (enum_name.clone(), &*enum_def_init, def));
// first thing: figure out the generics we are using here. // first thing: figure out the generics we are using here.
// we need to search all of the variant types for that. // we need to search all of the variant types for that.
...@@ -906,131 +917,142 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> { ...@@ -906,131 +917,142 @@ impl <'def, 'tcx : 'def> TypeTranslator<'def, 'tcx> {
info!("enum using generics: {:?}", used_generics); info!("enum using generics: {:?}", used_generics);
// now build masks describing which generics each of the variants uses // insert partial definition for recursive occurrences
// and register the variants self.enum_registry.borrow_mut().insert(def.did(), (enum_name.clone(), &*enum_def_init, def));
let mut variant_masks: HashMap<DefId, Vec<bool>> = HashMap::new();
let mut variant_attrs = Vec::new(); let translate_variants = || {
for v in def.variants().iter() { // now build masks describing which generics each of the variants uses
let mut folder = TyVarFolder::new(self.env.tcx()); // and register the variants
for f in v.fields.iter() { let mut variant_masks: HashMap<DefId, Vec<bool>> = HashMap::new();
let f_ty = self.env.tcx().type_of(f.did).instantiate_identity(); let mut variant_attrs = Vec::new();
f_ty.fold_with(&mut folder); for v in def.variants().iter() {
} let mut folder = TyVarFolder::new(self.env.tcx());
let variant_generics: HashSet<ty::ParamTy> = folder.get_result(); for f in v.fields.iter() {
let f_ty = self.env.tcx().type_of(f.did).instantiate_identity();
let mut mask = Vec::new(); f_ty.fold_with(&mut folder);
let mut these_param_defs = Vec::new();
let mut these_st_params = Vec::new();
for ((param, param_defs), st_param) in used_generics.iter().zip(ty_param_defs.iter()).zip(st_params.iter()) {
if variant_generics.contains(param) {
mask.push(true);
these_param_defs.push(param_defs.clone());
these_st_params.push(st_param.clone());
} }
else { let variant_generics: HashSet<ty::ParamTy> = folder.get_result();
mask.push(false);
let mut mask = Vec::new();
let mut these_param_defs = Vec::new();
let mut these_st_params = Vec::new();
for ((param, param_defs), st_param) in used_generics.iter().zip(ty_param_defs.iter()).zip(st_params.iter()) {
if variant_generics.contains(param) {
mask.push(true);
these_param_defs.push(param_defs.clone());
these_st_params.push(st_param.clone());
}
else {
mask.push(false);
}
} }
} variant_masks.insert(v.def_id, mask);
variant_masks.insert(v.def_id, mask);
// now generate the variant // now generate the variant
let struct_def_init = self.struct_arena.alloc(RefCell::new(None)); let struct_def_init = self.struct_arena.alloc(RefCell::new(None));
let struct_name = strip_coq_ident(format!("{}_{}", enum_name, v.ident(tcx)).as_str()); let struct_name = strip_coq_ident(format!("{}_{}", enum_name, v.ident(tcx)).as_str());
self.variant_registry.borrow_mut().insert(v.def_id, (struct_name.clone(), &*struct_def_init, v, true)); self.variant_registry.borrow_mut().insert(v.def_id, (struct_name.clone(), &*struct_def_init, v, true));
// IMPORTANT: use the full enum's ty_param_defs to account for indexing // IMPORTANT: use the full enum's ty_param_defs to account for indexing
let (variant_def, invariant_def) = self.make_adt_variant(struct_name.as_str(), v, def, &ty_param_defs, &st_params, Some(&mut adt_deps))?; let (variant_def, invariant_def) = self.make_adt_variant(struct_name.as_str(), v, def, &ty_param_defs, &st_params, Some(&mut adt_deps))?;
// IMPORTANT: use the subset of actually used params for the definition // IMPORTANT: use the subset of actually used params for the definition
let mut struct_def = radium::AbstractStruct::new(variant_def, these_param_defs, these_st_params); let mut struct_def = radium::AbstractStruct::new(variant_def, these_param_defs, these_st_params);
if let Some(invariant_def) = invariant_def { if let Some(invariant_def) = invariant_def {
struct_def.add_invariant(invariant_def); struct_def.add_invariant(invariant_def);
} }
// also remember the attributes for additional processing // also remember the attributes for additional processing
let outer_attrs = self.env.get_attributes(v.def_id); let outer_attrs = self.env.get_attributes(v.def_id);
let outer_attrs = crate::utils::filter_tool_attrs(outer_attrs); let outer_attrs = crate::utils::filter_tool_attrs(outer_attrs);
variant_attrs.push(outer_attrs); variant_attrs.push(outer_attrs);
// finalize the definition // finalize the definition
{ {
let mut struct_def_ref = struct_def_init.borrow_mut(); let mut struct_def_ref = struct_def_init.borrow_mut();
*struct_def_ref = Some(struct_def); *struct_def_ref = Some(struct_def);
}
} }
}
// get the type of the discriminant // get the type of the discriminant
let it = def.repr().discr_type(); let it = def.repr().discr_type();
let translated_it = self.translate_integer_type(it)?; let translated_it = self.translate_integer_type(it)?;
// build the discriminant map // build the discriminant map
let discrs = self.build_discriminant_map(def)?; let discrs = self.build_discriminant_map(def)?;
// get representation options // get representation options
let repr = def.repr(); let repr = def.repr();
let mut repr_opt = radium::EnumRepr::ReprRust; let mut repr_opt = radium::EnumRepr::ReprRust;
if repr.c() { if repr.c() {
repr_opt = radium::EnumRepr::ReprC; repr_opt = radium::EnumRepr::ReprC;
} }
else if repr.simd() { else if repr.simd() {
return Err(TranslationError::UnsupportedFeature { description: "The SIMD flag is currently unsupported".to_string() }) return Err(TranslationError::UnsupportedFeature { description: "The SIMD flag is currently unsupported".to_string() })
} }
else if repr.packed() { else if repr.packed() {
return Err(TranslationError::UnsupportedFeature { description: "The repr(packed) flag is currently unsupported".to_string() }) return Err(TranslationError::UnsupportedFeature { description: "The repr(packed) flag is currently unsupported".to_string() })
} }
else if repr.linear() { else if repr.linear() {
return Err(TranslationError::UnsupportedFeature { description: "The linear flag is currently unsupported".to_string() }) return Err(TranslationError::UnsupportedFeature { description: "The linear flag is currently unsupported".to_string() })
} }
else if repr.transparent() { else if repr.transparent() {
repr_opt = radium::EnumRepr::ReprTransparent; repr_opt = radium::EnumRepr::ReprTransparent;
} }
// parse annotations for enum type // parse annotations for enum type
let enum_spec; let enum_spec;
let mut inductive_decl = None; let mut inductive_decl = None;
let builtin_spec = self.get_builtin_enum_spec(def.did())?; let builtin_spec = self.get_builtin_enum_spec(def.did())?;
if let Some(spec) = builtin_spec { if let Some(spec) = builtin_spec {
enum_spec = spec; enum_spec = spec;
} }
else if self.env.has_tool_attribute(def.did(), "refined_by") { else if self.env.has_tool_attribute(def.did(), "refined_by") {
let attributes = self.env.get_attributes(def.did()); let attributes = self.env.get_attributes(def.did());
let attributes = crate::utils::filter_tool_attrs(attributes); let attributes = crate::utils::filter_tool_attrs(attributes);
// TODO: change once we handle lft parameters properly // TODO: change once we handle lft parameters properly
let lft_params: Vec<(Option<String>, radium::Lft)> = Vec::new(); let lft_params: Vec<(Option<String>, radium::Lft)> = Vec::new();
let mut parser = VerboseEnumSpecParser::new(); let mut parser = VerboseEnumSpecParser::new();
enum_spec = parser.parse_enum_spec("", &attributes, &variant_attrs, &ty_param_defs, &lft_params) enum_spec = parser.parse_enum_spec("", &attributes, &variant_attrs, &ty_param_defs, &lft_params)
.map_err(|err| TranslationError::FatalError(err))?; .map_err(|err| TranslationError::FatalError(err))?;
} }
else { else {
// generate a specification // generate a specification
let decl; let decl;
(decl, enum_spec) = self.generate_enum_spec(def, &enum_name); (decl, enum_spec) = self.generate_enum_spec(def, &enum_name);
inductive_decl = Some(decl); inductive_decl = Some(decl);
} }
let mut enum_builder = radium::EnumBuilder::new(enum_name, ty_param_defs, st_params, translated_it, repr_opt); let mut enum_builder = radium::EnumBuilder::new(enum_name, ty_param_defs, st_params, translated_it, repr_opt);
// now build the enum itself // now build the enum itself
for v in def.variants().iter() { for v in def.variants().iter() {
let variant_ref = self.lookup_adt_variant(v.def_id)?; let variant_ref = self.lookup_adt_variant(v.def_id)?;
let variant_name = strip_coq_ident(&v.ident(tcx).to_string()); let variant_name = strip_coq_ident(&v.ident(tcx).to_string());
let discriminant = discrs.get(&variant_name).unwrap(); let discriminant = discrs.get(&variant_name).unwrap();
enum_builder.add_variant(&variant_name, variant_ref, variant_masks.remove(&v.def_id).unwrap(), *discriminant); enum_builder.add_variant(&variant_name, variant_ref, variant_masks.remove(&v.def_id).unwrap(), *discriminant);
} }
Ok(enum_builder.finish(inductive_decl, enum_spec))
};
let enum_def = enum_builder.finish(inductive_decl, enum_spec); match translate_variants() {
// finalize the definition Ok(enum_def) => {
{ // finalize the definition
let mut enum_def_ref = enum_def_init.borrow_mut(); let mut enum_def_ref = enum_def_init.borrow_mut();
*enum_def_ref = Some(enum_def); *enum_def_ref = Some(enum_def);
let mut deps_ref = self.adt_deps.borrow_mut(); let mut deps_ref = self.adt_deps.borrow_mut();
deps_ref.insert(def.did(), adt_deps); deps_ref.insert(def.did(), adt_deps);
Ok(())
},
Err(err) => {
// deregister the ADT again
self.enum_registry.borrow_mut().remove(&def.did());
Err(err)
},
} }
Ok(())
} }
/// Translate type. /// Translate type.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment