|
1 | 1 | use crate::parse::{ |
2 | 2 | FunctionItem, ParsedItem, TypeItem, |
3 | | - attr::{ |
4 | | - Clause, FunctionAnnealBlock, FunctionBlockInner, SpannedLine, TraitAnnealBlock, |
5 | | - TypeAnnealBlock, |
6 | | - }, |
| 3 | + attr::{Clause, FunctionBlockInner, SpannedLine, TraitAnnealBlock, TypeAnnealBlock}, |
7 | 4 | hkd::AstNode, |
8 | 5 | }; |
9 | 6 |
|
@@ -238,9 +235,7 @@ pub fn generate_item( |
238 | 235 | naming_context: &NamingContext, |
239 | 236 | ) { |
240 | 237 | match &item.item { |
241 | | - ParsedItem::Function(func) => { |
242 | | - generate_function(&func.item, &func.anneal, builder, &item.source_file, naming_context) |
243 | | - } |
| 238 | + ParsedItem::Function(_) => generate_function(item, builder, naming_context), |
244 | 239 | ParsedItem::Type(ty) => { |
245 | 240 | generate_type(&ty.item, &ty.anneal, builder, &item.source_file, naming_context) |
246 | 241 | } |
@@ -566,12 +561,17 @@ impl LeanBuilder { |
566 | 561 | /// by ... |
567 | 562 | /// ``` |
568 | 563 | fn generate_function( |
569 | | - func: &FunctionItem<crate::parse::hkd::Safe>, |
570 | | - block: &FunctionAnnealBlock<crate::parse::hkd::Safe>, |
| 564 | + item: &crate::parse::ParsedLeanItem<crate::parse::hkd::Safe>, |
571 | 565 | builder: &mut LeanBuilder, |
572 | | - source_file: &std::path::Path, |
573 | 566 | naming_context: &NamingContext, |
574 | 567 | ) { |
| 568 | + let ParsedItem::Function(decorated_func) = &item.item else { |
| 569 | + unreachable!("generate_function must be called with a function item"); |
| 570 | + }; |
| 571 | + let func = &decorated_func.item; |
| 572 | + let block = &decorated_func.anneal; |
| 573 | + let source_file = item.source_file.as_path(); |
| 574 | + |
575 | 575 | let (fn_name, fn_span, impl_struct_name, generic_params, generic_bounds, dict_args) = match func |
576 | 576 | { |
577 | 577 | FunctionItem::Free(n) => { |
@@ -677,23 +677,8 @@ fn generate_function( |
677 | 677 | let has_args = !args.is_empty(); |
678 | 678 | let generate_pre = has_args || !prop_requires.is_empty(); |
679 | 679 |
|
680 | | - let aeneas_fn_name = naming_context.aeneas_call_name(&crate::parse::ParsedLeanItem { |
681 | | - item: ParsedItem::Function(crate::parse::AnnealDecorated { |
682 | | - item: func.clone(), |
683 | | - anneal: block.clone(), |
684 | | - }), |
685 | | - module_path: Vec::new(), |
686 | | - source_file: source_file.to_path_buf(), |
687 | | - }); |
688 | | - |
689 | | - let aeneas_namespace = naming_context.item_namespace(&crate::parse::ParsedLeanItem { |
690 | | - item: ParsedItem::Function(crate::parse::AnnealDecorated { |
691 | | - item: func.clone(), |
692 | | - anneal: block.clone(), |
693 | | - }), |
694 | | - module_path: Vec::new(), |
695 | | - source_file: source_file.to_path_buf(), |
696 | | - }); |
| 680 | + let aeneas_fn_name = naming_context.aeneas_call_name(item); |
| 681 | + let aeneas_namespace = naming_context.item_namespace(item); |
697 | 682 | let fully_qualified_fnc = if aeneas_namespace.is_empty() { |
698 | 683 | format!("_root_.{}.{}", naming_context.crate_name, aeneas_fn_name) |
699 | 684 | } else { |
@@ -929,14 +914,7 @@ fn generate_function( |
929 | 914 | provided_cases, |
930 | 915 | exact_fields, |
931 | 916 | source_file, |
932 | | - spec_name: naming_context.item_spec_name(&crate::parse::ParsedLeanItem { |
933 | | - item: ParsedItem::Function(crate::parse::AnnealDecorated { |
934 | | - item: func.clone(), |
935 | | - anneal: block.clone(), |
936 | | - }), |
937 | | - module_path: Vec::new(), |
938 | | - source_file: source_file.to_path_buf(), |
939 | | - }), |
| 917 | + spec_name: naming_context.item_spec_name(item), |
940 | 918 | aeneas_fn_name: fully_qualified_fnc, |
941 | 919 | }); |
942 | 920 |
|
@@ -1338,7 +1316,7 @@ mod tests { |
1338 | 1316 |
|
1339 | 1317 | use super::*; |
1340 | 1318 | use crate::parse::{ |
1341 | | - attr::{AnnealBlockCommon, Clause, FunctionBlockInner, Propositions}, |
| 1319 | + attr::{AnnealBlockCommon, Clause, FunctionAnnealBlock, FunctionBlockInner, Propositions}, |
1342 | 1320 | hkd::{Mirror, Safe}, |
1343 | 1321 | }; |
1344 | 1322 |
|
@@ -1424,6 +1402,44 @@ mod tests { |
1424 | 1402 | } |
1425 | 1403 | } |
1426 | 1404 |
|
| 1405 | + fn mk_function_item( |
| 1406 | + module_path: Vec<&str>, |
| 1407 | + func: &FunctionItem<crate::parse::hkd::Safe>, |
| 1408 | + block: &FunctionAnnealBlock<crate::parse::hkd::Safe>, |
| 1409 | + source_file: &Path, |
| 1410 | + ) -> crate::parse::ParsedLeanItem<crate::parse::hkd::Safe> { |
| 1411 | + crate::parse::ParsedLeanItem { |
| 1412 | + item: ParsedItem::Function(crate::parse::AnnealDecorated { |
| 1413 | + item: func.clone(), |
| 1414 | + anneal: block.clone(), |
| 1415 | + }), |
| 1416 | + module_path: module_path.into_iter().map(|part| part.to_string()).collect(), |
| 1417 | + source_file: source_file.to_path_buf(), |
| 1418 | + } |
| 1419 | + } |
| 1420 | + |
| 1421 | + fn generate_function( |
| 1422 | + func: &FunctionItem<crate::parse::hkd::Safe>, |
| 1423 | + block: &FunctionAnnealBlock<crate::parse::hkd::Safe>, |
| 1424 | + builder: &mut LeanBuilder, |
| 1425 | + source_file: &Path, |
| 1426 | + naming_context: &NamingContext, |
| 1427 | + ) { |
| 1428 | + generate_function_in_path(vec!["crate"], func, block, builder, source_file, naming_context); |
| 1429 | + } |
| 1430 | + |
| 1431 | + fn generate_function_in_path( |
| 1432 | + module_path: Vec<&str>, |
| 1433 | + func: &FunctionItem<crate::parse::hkd::Safe>, |
| 1434 | + block: &FunctionAnnealBlock<crate::parse::hkd::Safe>, |
| 1435 | + builder: &mut LeanBuilder, |
| 1436 | + source_file: &Path, |
| 1437 | + naming_context: &NamingContext, |
| 1438 | + ) { |
| 1439 | + let item = mk_function_item(module_path, func, block, source_file); |
| 1440 | + super::generate_function(&item, builder, naming_context); |
| 1441 | + } |
| 1442 | + |
1427 | 1443 | // --- Type Mapping Tests --- |
1428 | 1444 |
|
1429 | 1445 | #[test] |
@@ -2802,4 +2818,26 @@ mod tests { |
2802 | 2818 | ); |
2803 | 2819 | } |
2804 | 2820 | } |
| 2821 | + |
| 2822 | + #[test] |
| 2823 | + fn test_generate_function_preserves_module_path_in_proof_tactics() { |
| 2824 | + let item: syn::ItemFn = parse_quote! { fn nested(x: u32) -> u32 { x } }; |
| 2825 | + let func = FunctionItem::Free(AstNode { inner: item.mirror() }); |
| 2826 | + let block = mk_block(vec![vec!["x > 0"]], vec![], Some(vec!["exact rfl"]), None, vec![]); |
| 2827 | + |
| 2828 | + let mut builder = LeanBuilder::new(); |
| 2829 | + let naming_context = NamingContext::new("test".to_string()); |
| 2830 | + generate_function_in_path( |
| 2831 | + vec!["crate", "outer", "inner"], |
| 2832 | + &func, |
| 2833 | + &block, |
| 2834 | + &mut builder, |
| 2835 | + Path::new("test.rs"), |
| 2836 | + &naming_context, |
| 2837 | + ); |
| 2838 | + let out = builder.buf; |
| 2839 | + |
| 2840 | + assert!(out.contains("verify_is_valid h_x_is_valid _root_.test.outer.inner.nested")); |
| 2841 | + assert!(out.contains("verify_user_bound h_anon _root_.test.outer.inner.nested")); |
| 2842 | + } |
2805 | 2843 | } |
0 commit comments