@@ -6,14 +6,15 @@ use crate::Namespace::*;
6
6
use crate :: { AmbiguityError , AmbiguityErrorMisc , AmbiguityKind , BuiltinMacroState , Determinacy } ;
7
7
use crate :: { CrateLint , ParentScope , ResolutionError , Resolver , Scope , ScopeSet , Weak } ;
8
8
use crate :: { ModuleKind , ModuleOrUniformRoot , NameBinding , PathResult , Segment , ToNameBinding } ;
9
- use rustc_ast:: { self as ast, NodeId } ;
9
+ use rustc_ast:: { self as ast, Inline , ItemKind , ModKind , NodeId } ;
10
10
use rustc_ast_lowering:: ResolverAstLowering ;
11
11
use rustc_ast_pretty:: pprust;
12
12
use rustc_attr:: StabilityLevel ;
13
13
use rustc_data_structures:: fx:: FxHashSet ;
14
14
use rustc_data_structures:: ptr_key:: PtrKey ;
15
15
use rustc_data_structures:: sync:: Lrc ;
16
16
use rustc_errors:: struct_span_err;
17
+ use rustc_expand:: base:: Annotatable ;
17
18
use rustc_expand:: base:: { Indeterminate , ResolverExpand , SyntaxExtension , SyntaxExtensionKind } ;
18
19
use rustc_expand:: compile_declarative_macro;
19
20
use rustc_expand:: expand:: { AstFragment , Invocation , InvocationKind } ;
@@ -153,6 +154,26 @@ crate fn registered_attrs_and_tools(
153
154
( registered_attrs, registered_tools)
154
155
}
155
156
157
+ // Some feature gates for inner attributes are reported as lints for backward compatibility.
158
+ fn soft_custom_inner_attributes_gate ( path : & ast:: Path , invoc : & Invocation ) -> bool {
159
+ match & path. segments [ ..] {
160
+ // `#![test]`
161
+ [ seg] if seg. ident . name == sym:: test => return true ,
162
+ // `#![rustfmt::skip]` on out-of-line modules
163
+ [ seg1, seg2] if seg1. ident . name == sym:: rustfmt && seg2. ident . name == sym:: skip => {
164
+ if let InvocationKind :: Attr { item, .. } = & invoc. kind {
165
+ if let Annotatable :: Item ( item) = item {
166
+ if let ItemKind :: Mod ( _, ModKind :: Loaded ( _, Inline :: No , _) ) = item. kind {
167
+ return true ;
168
+ }
169
+ }
170
+ }
171
+ }
172
+ _ => { }
173
+ }
174
+ false
175
+ }
176
+
156
177
impl < ' a > ResolverExpand for Resolver < ' a > {
157
178
fn next_node_id ( & mut self ) -> NodeId {
158
179
self . next_node_id ( )
@@ -267,6 +288,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
267
288
parent_scope,
268
289
node_id,
269
290
force,
291
+ soft_custom_inner_attributes_gate ( path, invoc) ,
270
292
) ?;
271
293
272
294
let span = invoc. span ( ) ;
@@ -440,6 +462,7 @@ impl<'a> Resolver<'a> {
440
462
parent_scope : & ParentScope < ' a > ,
441
463
node_id : NodeId ,
442
464
force : bool ,
465
+ soft_custom_inner_attributes_gate : bool ,
443
466
) -> Result < ( Lrc < SyntaxExtension > , Res ) , Indeterminate > {
444
467
let ( ext, res) = match self . resolve_macro_path ( path, Some ( kind) , parent_scope, true , force)
445
468
{
@@ -507,7 +530,7 @@ impl<'a> Resolver<'a> {
507
530
Res :: NonMacroAttr ( ..) => "custom inner attributes are unstable" ,
508
531
_ => unreachable ! ( ) ,
509
532
} ;
510
- if path == & sym :: test {
533
+ if soft_custom_inner_attributes_gate {
511
534
self . session . parse_sess . buffer_lint ( SOFT_UNSTABLE , path. span , node_id, msg) ;
512
535
} else {
513
536
feature_err ( & self . session . parse_sess , sym:: custom_inner_attributes, path. span , msg)
0 commit comments