@@ -3,7 +3,8 @@ use std::convert::identity;
33use rustc_ast as ast;
44use rustc_ast:: token:: DocFragmentKind ;
55use rustc_ast:: { AttrItemKind , AttrStyle , NodeId , Safety } ;
6- use rustc_errors:: DiagCtxtHandle ;
6+ use rustc_data_structures:: sync:: { DynSend , DynSync } ;
7+ use rustc_errors:: { Diag , DiagCtxtHandle , Level } ;
78use rustc_feature:: { AttributeTemplate , Features } ;
89use rustc_hir:: attrs:: AttributeKind ;
910use rustc_hir:: lints:: AttributeLintKind ;
@@ -18,6 +19,15 @@ use crate::parser::{AllowExprMetavar, ArgParser, PathParser, RefPathParser};
1819use crate :: session_diagnostics:: ParsedDescription ;
1920use crate :: { Early , Late , OmitDoc , ShouldEmit } ;
2021
22+ pub enum EmitAttribute {
23+ Static ( AttributeLintKind ) ,
24+ Dynamic (
25+ Box <
26+ dyn for < ' a > Fn ( DiagCtxtHandle < ' a > , Level ) -> Diag < ' a , ( ) > + DynSend + DynSync + ' static ,
27+ > ,
28+ ) ,
29+ }
30+
2131/// Context created once, for example as part of the ast lowering
2232/// context, through which all attributes can be lowered.
2333pub struct AttributeParser < ' sess , S : Stage = Late > {
@@ -116,13 +126,18 @@ impl<'sess> AttributeParser<'sess, Early> {
116126 target,
117127 OmitDoc :: Skip ,
118128 std:: convert:: identity,
119- |lint_id, span, kind| {
120- sess. psess . buffer_lint (
121- lint_id. lint ,
122- span,
123- target_node_id,
124- BuiltinLintDiag :: AttributeLint ( kind) ,
125- )
129+ |lint_id, span, kind| match kind {
130+ EmitAttribute :: Static ( attr_kind) => {
131+ sess. psess . buffer_lint (
132+ lint_id. lint ,
133+ span,
134+ target_node_id,
135+ BuiltinLintDiag :: AttributeLint ( attr_kind) ,
136+ ) ;
137+ }
138+ EmitAttribute :: Dynamic ( callback) => {
139+ sess. psess . dyn_buffer_lint ( lint_id. lint , span, target_node_id, callback) ;
140+ }
126141 } ,
127142 )
128143 }
@@ -200,16 +215,21 @@ impl<'sess> AttributeParser<'sess, Early> {
200215 sess,
201216 stage : Early { emit_errors } ,
202217 } ;
203- let mut emit_lint = |lint_id : LintId , span : Span , kind : AttributeLintKind | {
204- sess. psess . buffer_lint (
205- lint_id. lint ,
206- span,
207- target_node_id,
208- BuiltinLintDiag :: AttributeLint ( kind) ,
209- )
218+ let mut emit_lint = |lint_id : LintId , span : Span , kind : EmitAttribute | match kind {
219+ EmitAttribute :: Static ( attr_kind) => {
220+ sess. psess . buffer_lint (
221+ lint_id. lint ,
222+ span,
223+ target_node_id,
224+ BuiltinLintDiag :: AttributeLint ( attr_kind) ,
225+ ) ;
226+ }
227+ EmitAttribute :: Dynamic ( callback) => {
228+ sess. psess . dyn_buffer_lint ( lint_id. lint , span, target_node_id, callback) ;
229+ }
210230 } ;
211231 if let Some ( safety) = attr_safety {
212- parser. check_attribute_safety ( & attr_path, inner_span, safety, & mut emit_lint)
232+ parser. check_attribute_safety ( & attr_path, inner_span, safety, & mut emit_lint) ;
213233 }
214234 let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
215235 shared : SharedContext {
@@ -266,7 +286,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
266286 target : Target ,
267287 omit_doc : OmitDoc ,
268288 lower_span : impl Copy + Fn ( Span ) -> Span ,
269- mut emit_lint : impl FnMut ( LintId , Span , AttributeLintKind ) ,
289+ mut emit_lint : impl FnMut ( LintId , Span , EmitAttribute ) ,
270290 ) -> Vec < Attribute > {
271291 let mut attributes = Vec :: new ( ) ;
272292 // We store the attributes we intend to discard at the end of this function in order to
0 commit comments