@@ -4,15 +4,16 @@ use std::ops::{Deref, DerefMut};
4
4
use std:: sync:: LazyLock ;
5
5
6
6
use private:: Sealed ;
7
- use rustc_ast:: { self as ast , AttrStyle , MetaItemLit , NodeId } ;
8
- use rustc_errors:: { DiagCtxtHandle , Diagnostic } ;
9
- use rustc_feature:: { AttributeTemplate , Features } ;
7
+ use rustc_ast:: { AttrStyle , MetaItemLit , NodeId } ;
8
+ use rustc_errors:: Diagnostic ;
9
+ use rustc_feature:: AttributeTemplate ;
10
10
use rustc_hir:: attrs:: AttributeKind ;
11
11
use rustc_hir:: lints:: { AttributeLint , AttributeLintKind } ;
12
- use rustc_hir:: { AttrArgs , AttrItem , AttrPath , Attribute , HashIgnoredAttrId , HirId , Target } ;
12
+ use rustc_hir:: { AttrPath , HirId } ;
13
13
use rustc_session:: Session ;
14
- use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , Symbol , sym } ;
14
+ use rustc_span:: { ErrorGuaranteed , Span , Symbol } ;
15
15
16
+ use crate :: AttributeParser ;
16
17
use crate :: attributes:: allow_unstable:: {
17
18
AllowConstFnUnstableParser , AllowInternalUnstableParser , UnstableFeatureBoundParser ,
18
19
} ;
@@ -62,21 +63,21 @@ use crate::attributes::traits::{
62
63
} ;
63
64
use crate :: attributes:: transparency:: TransparencyParser ;
64
65
use crate :: attributes:: { AttributeParser as _, Combine , Single , WithoutArgs } ;
65
- use crate :: parser:: { ArgParser , MetaItemParser , PathParser } ;
66
+ use crate :: parser:: { ArgParser , PathParser } ;
66
67
use crate :: session_diagnostics:: { AttributeParseError , AttributeParseErrorReason , UnknownMetaItem } ;
67
68
use crate :: target_checking:: AllowedTargets ;
68
69
69
70
type GroupType < S > = LazyLock < GroupTypeInner < S > > ;
70
71
71
- struct GroupTypeInner < S : Stage > {
72
- accepters : BTreeMap < & ' static [ Symbol ] , Vec < GroupTypeInnerAccept < S > > > ,
73
- finalizers : Vec < FinalizeFn < S > > ,
72
+ pub ( super ) struct GroupTypeInner < S : Stage > {
73
+ pub ( super ) accepters : BTreeMap < & ' static [ Symbol ] , Vec < GroupTypeInnerAccept < S > > > ,
74
+ pub ( super ) finalizers : Vec < FinalizeFn < S > > ,
74
75
}
75
76
76
- struct GroupTypeInnerAccept < S : Stage > {
77
- template : AttributeTemplate ,
78
- accept_fn : AcceptFn < S > ,
79
- allowed_targets : AllowedTargets ,
77
+ pub ( super ) struct GroupTypeInnerAccept < S : Stage > {
78
+ pub ( super ) template : AttributeTemplate ,
79
+ pub ( super ) accept_fn : AcceptFn < S > ,
80
+ pub ( super ) allowed_targets : AllowedTargets ,
80
81
}
81
82
82
83
type AcceptFn < S > =
@@ -590,7 +591,7 @@ pub struct SharedContext<'p, 'sess, S: Stage> {
590
591
/// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
591
592
pub ( crate ) target_id : S :: Id ,
592
593
593
- emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
594
+ pub ( crate ) emit_lint : & ' p mut dyn FnMut ( AttributeLint < S :: Id > ) ,
594
595
}
595
596
596
597
/// Context given to every attribute parser during finalization.
@@ -661,311 +662,3 @@ impl ShouldEmit {
661
662
}
662
663
}
663
664
}
664
-
665
- /// Context created once, for example as part of the ast lowering
666
- /// context, through which all attributes can be lowered.
667
- pub struct AttributeParser < ' sess , S : Stage = Late > {
668
- pub ( crate ) tools : Vec < Symbol > ,
669
- pub ( crate ) features : Option < & ' sess Features > ,
670
- sess : & ' sess Session ,
671
- stage : S ,
672
-
673
- /// *Only* parse attributes with this symbol.
674
- ///
675
- /// Used in cases where we want the lowering infrastructure for parse just a single attribute.
676
- parse_only : Option < Symbol > ,
677
- }
678
-
679
- impl < ' sess > AttributeParser < ' sess , Early > {
680
- /// This method allows you to parse attributes *before* you have access to features or tools.
681
- /// One example where this is necessary, is to parse `feature` attributes themselves for
682
- /// example.
683
- ///
684
- /// Try to use this as little as possible. Attributes *should* be lowered during
685
- /// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
686
- /// crash if you tried to do so through [`parse_limited`](Self::parse_limited).
687
- ///
688
- /// To make sure use is limited, supply a `Symbol` you'd like to parse. Only attributes with
689
- /// that symbol are picked out of the list of instructions and parsed. Those are returned.
690
- ///
691
- /// No diagnostics will be emitted when parsing limited. Lints are not emitted at all, while
692
- /// errors will be emitted as a delayed bugs. in other words, we *expect* attributes parsed
693
- /// with `parse_limited` to be reparsed later during ast lowering where we *do* emit the errors
694
- pub fn parse_limited (
695
- sess : & ' sess Session ,
696
- attrs : & [ ast:: Attribute ] ,
697
- sym : Symbol ,
698
- target_span : Span ,
699
- target_node_id : NodeId ,
700
- features : Option < & ' sess Features > ,
701
- ) -> Option < Attribute > {
702
- let mut p = Self {
703
- features,
704
- tools : Vec :: new ( ) ,
705
- parse_only : Some ( sym) ,
706
- sess,
707
- stage : Early { emit_errors : ShouldEmit :: Nothing } ,
708
- } ;
709
- let mut parsed = p. parse_attribute_list (
710
- attrs,
711
- target_span,
712
- target_node_id,
713
- Target :: Crate , // Does not matter, we're not going to emit errors anyways
714
- OmitDoc :: Skip ,
715
- std:: convert:: identity,
716
- |_lint| {
717
- panic ! ( "can't emit lints here for now (nothing uses this atm)" ) ;
718
- } ,
719
- ) ;
720
- assert ! ( parsed. len( ) <= 1 ) ;
721
-
722
- parsed. pop ( )
723
- }
724
-
725
- pub fn parse_single < T > (
726
- sess : & ' sess Session ,
727
- attr : & ast:: Attribute ,
728
- target_span : Span ,
729
- target_node_id : NodeId ,
730
- features : Option < & ' sess Features > ,
731
- emit_errors : ShouldEmit ,
732
- parse_fn : fn ( cx : & mut AcceptContext < ' _ , ' _ , Early > , item : & ArgParser < ' _ > ) -> T ,
733
- template : & AttributeTemplate ,
734
- ) -> T {
735
- let mut parser = Self {
736
- features,
737
- tools : Vec :: new ( ) ,
738
- parse_only : None ,
739
- sess,
740
- stage : Early { emit_errors } ,
741
- } ;
742
- let ast:: AttrKind :: Normal ( normal_attr) = & attr. kind else {
743
- panic ! ( "parse_single called on a doc attr" )
744
- } ;
745
- let meta_parser = MetaItemParser :: from_attr ( normal_attr, parser. dcx ( ) ) ;
746
- let path = meta_parser. path ( ) ;
747
- let args = meta_parser. args ( ) ;
748
- let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
749
- shared : SharedContext {
750
- cx : & mut parser,
751
- target_span,
752
- target_id : target_node_id,
753
- emit_lint : & mut |_lint| {
754
- panic ! ( "can't emit lints here for now (nothing uses this atm)" ) ;
755
- } ,
756
- } ,
757
- attr_span : attr. span ,
758
- attr_style : attr. style ,
759
- template,
760
- attr_path : path. get_attribute_path ( ) ,
761
- } ;
762
- parse_fn ( & mut cx, args)
763
- }
764
- }
765
-
766
- impl < ' sess , S : Stage > AttributeParser < ' sess , S > {
767
- pub fn new (
768
- sess : & ' sess Session ,
769
- features : & ' sess Features ,
770
- tools : Vec < Symbol > ,
771
- stage : S ,
772
- ) -> Self {
773
- Self { features : Some ( features) , tools, parse_only : None , sess, stage }
774
- }
775
-
776
- pub ( crate ) fn sess ( & self ) -> & ' sess Session {
777
- & self . sess
778
- }
779
-
780
- pub ( crate ) fn features ( & self ) -> & ' sess Features {
781
- self . features . expect ( "features not available at this point in the compiler" )
782
- }
783
-
784
- pub ( crate ) fn features_option ( & self ) -> Option < & ' sess Features > {
785
- self . features
786
- }
787
-
788
- pub ( crate ) fn dcx ( & self ) -> DiagCtxtHandle < ' sess > {
789
- self . sess ( ) . dcx ( )
790
- }
791
-
792
- /// Parse a list of attributes.
793
- ///
794
- /// `target_span` is the span of the thing this list of attributes is applied to,
795
- /// and when `omit_doc` is set, doc attributes are filtered out.
796
- pub fn parse_attribute_list (
797
- & mut self ,
798
- attrs : & [ ast:: Attribute ] ,
799
- target_span : Span ,
800
- target_id : S :: Id ,
801
- target : Target ,
802
- omit_doc : OmitDoc ,
803
-
804
- lower_span : impl Copy + Fn ( Span ) -> Span ,
805
- mut emit_lint : impl FnMut ( AttributeLint < S :: Id > ) ,
806
- ) -> Vec < Attribute > {
807
- let mut attributes = Vec :: new ( ) ;
808
- let mut attr_paths = Vec :: new ( ) ;
809
-
810
- for attr in attrs {
811
- // If we're only looking for a single attribute, skip all the ones we don't care about.
812
- if let Some ( expected) = self . parse_only {
813
- if !attr. has_name ( expected) {
814
- continue ;
815
- }
816
- }
817
-
818
- // Sometimes, for example for `#![doc = include_str!("readme.md")]`,
819
- // doc still contains a non-literal. You might say, when we're lowering attributes
820
- // that's expanded right? But no, sometimes, when parsing attributes on macros,
821
- // we already use the lowering logic and these are still there. So, when `omit_doc`
822
- // is set we *also* want to ignore these.
823
- if omit_doc == OmitDoc :: Skip && attr. has_name ( sym:: doc) {
824
- continue ;
825
- }
826
-
827
- match & attr. kind {
828
- ast:: AttrKind :: DocComment ( comment_kind, symbol) => {
829
- if omit_doc == OmitDoc :: Skip {
830
- continue ;
831
- }
832
-
833
- attributes. push ( Attribute :: Parsed ( AttributeKind :: DocComment {
834
- style : attr. style ,
835
- kind : * comment_kind,
836
- span : lower_span ( attr. span ) ,
837
- comment : * symbol,
838
- } ) )
839
- }
840
- // // FIXME: make doc attributes go through a proper attribute parser
841
- // ast::AttrKind::Normal(n) if n.has_name(sym::doc) => {
842
- // let p = GenericMetaItemParser::from_attr(&n, self.dcx());
843
- //
844
- // attributes.push(Attribute::Parsed(AttributeKind::DocComment {
845
- // style: attr.style,
846
- // kind: CommentKind::Line,
847
- // span: attr.span,
848
- // comment: p.args().name_value(),
849
- // }))
850
- // }
851
- ast:: AttrKind :: Normal ( n) => {
852
- attr_paths. push ( PathParser :: Ast ( & n. item . path ) ) ;
853
-
854
- let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
855
- let path = parser. path ( ) ;
856
- let args = parser. args ( ) ;
857
- let path_parts = path. segments ( ) . map ( |i| i. name ) . collect :: < Vec < _ > > ( ) ;
858
-
859
- if let Some ( accepts) = S :: parsers ( ) . accepters . get ( path_parts. as_slice ( ) ) {
860
- for accept in accepts {
861
- let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
862
- shared : SharedContext {
863
- cx : self ,
864
- target_span,
865
- target_id,
866
- emit_lint : & mut emit_lint,
867
- } ,
868
- attr_span : lower_span ( attr. span ) ,
869
- attr_style : attr. style ,
870
- template : & accept. template ,
871
- attr_path : path. get_attribute_path ( ) ,
872
- } ;
873
-
874
- ( accept. accept_fn ) ( & mut cx, args) ;
875
-
876
- if self . stage . should_emit ( ) . should_emit ( ) {
877
- self . check_target (
878
- path. get_attribute_path ( ) ,
879
- attr. span ,
880
- & accept. allowed_targets ,
881
- target,
882
- target_id,
883
- & mut emit_lint,
884
- ) ;
885
- }
886
- }
887
- } else {
888
- // If we're here, we must be compiling a tool attribute... Or someone
889
- // forgot to parse their fancy new attribute. Let's warn them in any case.
890
- // If you are that person, and you really think your attribute should
891
- // remain unparsed, carefully read the documentation in this module and if
892
- // you still think so you can add an exception to this assertion.
893
-
894
- // FIXME(jdonszelmann): convert other attributes, and check with this that
895
- // we caught em all
896
- // const FIXME_TEMPORARY_ATTR_ALLOWLIST: &[Symbol] = &[sym::cfg];
897
- // assert!(
898
- // self.tools.contains(&parts[0]) || true,
899
- // // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
900
- // "attribute {path} wasn't parsed and isn't a know tool attribute",
901
- // );
902
-
903
- attributes. push ( Attribute :: Unparsed ( Box :: new ( AttrItem {
904
- path : AttrPath :: from_ast ( & n. item . path ) ,
905
- args : self . lower_attr_args ( & n. item . args , lower_span) ,
906
- id : HashIgnoredAttrId { attr_id : attr. id } ,
907
- style : attr. style ,
908
- span : lower_span ( attr. span ) ,
909
- } ) ) ) ;
910
- }
911
- }
912
- }
913
- }
914
-
915
- let mut parsed_attributes = Vec :: new ( ) ;
916
- for f in & S :: parsers ( ) . finalizers {
917
- if let Some ( attr) = f ( & mut FinalizeContext {
918
- shared : SharedContext {
919
- cx : self ,
920
- target_span,
921
- target_id,
922
- emit_lint : & mut emit_lint,
923
- } ,
924
- all_attrs : & attr_paths,
925
- } ) {
926
- parsed_attributes. push ( Attribute :: Parsed ( attr) ) ;
927
- }
928
- }
929
-
930
- attributes. extend ( parsed_attributes) ;
931
-
932
- attributes
933
- }
934
-
935
- /// Returns whether there is a parser for an attribute with this name
936
- pub fn is_parsed_attribute ( path : & [ Symbol ] ) -> bool {
937
- Late :: parsers ( ) . accepters . contains_key ( path)
938
- }
939
-
940
- fn lower_attr_args ( & self , args : & ast:: AttrArgs , lower_span : impl Fn ( Span ) -> Span ) -> AttrArgs {
941
- match args {
942
- ast:: AttrArgs :: Empty => AttrArgs :: Empty ,
943
- ast:: AttrArgs :: Delimited ( args) => AttrArgs :: Delimited ( args. clone ( ) ) ,
944
- // This is an inert key-value attribute - it will never be visible to macros
945
- // after it gets lowered to HIR. Therefore, we can extract literals to handle
946
- // nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
947
- ast:: AttrArgs :: Eq { eq_span, expr } => {
948
- // In valid code the value always ends up as a single literal. Otherwise, a dummy
949
- // literal suffices because the error is handled elsewhere.
950
- let lit = if let ast:: ExprKind :: Lit ( token_lit) = expr. kind
951
- && let Ok ( lit) =
952
- ast:: MetaItemLit :: from_token_lit ( token_lit, lower_span ( expr. span ) )
953
- {
954
- lit
955
- } else {
956
- let guar = self . dcx ( ) . span_delayed_bug (
957
- args. span ( ) . unwrap_or ( DUMMY_SP ) ,
958
- "expr in place where literal is expected (builtin attr parsing)" ,
959
- ) ;
960
- ast:: MetaItemLit {
961
- symbol : sym:: dummy,
962
- suffix : None ,
963
- kind : ast:: LitKind :: Err ( guar) ,
964
- span : DUMMY_SP ,
965
- }
966
- } ;
967
- AttrArgs :: Eq { eq_span : lower_span ( * eq_span) , expr : lit }
968
- }
969
- }
970
- }
971
- }
0 commit comments