@@ -13,8 +13,9 @@ use crate::attrs::PrintAttribute;
1313#[ derive( Clone , Default , Debug , StableHash , Encodable , Decodable , PrintAttribute ) ]
1414pub struct Directive {
1515 pub is_rustc_attr : bool ,
16- pub condition : Option < OnUnimplementedCondition > ,
17- pub subcommands : ThinVec < Directive > ,
16+ /// This is never nested more than once, i.e. the directives in this
17+ /// thinvec have no filters of their own.
18+ pub filters : ThinVec < ( OnUnimplementedCondition , Directive ) > ,
1819 pub message : Option < ( Span , FormatString ) > ,
1920 pub label : Option < ( Span , FormatString ) > ,
2021 pub notes : ThinVec < FormatString > ,
@@ -28,11 +29,8 @@ impl Directive {
2829 /// We can't check this while parsing the attribute because `rustc_attr_parsing` doesn't have
2930 /// access to the item an attribute is on. Instead we later call this function in `check_attr`.
3031 pub fn visit_params ( & self , visit : & mut impl FnMut ( Symbol , Span ) ) {
31- if let Some ( condition) = & self . condition {
32- condition. visit_params ( visit) ;
33- }
34-
35- for subcommand in & self . subcommands {
32+ for ( filter, subcommand) in & self . filters {
33+ filter. visit_params ( visit) ;
3634 subcommand. visit_params ( visit) ;
3735 }
3836
@@ -62,53 +60,25 @@ impl Directive {
6260 "Directive::eval({self:?}, this={this}, options={condition_options:?}, args ={args:?})"
6361 ) ;
6462
65- let Some ( condition_options) = condition_options else {
63+ let mut ret = CustomDiagnostic :: default ( ) ;
64+
65+ if let Some ( condition_options) = condition_options {
66+ for ( filter, directive) in & self . filters {
67+ if filter. matches_predicate ( condition_options) {
68+ debug ! ( "eval: {filter:?} succeeded" ) ;
69+ ret. update ( directive, args) ;
70+ } else {
71+ debug ! ( "eval: skipping {filter:?} due to condition" ) ;
72+ }
73+ }
74+ } else {
6675 debug_assert ! (
6776 !self . is_rustc_attr,
6877 "Directive::eval called for `rustc_on_unimplemented` without `condition_options`"
6978 ) ;
70- return CustomDiagnostic {
71- label : self . label . as_ref ( ) . map ( |l| l. 1 . format ( args) ) ,
72- message : self . message . as_ref ( ) . map ( |m| m. 1 . format ( args) ) ,
73- notes : self . notes . iter ( ) . map ( |n| n. format ( args) ) . collect ( ) ,
74- parent_label : None ,
75- } ;
7679 } ;
77- let mut message = None ;
78- let mut label = None ;
79- let mut notes = Vec :: new ( ) ;
80- let mut parent_label = None ;
81-
82- for command in self . subcommands . iter ( ) . chain ( Some ( self ) ) . rev ( ) {
83- debug ! ( ?command) ;
84- if let Some ( ref condition) = command. condition
85- && !condition. matches_predicate ( condition_options)
86- {
87- debug ! ( "eval: skipping {command:?} due to condition" ) ;
88- continue ;
89- }
90- debug ! ( "eval: {command:?} succeeded" ) ;
91- if let Some ( ref message_) = command. message {
92- message = Some ( message_. clone ( ) ) ;
93- }
94-
95- if let Some ( ref label_) = command. label {
96- label = Some ( label_. clone ( ) ) ;
97- }
98-
99- notes. extend ( command. notes . clone ( ) ) ;
100-
101- if let Some ( ref parent_label_) = command. parent_label {
102- parent_label = Some ( parent_label_. clone ( ) ) ;
103- }
104- }
105-
106- CustomDiagnostic {
107- label : label. map ( |l| l. 1 . format ( args) ) ,
108- message : message. map ( |m| m. 1 . format ( args) ) ,
109- notes : notes. into_iter ( ) . map ( |n| n. format ( args) ) . collect ( ) ,
110- parent_label : parent_label. map ( |e_s| e_s. format ( args) ) ,
111- }
80+ ret. update ( self , args) ;
81+ ret
11282 }
11383}
11484
@@ -121,6 +91,22 @@ pub struct CustomDiagnostic {
12191 pub parent_label : Option < String > ,
12292}
12393
94+ impl CustomDiagnostic {
95+ fn update ( & mut self , di : & Directive , args : & FormatArgs ) {
96+ if self . message . is_none ( ) {
97+ self . message = di. message . as_ref ( ) . map ( |m| m. 1 . format ( args) ) ;
98+ }
99+ if self . label . is_none ( ) {
100+ self . label = di. label . as_ref ( ) . map ( |l| l. 1 . format ( args) ) ;
101+ }
102+ if self . parent_label . is_none ( ) {
103+ self . parent_label = di. parent_label . as_ref ( ) . map ( |p| p. format ( args) ) ;
104+ }
105+
106+ self . notes . extend ( di. notes . iter ( ) . map ( |n| n. format ( args) ) )
107+ }
108+ }
109+
124110/// Like [std::fmt::Arguments] this is a string that has been parsed into "pieces",
125111/// either as string pieces or dynamic arguments.
126112#[ derive( Clone , Debug , StableHash , Encodable , Decodable , PrintAttribute ) ]
0 commit comments