@@ -6,14 +6,15 @@ use crate::Namespace::*;
66use crate :: { AmbiguityError , AmbiguityErrorMisc , AmbiguityKind , BuiltinMacroState , Determinacy } ;
77use crate :: { CrateLint , ParentScope , ResolutionError , Resolver , Scope , ScopeSet , Weak } ;
88use 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 } ;
1010use rustc_ast_lowering:: ResolverAstLowering ;
1111use rustc_ast_pretty:: pprust;
1212use rustc_attr:: StabilityLevel ;
1313use rustc_data_structures:: fx:: FxHashSet ;
1414use rustc_data_structures:: ptr_key:: PtrKey ;
1515use rustc_data_structures:: sync:: Lrc ;
1616use rustc_errors:: struct_span_err;
17+ use rustc_expand:: base:: Annotatable ;
1718use rustc_expand:: base:: { Indeterminate , ResolverExpand , SyntaxExtension , SyntaxExtensionKind } ;
1819use rustc_expand:: compile_declarative_macro;
1920use rustc_expand:: expand:: { AstFragment , Invocation , InvocationKind } ;
@@ -153,6 +154,26 @@ crate fn registered_attrs_and_tools(
153154 ( registered_attrs, registered_tools)
154155}
155156
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+
156177impl < ' a > ResolverExpand for Resolver < ' a > {
157178 fn next_node_id ( & mut self ) -> NodeId {
158179 self . next_node_id ( )
@@ -267,6 +288,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
267288 parent_scope,
268289 node_id,
269290 force,
291+ soft_custom_inner_attributes_gate ( path, invoc) ,
270292 ) ?;
271293
272294 let span = invoc. span ( ) ;
@@ -440,6 +462,7 @@ impl<'a> Resolver<'a> {
440462 parent_scope : & ParentScope < ' a > ,
441463 node_id : NodeId ,
442464 force : bool ,
465+ soft_custom_inner_attributes_gate : bool ,
443466 ) -> Result < ( Lrc < SyntaxExtension > , Res ) , Indeterminate > {
444467 let ( ext, res) = match self . resolve_macro_path ( path, Some ( kind) , parent_scope, true , force)
445468 {
@@ -507,7 +530,7 @@ impl<'a> Resolver<'a> {
507530 Res :: NonMacroAttr ( ..) => "custom inner attributes are unstable" ,
508531 _ => unreachable ! ( ) ,
509532 } ;
510- if path == & sym :: test {
533+ if soft_custom_inner_attributes_gate {
511534 self . session . parse_sess . buffer_lint ( SOFT_UNSTABLE , path. span , node_id, msg) ;
512535 } else {
513536 feature_err ( & self . session . parse_sess , sym:: custom_inner_attributes, path. span , msg)
0 commit comments