|
1 | 1 | use std::path::PathBuf; |
2 | 2 |
|
3 | 3 | use rustc_ast::{LitIntType, LitKind, MetaItemLit}; |
4 | | -use rustc_hir::attrs::{BorrowckGraphvizFormatKind, RustcLayoutType, RustcMirKind}; |
| 4 | +use rustc_hir::attrs::{ |
| 5 | + BorrowckGraphvizFormatKind, RustcCleanAttribute, RustcCleanQueries, RustcLayoutType, |
| 6 | + RustcMirKind, |
| 7 | +}; |
5 | 8 | use rustc_session::errors; |
| 9 | +use rustc_span::Symbol; |
6 | 10 |
|
7 | 11 | use super::prelude::*; |
8 | 12 | use super::util::parse_single_integer; |
9 | | -use crate::session_diagnostics::RustcScalableVectorCountOutOfRange; |
| 13 | +use crate::session_diagnostics::{AttributeRequiresOpt, RustcScalableVectorCountOutOfRange}; |
10 | 14 |
|
11 | 15 | pub(crate) struct RustcMainParser; |
12 | 16 |
|
@@ -234,7 +238,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcLintUntrackedQueryInformationPa |
234 | 238 | pub(crate) struct RustcObjectLifetimeDefaultParser; |
235 | 239 |
|
236 | 240 | impl<S: Stage> SingleAttributeParser<S> for RustcObjectLifetimeDefaultParser { |
237 | | - const PATH: &[rustc_span::Symbol] = &[sym::rustc_object_lifetime_default]; |
| 241 | + const PATH: &[Symbol] = &[sym::rustc_object_lifetime_default]; |
238 | 242 | const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; |
239 | 243 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; |
240 | 244 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); |
@@ -271,7 +275,7 @@ impl<S: Stage> SingleAttributeParser<S> for RustcSimdMonomorphizeLaneLimitParser |
271 | 275 | pub(crate) struct RustcScalableVectorParser; |
272 | 276 |
|
273 | 277 | impl<S: Stage> SingleAttributeParser<S> for RustcScalableVectorParser { |
274 | | - const PATH: &[rustc_span::Symbol] = &[sym::rustc_scalable_vector]; |
| 278 | + const PATH: &[Symbol] = &[sym::rustc_scalable_vector]; |
275 | 279 | const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; |
276 | 280 | const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; |
277 | 281 | const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]); |
@@ -344,7 +348,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcOffloadKernelParser { |
344 | 348 | pub(crate) struct RustcLayoutParser; |
345 | 349 |
|
346 | 350 | impl<S: Stage> CombineAttributeParser<S> for RustcLayoutParser { |
347 | | - const PATH: &[rustc_span::Symbol] = &[sym::rustc_layout]; |
| 351 | + const PATH: &[Symbol] = &[sym::rustc_layout]; |
348 | 352 |
|
349 | 353 | type Item = RustcLayoutType; |
350 | 354 |
|
@@ -401,7 +405,7 @@ impl<S: Stage> CombineAttributeParser<S> for RustcLayoutParser { |
401 | 405 | pub(crate) struct RustcMirParser; |
402 | 406 |
|
403 | 407 | impl<S: Stage> CombineAttributeParser<S> for RustcMirParser { |
404 | | - const PATH: &[rustc_span::Symbol] = &[sym::rustc_mir]; |
| 408 | + const PATH: &[Symbol] = &[sym::rustc_mir]; |
405 | 409 |
|
406 | 410 | type Item = RustcMirKind; |
407 | 411 |
|
@@ -497,3 +501,223 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcNonConstTraitMethodParser { |
497 | 501 | ]); |
498 | 502 | const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod; |
499 | 503 | } |
| 504 | + |
| 505 | +pub(crate) struct RustcCleanParser; |
| 506 | + |
| 507 | +impl<S: Stage> CombineAttributeParser<S> for RustcCleanParser { |
| 508 | + const PATH: &[Symbol] = &[sym::rustc_clean]; |
| 509 | + |
| 510 | + type Item = RustcCleanAttribute; |
| 511 | + |
| 512 | + const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcClean(items); |
| 513 | + |
| 514 | + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 515 | + // tidy-alphabetical-start |
| 516 | + Allow(Target::AssocConst), |
| 517 | + Allow(Target::AssocTy), |
| 518 | + Allow(Target::Const), |
| 519 | + Allow(Target::Enum), |
| 520 | + Allow(Target::Expression), |
| 521 | + Allow(Target::Field), |
| 522 | + Allow(Target::Fn), |
| 523 | + Allow(Target::ForeignMod), |
| 524 | + Allow(Target::Impl { of_trait: false }), |
| 525 | + Allow(Target::Impl { of_trait: true }), |
| 526 | + Allow(Target::Method(MethodKind::Inherent)), |
| 527 | + Allow(Target::Method(MethodKind::Trait { body: false })), |
| 528 | + Allow(Target::Method(MethodKind::Trait { body: true })), |
| 529 | + Allow(Target::Method(MethodKind::TraitImpl)), |
| 530 | + Allow(Target::Mod), |
| 531 | + Allow(Target::Static), |
| 532 | + Allow(Target::Struct), |
| 533 | + Allow(Target::Trait), |
| 534 | + Allow(Target::TyAlias), |
| 535 | + Allow(Target::Union), |
| 536 | + // tidy-alphabetical-end |
| 537 | + ]); |
| 538 | + |
| 539 | + const TEMPLATE: AttributeTemplate = |
| 540 | + template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]); |
| 541 | + |
| 542 | + fn extend( |
| 543 | + cx: &mut AcceptContext<'_, '_, S>, |
| 544 | + args: &ArgParser, |
| 545 | + ) -> impl IntoIterator<Item = Self::Item> { |
| 546 | + if !cx.cx.sess.opts.unstable_opts.query_dep_graph { |
| 547 | + cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" }); |
| 548 | + } |
| 549 | + let Some(list) = args.list() else { |
| 550 | + cx.expected_list(cx.attr_span, args); |
| 551 | + return None; |
| 552 | + }; |
| 553 | + let mut except = None; |
| 554 | + let mut loaded_from_disk = None; |
| 555 | + let mut cfg = None; |
| 556 | + |
| 557 | + for item in list.mixed() { |
| 558 | + let Some((value, name)) = |
| 559 | + item.meta_item().and_then(|m| Option::zip(m.args().name_value(), m.ident())) |
| 560 | + else { |
| 561 | + cx.expected_name_value(item.span(), None); |
| 562 | + continue; |
| 563 | + }; |
| 564 | + let value_span = value.value_span; |
| 565 | + let Some(value) = value.value_as_str() else { |
| 566 | + cx.expected_string_literal(value_span, None); |
| 567 | + continue; |
| 568 | + }; |
| 569 | + match name.name { |
| 570 | + sym::cfg if cfg.is_some() => { |
| 571 | + cx.duplicate_key(item.span(), sym::cfg); |
| 572 | + } |
| 573 | + |
| 574 | + sym::cfg => { |
| 575 | + cfg = Some(value); |
| 576 | + } |
| 577 | + sym::except if except.is_some() => { |
| 578 | + cx.duplicate_key(item.span(), sym::except); |
| 579 | + } |
| 580 | + sym::except => { |
| 581 | + let entries = |
| 582 | + value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect(); |
| 583 | + except = Some(RustcCleanQueries { entries, span: value_span }); |
| 584 | + } |
| 585 | + sym::loaded_from_disk if loaded_from_disk.is_some() => { |
| 586 | + cx.duplicate_key(item.span(), sym::loaded_from_disk); |
| 587 | + } |
| 588 | + sym::loaded_from_disk => { |
| 589 | + let entries = |
| 590 | + value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect(); |
| 591 | + loaded_from_disk = Some(RustcCleanQueries { entries, span: value_span }); |
| 592 | + } |
| 593 | + _ => { |
| 594 | + cx.expected_specific_argument( |
| 595 | + name.span, |
| 596 | + &[sym::cfg, sym::except, sym::loaded_from_disk], |
| 597 | + ); |
| 598 | + } |
| 599 | + } |
| 600 | + } |
| 601 | + let Some(cfg) = cfg else { |
| 602 | + cx.expected_specific_argument(list.span, &[sym::cfg]); |
| 603 | + return None; |
| 604 | + }; |
| 605 | + |
| 606 | + Some(RustcCleanAttribute { span: cx.attr_span, cfg, except, loaded_from_disk }) |
| 607 | + } |
| 608 | +} |
| 609 | + |
| 610 | +pub(crate) struct RustcIfThisChangedParser; |
| 611 | + |
| 612 | +impl<S: Stage> SingleAttributeParser<S> for RustcIfThisChangedParser { |
| 613 | + const PATH: &[Symbol] = &[sym::rustc_if_this_changed]; |
| 614 | + |
| 615 | + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost; |
| 616 | + |
| 617 | + const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error; |
| 618 | + |
| 619 | + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 620 | + // tidy-alphabetical-start |
| 621 | + Allow(Target::AssocConst), |
| 622 | + Allow(Target::AssocTy), |
| 623 | + Allow(Target::Const), |
| 624 | + Allow(Target::Enum), |
| 625 | + Allow(Target::Expression), |
| 626 | + Allow(Target::Field), |
| 627 | + Allow(Target::Fn), |
| 628 | + Allow(Target::ForeignMod), |
| 629 | + Allow(Target::Impl { of_trait: false }), |
| 630 | + Allow(Target::Impl { of_trait: true }), |
| 631 | + Allow(Target::Method(MethodKind::Inherent)), |
| 632 | + Allow(Target::Method(MethodKind::Trait { body: false })), |
| 633 | + Allow(Target::Method(MethodKind::Trait { body: true })), |
| 634 | + Allow(Target::Method(MethodKind::TraitImpl)), |
| 635 | + Allow(Target::Mod), |
| 636 | + Allow(Target::Static), |
| 637 | + Allow(Target::Struct), |
| 638 | + Allow(Target::Trait), |
| 639 | + Allow(Target::TyAlias), |
| 640 | + Allow(Target::Union), |
| 641 | + // tidy-alphabetical-end |
| 642 | + ]); |
| 643 | + |
| 644 | + const TEMPLATE: AttributeTemplate = template!(Word, List: &["DepNode"]); |
| 645 | + |
| 646 | + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> { |
| 647 | + if !cx.cx.sess.opts.unstable_opts.query_dep_graph { |
| 648 | + cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" }); |
| 649 | + } |
| 650 | + match args { |
| 651 | + ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)), |
| 652 | + ArgParser::List(list) => { |
| 653 | + let Some(item) = list.single() else { |
| 654 | + cx.expected_single_argument(list.span); |
| 655 | + return None; |
| 656 | + }; |
| 657 | + let Some(ident) = item.meta_item().and_then(|item| item.ident()) else { |
| 658 | + cx.expected_identifier(item.span()); |
| 659 | + return None; |
| 660 | + }; |
| 661 | + Some(AttributeKind::RustcIfThisChanged(cx.attr_span, Some(ident.name))) |
| 662 | + } |
| 663 | + ArgParser::NameValue(_) => { |
| 664 | + cx.expected_list_or_no_args(cx.inner_span); |
| 665 | + None |
| 666 | + } |
| 667 | + } |
| 668 | + } |
| 669 | +} |
| 670 | + |
| 671 | +pub(crate) struct RustcThenThisWouldNeedParser; |
| 672 | + |
| 673 | +impl<S: Stage> CombineAttributeParser<S> for RustcThenThisWouldNeedParser { |
| 674 | + const PATH: &[Symbol] = &[sym::rustc_then_this_would_need]; |
| 675 | + type Item = Ident; |
| 676 | + |
| 677 | + const CONVERT: ConvertFn<Self::Item> = |
| 678 | + |items, span| AttributeKind::RustcThenThisWouldNeed(span, items); |
| 679 | + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ |
| 680 | + // tidy-alphabetical-start |
| 681 | + Allow(Target::AssocConst), |
| 682 | + Allow(Target::AssocTy), |
| 683 | + Allow(Target::Const), |
| 684 | + Allow(Target::Enum), |
| 685 | + Allow(Target::Expression), |
| 686 | + Allow(Target::Field), |
| 687 | + Allow(Target::Fn), |
| 688 | + Allow(Target::ForeignMod), |
| 689 | + Allow(Target::Impl { of_trait: false }), |
| 690 | + Allow(Target::Impl { of_trait: true }), |
| 691 | + Allow(Target::Method(MethodKind::Inherent)), |
| 692 | + Allow(Target::Method(MethodKind::Trait { body: false })), |
| 693 | + Allow(Target::Method(MethodKind::Trait { body: true })), |
| 694 | + Allow(Target::Method(MethodKind::TraitImpl)), |
| 695 | + Allow(Target::Mod), |
| 696 | + Allow(Target::Static), |
| 697 | + Allow(Target::Struct), |
| 698 | + Allow(Target::Trait), |
| 699 | + Allow(Target::TyAlias), |
| 700 | + Allow(Target::Union), |
| 701 | + // tidy-alphabetical-end |
| 702 | + ]); |
| 703 | + |
| 704 | + const TEMPLATE: AttributeTemplate = template!(List: &["DepNode"]); |
| 705 | + |
| 706 | + fn extend( |
| 707 | + cx: &mut AcceptContext<'_, '_, S>, |
| 708 | + args: &ArgParser, |
| 709 | + ) -> impl IntoIterator<Item = Self::Item> { |
| 710 | + if !cx.cx.sess.opts.unstable_opts.query_dep_graph { |
| 711 | + cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" }); |
| 712 | + } |
| 713 | + let Some(item) = args.list().and_then(|l| l.single()) else { |
| 714 | + cx.expected_single_argument(cx.inner_span); |
| 715 | + return None; |
| 716 | + }; |
| 717 | + let Some(ident) = item.meta_item().and_then(|item| item.ident()) else { |
| 718 | + cx.expected_identifier(item.span()); |
| 719 | + return None; |
| 720 | + }; |
| 721 | + Some(ident) |
| 722 | + } |
| 723 | +} |
0 commit comments