1- use rustc_ast as ast;
1+ use rustc_ast:: { self as ast, NodeId } ;
22use rustc_feature:: is_builtin_attr_name;
33use rustc_hir:: def:: { DefKind , Namespace , NonMacroAttrKind , PartialRes , PerNS } ;
44use rustc_hir:: PrimTy ;
55use rustc_middle:: bug;
66use rustc_middle:: ty;
7+ use rustc_session:: lint:: builtin:: PROC_MACRO_DERIVE_RESOLUTION_FALLBACK ;
8+ use rustc_session:: lint:: BuiltinLintDiagnostics ;
79use rustc_span:: def_id:: LocalDefId ;
810use rustc_span:: edition:: Edition ;
911use rustc_span:: hygiene:: { ExpnId , ExpnKind , LocalExpnId , MacroKind , SyntaxContext } ;
@@ -99,7 +101,7 @@ impl<'a> Resolver<'a> {
99101 } ;
100102 let mut scope = match ns {
101103 _ if is_absolute_path => Scope :: CrateRoot ,
102- TypeNS | ValueNS => Scope :: Module ( module) ,
104+ TypeNS | ValueNS => Scope :: Module ( module, None ) ,
103105 MacroNS => Scope :: DeriveHelpers ( parent_scope. expansion ) ,
104106 } ;
105107 let mut ctxt = ctxt. normalize_to_macros_2_0 ( ) ;
@@ -163,7 +165,7 @@ impl<'a> Resolver<'a> {
163165 MacroRulesScope :: Invocation ( invoc_id) => {
164166 Scope :: MacroRules ( self . invocation_parent_scopes [ & invoc_id] . macro_rules )
165167 }
166- MacroRulesScope :: Empty => Scope :: Module ( module) ,
168+ MacroRulesScope :: Empty => Scope :: Module ( module, None ) ,
167169 } ,
168170 Scope :: CrateRoot => match ns {
169171 TypeNS => {
@@ -172,10 +174,16 @@ impl<'a> Resolver<'a> {
172174 }
173175 ValueNS | MacroNS => break ,
174176 } ,
175- Scope :: Module ( module) => {
177+ Scope :: Module ( module, prev_lint_id ) => {
176178 use_prelude = !module. no_implicit_prelude ;
177- match self . hygienic_lexical_parent ( module, & mut ctxt) {
178- Some ( parent_module) => Scope :: Module ( parent_module) ,
179+ let derive_fallback_lint_id = match scope_set {
180+ ScopeSet :: Late ( .., lint_id) => lint_id,
181+ _ => None ,
182+ } ;
183+ match self . hygienic_lexical_parent ( module, & mut ctxt, derive_fallback_lint_id) {
184+ Some ( ( parent_module, lint_id) ) => {
185+ Scope :: Module ( parent_module, lint_id. or ( prev_lint_id) )
186+ }
179187 None => {
180188 ctxt. adjust ( ExpnId :: root ( ) ) ;
181189 match ns {
@@ -207,13 +215,45 @@ impl<'a> Resolver<'a> {
207215 & mut self ,
208216 module : Module < ' a > ,
209217 ctxt : & mut SyntaxContext ,
210- ) -> Option < Module < ' a > > {
218+ derive_fallback_lint_id : Option < NodeId > ,
219+ ) -> Option < ( Module < ' a > , Option < NodeId > ) > {
211220 if !module. expansion . outer_expn_is_descendant_of ( * ctxt) {
212- return Some ( self . expn_def_scope ( ctxt. remove_mark ( ) ) ) ;
221+ return Some ( ( self . expn_def_scope ( ctxt. remove_mark ( ) ) , None ) ) ;
213222 }
214223
215224 if let ModuleKind :: Block = module. kind {
216- return Some ( module. parent . unwrap ( ) . nearest_item_scope ( ) ) ;
225+ return Some ( ( module. parent . unwrap ( ) . nearest_item_scope ( ) , None ) ) ;
226+ }
227+
228+ // We need to support the next case under a deprecation warning
229+ // ```
230+ // struct MyStruct;
231+ // ---- begin: this comes from a proc macro derive
232+ // mod implementation_details {
233+ // // Note that `MyStruct` is not in scope here.
234+ // impl SomeTrait for MyStruct { ... }
235+ // }
236+ // ---- end
237+ // ```
238+ // So we have to fall back to the module's parent during lexical resolution in this case.
239+ if derive_fallback_lint_id. is_some ( ) {
240+ if let Some ( parent) = module. parent {
241+ // Inner module is inside the macro, parent module is outside of the macro.
242+ if module. expansion != parent. expansion
243+ && module. expansion . is_descendant_of ( parent. expansion )
244+ {
245+ // The macro is a proc macro derive
246+ if let Some ( def_id) = module. expansion . expn_data ( ) . macro_def_id {
247+ let ext = self . get_macro_by_def_id ( def_id) . ext ;
248+ if ext. builtin_name . is_none ( )
249+ && ext. macro_kind ( ) == MacroKind :: Derive
250+ && parent. expansion . outer_expn_is_descendant_of ( * ctxt)
251+ {
252+ return Some ( ( parent, derive_fallback_lint_id) ) ;
253+ }
254+ }
255+ }
256+ }
217257 }
218258
219259 None
@@ -470,7 +510,7 @@ impl<'a> Resolver<'a> {
470510 Err ( ( Determinacy :: Determined , _) ) => Err ( Determinacy :: Determined ) ,
471511 }
472512 }
473- Scope :: Module ( module) => {
513+ Scope :: Module ( module, derive_fallback_lint_id ) => {
474514 let adjusted_parent_scope = & ParentScope { module, ..* parent_scope } ;
475515 let binding = this. resolve_ident_in_module_unadjusted_ext (
476516 ModuleOrUniformRoot :: Module ( module) ,
@@ -483,6 +523,21 @@ impl<'a> Resolver<'a> {
483523 ) ;
484524 match binding {
485525 Ok ( binding) => {
526+ if let Some ( lint_id) = derive_fallback_lint_id {
527+ this. lint_buffer . buffer_lint_with_diagnostic (
528+ PROC_MACRO_DERIVE_RESOLUTION_FALLBACK ,
529+ lint_id,
530+ orig_ident. span ,
531+ & format ! (
532+ "cannot find {} `{}` in this scope" ,
533+ ns. descr( ) ,
534+ ident
535+ ) ,
536+ BuiltinLintDiagnostics :: ProcMacroDeriveResolutionFallback (
537+ orig_ident. span ,
538+ ) ,
539+ ) ;
540+ }
486541 let misc_flags = if ptr:: eq ( module, this. graph_root ) {
487542 Flags :: MISC_SUGGEST_CRATE
488543 } else if module. is_normal ( ) {
0 commit comments