@@ -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 > {
@@ -118,7 +128,14 @@ impl<'sess> AttributeParser<'sess, Early> {
118128 target,
119129 OmitDoc :: Skip ,
120130 std:: convert:: identity,
121- |lint_id, span, kind| sess. psess . buffer_lint ( lint_id. lint , span, target_node_id, kind) ,
131+ |lint_id, span, kind| match kind {
132+ EmitAttribute :: Static ( kind) => {
133+ sess. psess . buffer_lint ( lint_id. lint , span, target_node_id, kind)
134+ }
135+ EmitAttribute :: Dynamic ( callback) => {
136+ sess. psess . dyn_buffer_lint ( lint_id. lint , span, target_node_id, callback)
137+ }
138+ } ,
122139 )
123140 }
124141
@@ -195,11 +212,16 @@ impl<'sess> AttributeParser<'sess, Early> {
195212 sess,
196213 stage : Early { emit_errors } ,
197214 } ;
198- let mut emit_lint = |lint_id : LintId , span : Span , kind : AttributeLintKind | {
199- sess. psess . buffer_lint ( lint_id. lint , span, target_node_id, kind)
215+ let mut emit_lint = |lint_id : LintId , span : Span , kind : EmitAttribute | match kind {
216+ EmitAttribute :: Static ( kind) => {
217+ sess. psess . buffer_lint ( lint_id. lint , span, target_node_id, kind)
218+ }
219+ EmitAttribute :: Dynamic ( callback) => {
220+ sess. psess . dyn_buffer_lint ( lint_id. lint , span, target_node_id, callback)
221+ }
200222 } ;
201223 if let Some ( safety) = attr_safety {
202- parser. check_attribute_safety ( & attr_path, inner_span, safety, & mut emit_lint)
224+ parser. check_attribute_safety ( & attr_path, inner_span, safety, & mut emit_lint) ;
203225 }
204226 let mut cx: AcceptContext < ' _ , ' sess , Early > = AcceptContext {
205227 shared : SharedContext {
@@ -256,7 +278,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
256278 target : Target ,
257279 omit_doc : OmitDoc ,
258280 lower_span : impl Copy + Fn ( Span ) -> Span ,
259- mut emit_lint : impl FnMut ( LintId , Span , AttributeLintKind ) ,
281+ mut emit_lint : impl FnMut ( LintId , Span , EmitAttribute ) ,
260282 ) -> Vec < Attribute > {
261283 let mut attributes = Vec :: new ( ) ;
262284 // We store the attributes we intend to discard at the end of this function in order to
0 commit comments