Skip to content

Commit dd0dcd2

Browse files
authored
[move-prover] Fix a bug in treatment of type reflection in spec funs (aptos-labs#15606)
When calling a generic function in a specification expression which transitively uses type reflection, the function call type instantiation wasn't correctly treated for the type info parameters. The refined test generates this situation and failed before but passes now. Removes the boogie compilation error in aptos-labs#15605, but after this the example in this bug times out, even though the package does not contain any specs. I verified that all verification conditions belong to functions in this package, but this does not change this. Should be fixed in subsequent PR before closing the bug.
1 parent f69598f commit dd0dcd2

File tree

6 files changed

+48
-13
lines changed

6 files changed

+48
-13
lines changed

third_party/move/move-model/src/model.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,17 @@ impl GlobalEnv {
885885
target_modules
886886
}
887887

888+
/// Find all primary target modules and return in a vector
889+
pub fn get_primary_target_modules(&self) -> Vec<ModuleEnv> {
890+
let mut target_modules: Vec<ModuleEnv> = vec![];
891+
for module_env in self.get_modules() {
892+
if module_env.is_primary_target() {
893+
target_modules.push(module_env);
894+
}
895+
}
896+
target_modules
897+
}
898+
888899
fn add_backtrace(msg: &str, _is_bug: bool) -> String {
889900
// Note that you need both MOVE_COMPILER_BACKTRACE=1 and RUST_BACKTRACE=1 for this to
890901
// actually generate a backtrace.

third_party/move/move-prover/boogie-backend/src/spec_translator.rs

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,27 @@ impl<'env> SpecTranslator<'env> {
314314
}
315315
};
316316
let type_info_params = if type_reflection {
317+
let mut covered = BTreeSet::new();
317318
(0..fun.type_params.len())
318319
.map(|i| {
320+
// Apply type instantiation if present
321+
let ty = self
322+
.type_inst
323+
.get(i)
324+
.cloned()
325+
.unwrap_or_else(|| Type::TypeParameter(i as u16));
326+
// There can be name clashes after instantiation. Parameters still need
327+
// to be there but all are instantiated with the same type. We escape
328+
// the redundant parameters.
329+
let prefix = if !covered.insert(ty.clone()) {
330+
format!("_{}_", i)
331+
} else {
332+
"".to_string()
333+
};
319334
format!(
320-
"{}_info: $TypeParamInfo",
321-
boogie_type(self.env, &Type::TypeParameter(i as u16))
335+
"{}{}_info: $TypeParamInfo",
336+
prefix,
337+
boogie_type(self.env, &ty)
322338
)
323339
})
324340
.collect_vec()
@@ -1154,13 +1170,9 @@ impl<'env> SpecTranslator<'env> {
11541170
.env
11551171
.spec_fun_uses_generic_type_reflection(&module_id.qualified_inst(fun_id, inst.clone()))
11561172
{
1157-
for i in 0..fun_decl.type_params.len() {
1173+
for ty in inst {
11581174
maybe_comma();
1159-
emit!(
1160-
self.writer,
1161-
"{}_info",
1162-
boogie_type(self.env, &Type::TypeParameter(i as u16))
1163-
)
1175+
emit!(self.writer, "{}_info", boogie_type(self.env, ty))
11641176
}
11651177
}
11661178
// Add memory parameters.

third_party/move/move-prover/bytecode-pipeline/src/verification_analysis.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ impl FunctionTargetProcessor for VerificationAnalysisProcessor {
9696

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

101101
let is_in_target_module = target_modules
102102
.iter()
@@ -162,7 +162,7 @@ impl FunctionTargetProcessor for VerificationAnalysisProcessor {
162162

163163
writeln!(f, "invariant applicability: [")?;
164164
let target_invs: BTreeSet<_> = env
165-
.get_target_modules()
165+
.get_primary_target_modules()
166166
.iter()
167167
.flat_map(|menv| env.get_global_invariants_by_module(menv.get_id()))
168168
.collect();

third_party/move/move-prover/bytecode-pipeline/src/verification_analysis_v2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -661,7 +661,7 @@ impl FunctionTargetProcessor for VerificationAnalysisProcessorV2 {
661661
_ => {},
662662
}
663663

664-
let target_modules = global_env.get_target_modules();
664+
let target_modules = global_env.get_primary_target_modules();
665665
let target_fun_ids: BTreeSet<QualifiedId<FunId>> = target_modules
666666
.iter()
667667
.flat_map(|mod_env| mod_env.get_functions())

third_party/move/move-prover/tests/sources/functional/type_reflection.move

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,24 @@ module 0x42::test {
110110
type_info::type_of<A>()
111111
}
112112
spec generic_type_info_verification_target {
113-
ensures result == generic_type_info_spec_fun<A>();
113+
ensures result == generic_type_info_spec_fun<A>()
114+
&& result == generic_type_info_spec_fun_2<A>();
114115
}
115116

116117
spec fun generic_type_info_spec_fun<A>(): type_info::TypeInfo {
117118
type_info::type_of<A>()
118119
}
120+
121+
spec fun generic_type_info_spec_fun_2<A>(): type_info::TypeInfo {
122+
takes_2<A, A>()
123+
}
124+
125+
spec fun takes_2<A, B>(): type_info::TypeInfo {
126+
// Pass on the 2nd type parameter to be sure the instantiation
127+
// of B is correctly handled
128+
type_info::type_of<B>()
129+
}
130+
119131
}
120132

121133
module 0x43::test {

third_party/move/tools/move-cli/src/base/prove.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ pub fn run_move_prover(
230230
} else {
231231
"FAILURE".bold().red()
232232
},
233-
model.get_target_modules().len(),
233+
model.get_primary_target_modules().len(),
234234
basedir,
235235
now.elapsed().as_secs_f64()
236236
)?;

0 commit comments

Comments
 (0)