|
36 | 36 | /// - Refer to `examples/syntax_attr.rs`. |
37 | 37 | use proc_macro2::TokenStream; |
38 | 38 | use quote::{ToTokens, quote, quote_spanned}; |
| 39 | +use syn::parse::Parser; |
39 | 40 | use syn::visit_mut::VisitMut; |
40 | 41 | use syn::{Expr, Item, ItemConst, parse2, spanned::Spanned}; |
41 | 42 |
|
@@ -526,14 +527,92 @@ pub(crate) fn rewrite_verus_spec_on_fun_or_loop( |
526 | 527 | fun.attrs.retain(|attr| !is_hidden_impl_marker(attr)); |
527 | 528 |
|
528 | 529 | let mut new_stream = TokenStream::new(); |
| 530 | + let mut rustdoc_attrs: Vec<syn::Attribute> = vec![]; |
| 531 | + if crate::rustdoc::env_rustdoc() { |
| 532 | + let mut verus_fun: verus_syn::ItemFn = syn_to_verus_syn(fun.clone()); |
| 533 | + verus_fun.sig.spec = spec_attr.spec.clone(); |
| 534 | + |
| 535 | + // Set return variable name |
| 536 | + if let Some((verus_syn::Pat::Ident(pat_ident), _)) = &spec_attr.ret_pat { |
| 537 | + if let verus_syn::ReturnType::Type(_, _, opt_name, _) = |
| 538 | + &mut verus_fun.sig.output |
| 539 | + { |
| 540 | + *opt_name = Some(Box::new(( |
| 541 | + verus_syn::token::Paren::default(), |
| 542 | + verus_syn::Pat::Ident(pat_ident.clone()), |
| 543 | + verus_syn::Token), |
| 544 | + ))); |
| 545 | + } |
| 546 | + } |
| 547 | + |
| 548 | + crate::rustdoc::process_item_fn(&mut verus_fun); |
| 549 | + |
| 550 | + for attr in &verus_fun.attrs { |
| 551 | + if attr.path().is_ident("doc") |
| 552 | + && attr.to_token_stream().to_string().contains("verusdoc_special_attr") |
| 553 | + { |
| 554 | + if let Ok(doc_attrs) = |
| 555 | + syn::Attribute::parse_outer.parse(attr.to_token_stream().into()) |
| 556 | + { |
| 557 | + rustdoc_attrs.extend(doc_attrs); |
| 558 | + } |
| 559 | + } |
| 560 | + } |
| 561 | + } |
529 | 562 |
|
530 | 563 | // Create a copy of unverified function. |
531 | 564 | // To avoid misuse of the unverified function, |
532 | 565 | // we add `requires false` and thus prevent verified function to use it. |
533 | 566 | // Allow unverified code to use the function without changing in/output. |
534 | 567 | if let Some(with) = &spec_attr.spec.with { |
535 | | - let extra_funs = rewrite_unverified_func(&mut fun, with.with.span(), erase); |
| 568 | + let mut extra_funs = rewrite_unverified_func(&mut fun, with.with.span(), erase); |
| 569 | + |
| 570 | + if crate::rustdoc::env_rustdoc() { |
| 571 | + if let Some(unverified_fun) = extra_funs.last_mut() { |
| 572 | + unverified_fun.attrs.extend(rustdoc_attrs.clone()); |
| 573 | + } |
| 574 | + fun.attrs.push(crate::syntax::mk_rust_attr_syn( |
| 575 | + with.with.span(), |
| 576 | + "doc", |
| 577 | + quote! {hidden}, |
| 578 | + )); |
| 579 | + } |
536 | 580 | extra_funs.iter().for_each(|f| f.to_tokens(&mut new_stream)); |
| 581 | + } else if crate::rustdoc::env_rustdoc() { |
| 582 | + fun.attrs.extend(rustdoc_attrs); |
| 583 | + } |
| 584 | + |
| 585 | + // Inject doc attribute in rustdoc mode |
| 586 | + if crate::rustdoc::env_rustdoc() { |
| 587 | + let mut verus_fun: verus_syn::ItemFn = syn_to_verus_syn(fun.clone()); |
| 588 | + verus_fun.sig.spec = spec_attr.spec.clone(); |
| 589 | + |
| 590 | + // Set return variable name |
| 591 | + if let Some((verus_syn::Pat::Ident(pat_ident), _)) = &spec_attr.ret_pat { |
| 592 | + if let verus_syn::ReturnType::Type(_, _, opt_name, _) = |
| 593 | + &mut verus_fun.sig.output |
| 594 | + { |
| 595 | + *opt_name = Some(Box::new(( |
| 596 | + verus_syn::token::Paren::default(), |
| 597 | + verus_syn::Pat::Ident(pat_ident.clone()), |
| 598 | + verus_syn::Token), |
| 599 | + ))); |
| 600 | + } |
| 601 | + } |
| 602 | + |
| 603 | + crate::rustdoc::process_item_fn(&mut verus_fun); |
| 604 | + |
| 605 | + for attr in &verus_fun.attrs { |
| 606 | + if attr.path().is_ident("doc") |
| 607 | + && attr.to_token_stream().to_string().contains("verusdoc_special_attr") |
| 608 | + { |
| 609 | + if let Ok(doc_attrs) = |
| 610 | + syn::Attribute::parse_outer.parse(attr.to_token_stream().into()) |
| 611 | + { |
| 612 | + fun.attrs.extend(doc_attrs); |
| 613 | + } |
| 614 | + } |
| 615 | + } |
537 | 616 | } |
538 | 617 |
|
539 | 618 | // Update function signature based on verus_spec. |
@@ -936,6 +1015,13 @@ fn rewrite_unverified_func( |
936 | 1015 | Some(syn::token::Semi { spans: [span] }), |
937 | 1016 | ); |
938 | 1017 | unverified_fun.attrs_mut().push(mk_verus_attr_syn(span, quote! { external_body })); |
| 1018 | + if !crate::rustdoc::env_rustdoc() { |
| 1019 | + unverified_fun.attrs_mut().push(crate::syntax::mk_rust_attr_syn( |
| 1020 | + span, |
| 1021 | + "doc", |
| 1022 | + quote! {hidden}, |
| 1023 | + )); |
| 1024 | + } |
939 | 1025 | if let Some(block) = unverified_fun.block_mut() { |
940 | 1026 | // For an unverified function, if it is in keep mode, |
941 | 1027 | // we erase the function body to avoid using |
|
0 commit comments