Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[move-prover] Fix a bug in treatment of type reflection in spec funs #15606

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions third_party/move/move-model/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -885,6 +885,17 @@ impl GlobalEnv {
target_modules
}

/// Find all primary target modules and return in a vector
pub fn get_primary_target_modules(&self) -> Vec<ModuleEnv> {
let mut target_modules: Vec<ModuleEnv> = vec![];
for module_env in self.get_modules() {
if module_env.is_primary_target() {
target_modules.push(module_env);
}
}
target_modules
}

fn add_backtrace(msg: &str, _is_bug: bool) -> String {
// Note that you need both MOVE_COMPILER_BACKTRACE=1 and RUST_BACKTRACE=1 for this to
// actually generate a backtrace.
Expand Down
28 changes: 20 additions & 8 deletions third_party/move/move-prover/boogie-backend/src/spec_translator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,11 +314,27 @@ impl<'env> SpecTranslator<'env> {
}
};
let type_info_params = if type_reflection {
let mut covered = BTreeSet::new();
(0..fun.type_params.len())
.map(|i| {
// Apply type instantiation if present
let ty = self
.type_inst
.get(i)
.cloned()
.unwrap_or_else(|| Type::TypeParameter(i as u16));
// There can be name clashes after instantiation. Parameters still need
// to be there but all are instantiated with the same type. We escape
// the redundant parameters.
let prefix = if !covered.insert(ty.clone()) {
format!("_{}_", i)
} else {
"".to_string()
};
format!(
"{}_info: $TypeParamInfo",
boogie_type(self.env, &Type::TypeParameter(i as u16))
"{}{}_info: $TypeParamInfo",
prefix,
boogie_type(self.env, &ty)
)
})
.collect_vec()
Expand Down Expand Up @@ -1154,13 +1170,9 @@ impl<'env> SpecTranslator<'env> {
.env
.spec_fun_uses_generic_type_reflection(&module_id.qualified_inst(fun_id, inst.clone()))
{
for i in 0..fun_decl.type_params.len() {
for ty in inst {
maybe_comma();
emit!(
self.writer,
"{}_info",
boogie_type(self.env, &Type::TypeParameter(i as u16))
)
emit!(self.writer, "{}_info", boogie_type(self.env, ty))
}
}
// Add memory parameters.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ impl FunctionTargetProcessor for VerificationAnalysisProcessor {

// Rule 2: verify the function if it is within the target modules
let env = fun_env.module_env.env;
let target_modules = env.get_target_modules();
let target_modules = env.get_primary_target_modules();

let is_in_target_module = target_modules
.iter()
Expand Down Expand Up @@ -162,7 +162,7 @@ impl FunctionTargetProcessor for VerificationAnalysisProcessor {

writeln!(f, "invariant applicability: [")?;
let target_invs: BTreeSet<_> = env
.get_target_modules()
.get_primary_target_modules()
.iter()
.flat_map(|menv| env.get_global_invariants_by_module(menv.get_id()))
.collect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -661,7 +661,7 @@ impl FunctionTargetProcessor for VerificationAnalysisProcessorV2 {
_ => {},
}

let target_modules = global_env.get_target_modules();
let target_modules = global_env.get_primary_target_modules();
let target_fun_ids: BTreeSet<QualifiedId<FunId>> = target_modules
.iter()
.flat_map(|mod_env| mod_env.get_functions())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,12 +110,24 @@ module 0x42::test {
type_info::type_of<A>()
}
spec generic_type_info_verification_target {
ensures result == generic_type_info_spec_fun<A>();
ensures result == generic_type_info_spec_fun<A>()
&& result == generic_type_info_spec_fun_2<A>();
}

spec fun generic_type_info_spec_fun<A>(): type_info::TypeInfo {
type_info::type_of<A>()
}

spec fun generic_type_info_spec_fun_2<A>(): type_info::TypeInfo {
takes_2<A, A>()
}

spec fun takes_2<A, B>(): type_info::TypeInfo {
// Pass on the 2nd type parameter to be sure the instantiation
// of B is correctly handled
type_info::type_of<B>()
}

}

module 0x43::test {
Expand Down
2 changes: 1 addition & 1 deletion third_party/move/tools/move-cli/src/base/prove.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ pub fn run_move_prover(
} else {
"FAILURE".bold().red()
},
model.get_target_modules().len(),
model.get_primary_target_modules().len(),
basedir,
now.elapsed().as_secs_f64()
)?;
Expand Down
Loading