| 563 | } |
| 564 | |
| 565 | pub fn extract_prusti_attributes( |
| 566 | item: &mut CheckableItem, |
| 567 | ) -> Vec<(SpecAttributeKind, TokenStream)> { |
| 568 | let mut prusti_attributes = Vec::new(); |
| 569 | let mut regular_attributes = Vec::new(); |
| 570 | for attr in item.attrs_mut().drain(0..) { |
| 571 | if attr.path.segments.len() == 1 { |
| 572 | if let Ok(attr_kind) = attr.path.segments[0].ident.to_string().try_into() { |
| 573 | let tokens = match attr_kind { |
| 574 | SpecAttributeKind::Requires |
| 575 | | SpecAttributeKind::Ensures |
| 576 | | SpecAttributeKind::AfterExpiry |
| 577 | | SpecAttributeKind::AfterExpiryIf => { |
| 578 | // We need to drop the surrounding parenthesis to make the |
| 579 | // tokens identical to the ones passed by the native procedural |
| 580 | // macro call. |
| 581 | let mut iter = attr.tokens.into_iter(); |
| 582 | let tokens = force_matches!(iter.next().unwrap(), TokenTree::Group(group) => group.stream()); |
| 583 | assert!(iter.next().is_none(), "Unexpected shape of an attribute."); |
| 584 | tokens |
| 585 | } |
| 586 | // Nothing to do for attributes without arguments. |
| 587 | SpecAttributeKind::Pure |
| 588 | | SpecAttributeKind::Trusted |
| 589 | | SpecAttributeKind::Predicate => { |
| 590 | assert!(attr.tokens.is_empty(), "Unexpected shape of an attribute."); |
| 591 | attr.tokens |
| 592 | } |
| 593 | }; |
| 594 | prusti_attributes.push((attr_kind, tokens)); |
| 595 | } else { |
| 596 | regular_attributes.push(attr); |
| 597 | } |
| 598 | } else { |
| 599 | regular_attributes.push(attr); |
| 600 | } |
| 601 | } |
| 602 | *item.attrs_mut() = regular_attributes; |
| 603 | prusti_attributes |
| 604 | } |