11use std:: {
2+ convert:: Infallible ,
23 fs, io,
34 ops:: Range ,
45 path:: { Path , PathBuf } ,
@@ -84,17 +85,17 @@ impl TypeItem {
8485}
8586
8687#[ derive( Clone , Debug ) ]
87- pub struct HermesDecorated < T , A = std :: convert :: Infallible > {
88+ pub struct HermesDecorated < T , A = Infallible > {
8889 pub item : T ,
8990 pub hermes : attr:: HermesBlock < A > ,
9091}
9192
9293#[ derive( Clone , Debug ) ]
9394pub enum ParsedItem {
9495 Function ( HermesDecorated < FunctionItem , attr:: HermesAttr > ) ,
95- Type ( HermesDecorated < TypeItem , std :: convert :: Infallible > ) ,
96- Trait ( HermesDecorated < ItemTrait , std :: convert :: Infallible > ) ,
97- Impl ( HermesDecorated < ItemImpl , std :: convert :: Infallible > ) ,
96+ Type ( HermesDecorated < TypeItem , Infallible > ) ,
97+ Trait ( HermesDecorated < ItemTrait , Infallible > ) ,
98+ Impl ( HermesDecorated < ItemImpl , Infallible > ) ,
9899}
99100
100101impl ParsedItem {
@@ -118,41 +119,41 @@ impl ParsedItem {
118119 }
119120}
120121
121- fn convert_block_infallible (
122+ /// Convert from a pair of `item` and `block: HermesBlock<HermesAttr>` to a
123+ /// `HermesDecorated<Infallible>`, erroring if the `block` has an attribute.
124+ ///
125+ /// On success, pass the `HermesDecorate<Infallible>` to `f`.
126+ fn try_from_raw_reject_attr < T , F : FnOnce ( HermesDecorated < T > ) -> ParsedItem > (
127+ item : T ,
122128 block : attr:: HermesBlock < attr:: HermesAttr > ,
123- ) -> Result < attr:: HermesBlock < std:: convert:: Infallible > , HermesError > {
129+ f : F ,
130+ ) -> Result < ParsedItem , HermesError > {
124131 if let Some ( _attr) = block. attribute {
125132 return Err ( HermesError :: DocBlockError {
126- src : NamedSource :: new ( "TODO" , "TODO" . to_string ( ) ) , // We fix this up in process_item
133+ // TODO
134+ src : NamedSource :: new ( "TODO" , "TODO" . to_string ( ) ) ,
127135 span : span_to_miette ( block. start_span ) ,
128136 msg : "This item does not support Hermes attributes (like `spec` or `unsafe(axiom)`). Only generic `hermes` blocks are allowed." . to_string ( ) ,
129137 } ) ;
130138 }
131- Ok ( attr:: HermesBlock {
132- attribute : None ,
133- content : block. content ,
134- content_span : block. content_span ,
135- start_span : block. start_span ,
136- } )
139+ Ok ( f ( HermesDecorated {
140+ item,
141+ hermes : attr:: HermesBlock {
142+ attribute : None ,
143+ content : block. content ,
144+ content_span : block. content_span ,
145+ start_span : block. start_span ,
146+ } ,
147+ } ) )
137148}
138149
139- fn try_from_raw_reject_attr < T , F : FnOnce ( HermesDecorated < T > ) -> ParsedItem > (
140- item : T ,
141- block : attr:: HermesBlock < attr:: HermesAttr > ,
142- f : F ,
143- ) -> Result < ParsedItem , HermesError > {
144- let hermes = convert_block_infallible ( block) ?;
145- Ok ( f ( HermesDecorated { item, hermes } ) )
146- }
150+ // TODO: Merge this with `HermesDecorated`?
147151
148- /// A complete parsed item including its module path and the extracted Lean block .
152+ /// A complete parsed item including its module path and source file .
149153#[ derive( Debug ) ]
150154pub struct ParsedLeanItem {
151155 pub item : ParsedItem ,
152156 pub module_path : Vec < String > ,
153- #[ allow( dead_code) ] // TODO: Remove if truly unused
154- lean_block : String ,
155- #[ allow( dead_code) ]
156157 source_file : Option < PathBuf > ,
157158}
158159
@@ -273,7 +274,6 @@ where
273274 I : FnMut ( & str , Result < ParsedLeanItem , HermesError > ) ,
274275 M : FnMut ( UnloadedModule ) ,
275276{
276- //fn try_from_raw_reject_attr<T, F: FnOnce(T) -> ParsedItem + Default>(item: T, attr: Option<attr::HermesAttr>) -> Result<ParsedItem, HermesError> {
277277 fn process_item <
278278 T ,
279279 F : FnOnce ( T , attr:: HermesBlock < attr:: HermesAttr > ) -> Result < ParsedItem , HermesError > ,
@@ -286,9 +286,10 @@ where
286286 ) {
287287 let block = match attr:: extract_hermes_block ( attrs) {
288288 Ok ( Some ( b) ) => b,
289- Ok ( None ) => return , // No Hermes block, skip
289+ // This item doesn't have a Hermes annotation; skip it.
290+ Ok ( None ) => return ,
290291 Err ( e) => {
291- debug ! ( "Error extracting ```lean block: {}" , e) ;
292+ log :: trace !( "Error extracting ```lean block: {}" , e) ;
292293 ( self . item_cb ) (
293294 & self . source_code . as_str ( ) [ span. byte_range ( ) ] ,
294295 Err ( HermesError :: DocBlockError {
@@ -302,26 +303,27 @@ where
302303 } ;
303304
304305 if self . inside_block {
305- ( self . item_cb ) (
306+ ( self . item_cb ) (
306307 & self . source_code . as_str ( ) [ span. byte_range ( ) ] ,
307308 Err ( HermesError :: NestedItemError {
308309 src : self . named_source . clone ( ) ,
309310 span : span_to_miette ( span) ,
310- msg : "Hermes cannot verify items defined inside function bodies or other blocks." . to_string ( ) ,
311+ msg :
312+ "Hermes cannot verify items defined inside function bodies or other blocks."
313+ . to_string ( ) ,
311314 } ) ,
312315 ) ;
313316 return ;
314317 }
315318
316- let Range { start, end } = span. byte_range ( ) ;
317- let source = & self . source_code . as_str ( ) [ start..end] ;
319+ let source = & self . source_code . as_str ( ) [ span. byte_range ( ) ] ;
318320
319- // Clone fields needed for ParsedLeanItem construction before moving block
320- let lean_block_content = block. content . clone ( ) ;
321-
322321 let parsed_item = match f ( item, block) {
323322 Ok ( i) => i,
324323 Err ( mut e) => {
324+ // TODO: What is the point of this? Why are we special-casing
325+ // `TODO`?
326+
325327 // If it's a DocBlockError that needs source context, ensure we provide it
326328 if let HermesError :: DocBlockError { src, .. } = & mut e {
327329 if src. name ( ) == "TODO" {
@@ -338,7 +340,6 @@ where
338340 Ok ( ParsedLeanItem {
339341 item : parsed_item,
340342 module_path : self . current_path . clone ( ) ,
341- lean_block : lean_block_content,
342343 source_file : self . source_file . clone ( ) ,
343344 } ) ,
344345 ) ;
@@ -353,7 +354,7 @@ where
353354 fn visit_item_mod ( & mut self , node : & ' ast ItemMod ) {
354355 let mod_name = node. ident . to_string ( ) ;
355356
356- // Check for unloaded modules ( mod foo;)
357+ // Unloaded module (i.e., ` mod foo;`).
357358 if node. content . is_none ( ) {
358359 ( self . mod_cb ) ( UnloadedModule {
359360 name : mod_name. clone ( ) ,
@@ -383,31 +384,46 @@ where
383384 fn visit_item_fn ( & mut self , node : & ' ast ItemFn ) {
384385 trace ! ( "Visiting Fn {}" , node. sig. ident) ;
385386 self . process_item ( node. clone ( ) , node. attrs . as_slice ( ) , node. span ( ) , |item, block| {
386- Ok ( ParsedItem :: Function ( HermesDecorated { item : FunctionItem :: Free ( item) , hermes : block } ) )
387+ Ok ( ParsedItem :: Function ( HermesDecorated {
388+ item : FunctionItem :: Free ( item) ,
389+ hermes : block,
390+ } ) )
387391 } ) ;
388392 syn:: visit:: visit_item_fn ( self , node) ;
389393 }
390394
391395 fn visit_item_struct ( & mut self , node : & ' ast ItemStruct ) {
392396 trace ! ( "Visiting Struct {}" , node. ident) ;
393397 self . process_item ( node. clone ( ) , node. attrs . as_slice ( ) , node. span ( ) , |item, block| {
394- try_from_raw_reject_attr ( item, block, |d| ParsedItem :: Type ( HermesDecorated { item : TypeItem :: Struct ( d. item ) , hermes : d. hermes } ) )
398+ try_from_raw_reject_attr ( item, block, |d| {
399+ ParsedItem :: Type ( HermesDecorated {
400+ item : TypeItem :: Struct ( d. item ) ,
401+ hermes : d. hermes ,
402+ } )
403+ } )
395404 } ) ;
396405 syn:: visit:: visit_item_struct ( self , node) ;
397406 }
398407
399408 fn visit_item_enum ( & mut self , node : & ' ast ItemEnum ) {
400409 trace ! ( "Visiting Enum {}" , node. ident) ;
401410 self . process_item ( node. clone ( ) , node. attrs . as_slice ( ) , node. span ( ) , |item, block| {
402- try_from_raw_reject_attr ( item, block, |d| ParsedItem :: Type ( HermesDecorated { item : TypeItem :: Enum ( d. item ) , hermes : d. hermes } ) )
411+ try_from_raw_reject_attr ( item, block, |d| {
412+ ParsedItem :: Type ( HermesDecorated { item : TypeItem :: Enum ( d. item ) , hermes : d. hermes } )
413+ } )
403414 } ) ;
404415 syn:: visit:: visit_item_enum ( self , node) ;
405416 }
406417
407418 fn visit_item_union ( & mut self , node : & ' ast ItemUnion ) {
408419 trace ! ( "Visiting Union {}" , node. ident) ;
409420 self . process_item ( node. clone ( ) , node. attrs . as_slice ( ) , node. span ( ) , |item, block| {
410- try_from_raw_reject_attr ( item, block, |d| ParsedItem :: Type ( HermesDecorated { item : TypeItem :: Union ( d. item ) , hermes : d. hermes } ) )
421+ try_from_raw_reject_attr ( item, block, |d| {
422+ ParsedItem :: Type ( HermesDecorated {
423+ item : TypeItem :: Union ( d. item ) ,
424+ hermes : d. hermes ,
425+ } )
426+ } )
411427 } ) ;
412428 syn:: visit:: visit_item_union ( self , node) ;
413429 }
@@ -442,15 +458,21 @@ where
442458 fn visit_impl_item_fn ( & mut self , node : & ' ast ImplItemFn ) {
443459 trace ! ( "Visiting ImplItemFn {}" , node. sig. ident) ;
444460 self . process_item ( node. clone ( ) , node. attrs . as_slice ( ) , node. span ( ) , |item, block| {
445- Ok ( ParsedItem :: Function ( HermesDecorated { item : FunctionItem :: Impl ( item) , hermes : block } ) )
461+ Ok ( ParsedItem :: Function ( HermesDecorated {
462+ item : FunctionItem :: Impl ( item) ,
463+ hermes : block,
464+ } ) )
446465 } ) ;
447466 syn:: visit:: visit_impl_item_fn ( self , node) ;
448467 }
449468
450469 fn visit_trait_item_fn ( & mut self , node : & ' ast TraitItemFn ) {
451470 trace ! ( "Visiting TraitItemFn {}" , node. sig. ident) ;
452471 self . process_item ( node. clone ( ) , node. attrs . as_slice ( ) , node. span ( ) , |item, block| {
453- Ok ( ParsedItem :: Function ( HermesDecorated { item : FunctionItem :: Trait ( item) , hermes : block } ) )
472+ Ok ( ParsedItem :: Function ( HermesDecorated {
473+ item : FunctionItem :: Trait ( item) ,
474+ hermes : block,
475+ } ) )
454476 } ) ;
455477 syn:: visit:: visit_trait_item_fn ( self , node) ;
456478 }
@@ -460,7 +482,6 @@ where
460482/// Returns `Ok(None)` if no block is found.
461483/// Returns `Err` if the block is malformed or multiple blocks are found.
462484
463-
464485/// Extracts the `...` from the first `#[path = "..."]` attribute found, if any.
465486fn extract_path_attr ( attrs : & [ Attribute ] ) -> Option < String > {
466487 for attr in attrs {
@@ -511,8 +532,6 @@ fn span_to_miette(span: proc_macro2::Span) -> SourceSpan {
511532}
512533
513534mod attr {
514- use std:: convert:: Infallible ;
515-
516535 use proc_macro2:: Span ;
517536
518537 use super :: * ;
@@ -600,7 +619,9 @@ mod attr {
600619 }
601620
602621 /// Helper to parse and extract a single Hermes block from a slice of attributes.
603- pub fn extract_hermes_block ( attrs : & [ Attribute ] ) -> Result < Option < HermesBlock < HermesAttr > > , Error > {
622+ pub fn extract_hermes_block (
623+ attrs : & [ Attribute ] ,
624+ ) -> Result < Option < HermesBlock < HermesAttr > > , Error > {
604625 let mut found_block: Option < HermesBlock < HermesAttr > > = None ;
605626 let mut iter = attrs. iter ( ) . peekable ( ) ;
606627
@@ -812,17 +833,17 @@ mod tests {
812833 "# ;
813834 let items = parse_to_vec ( code) ;
814835 assert_eq ! ( items. len( ) , 2 ) ;
815-
836+
816837 let ( src1, item1) = & items[ 0 ] ;
817838 let ( src2, item2) = & items[ 1 ] ;
818-
839+
819840 let i1 = item1. as_ref ( ) . unwrap ( ) ;
820841 let i2 = item2. as_ref ( ) . unwrap ( ) ;
821-
842+
822843 // Verify we got the right blocks for the right items
823844 assert ! ( i1. lean_block. contains( "theorem a" ) ) ;
824845 assert ! ( i2. lean_block. contains( "theorem b" ) ) ;
825-
846+
826847 // Verify source snippets match the function definition + doc comment
827848 assert ! ( src1. contains( "theorem a" ) ) ;
828849 assert ! ( src1. contains( "fn foo" ) ) ;
0 commit comments