@@ -55,7 +55,7 @@ use syntax::util::lev_distance::find_best_match_for_name;
5555
5656use syntax:: visit:: { self , FnKind , Visitor } ;
5757use syntax:: attr;
58- use syntax:: ast:: { Arm , IsAsync , BindingMode , Block , Crate , Expr , ExprKind } ;
58+ use syntax:: ast:: { CRATE_NODE_ID , Arm , IsAsync , BindingMode , Block , Crate , Expr , ExprKind } ;
5959use syntax:: ast:: { FnDecl , ForeignItem , ForeignItemKind , GenericParamKind , Generics } ;
6060use syntax:: ast:: { Item , ItemKind , ImplItem , ImplItemKind } ;
6161use syntax:: ast:: { Label , Local , Mutability , Pat , PatKind , Path } ;
@@ -1891,7 +1891,12 @@ impl<'a> Resolver<'a> {
18911891
18921892 ident. span = ident. span . modern ( ) ;
18931893 loop {
1894- module = unwrap_or ! ( self . hygienic_lexical_parent( module, & mut ident. span) , break ) ;
1894+ let ( opt_module, poisoned) = if record_used {
1895+ self . hygienic_lexical_parent_with_compatibility_fallback ( module, & mut ident. span )
1896+ } else {
1897+ ( self . hygienic_lexical_parent ( module, & mut ident. span ) , false )
1898+ } ;
1899+ module = unwrap_or ! ( opt_module, break ) ;
18951900 let orig_current_module = self . current_module ;
18961901 self . current_module = module; // Lexical resolutions can never be a privacy error.
18971902 let result = self . resolve_ident_in_module_unadjusted (
@@ -1900,7 +1905,19 @@ impl<'a> Resolver<'a> {
19001905 self . current_module = orig_current_module;
19011906
19021907 match result {
1903- Ok ( binding) => return Some ( LexicalScopeBinding :: Item ( binding) ) ,
1908+ Ok ( binding) => {
1909+ if poisoned {
1910+ self . session . buffer_lint_with_diagnostic (
1911+ lint:: builtin:: PROC_MACRO_DERIVE_RESOLUTION_FALLBACK ,
1912+ CRATE_NODE_ID , ident. span ,
1913+ & format ! ( "cannot find {} `{}` in this scope" , ns. descr( ) , ident) ,
1914+ lint:: builtin:: BuiltinLintDiagnostics ::
1915+ ProcMacroDeriveResolutionFallback ( ident. span ) ,
1916+ ) ;
1917+ }
1918+ return Some ( LexicalScopeBinding :: Item ( binding) )
1919+ }
1920+ _ if poisoned => break ,
19041921 Err ( Undetermined ) => return None ,
19051922 Err ( Determined ) => { }
19061923 }
@@ -1935,7 +1952,7 @@ impl<'a> Resolver<'a> {
19351952 None
19361953 }
19371954
1938- fn hygienic_lexical_parent ( & mut self , mut module : Module < ' a > , span : & mut Span )
1955+ fn hygienic_lexical_parent ( & mut self , module : Module < ' a > , span : & mut Span )
19391956 -> Option < Module < ' a > > {
19401957 if !module. expansion . is_descendant_of ( span. ctxt ( ) . outer ( ) ) {
19411958 return Some ( self . macro_def_scope ( span. remove_mark ( ) ) ) ;
@@ -1945,22 +1962,41 @@ impl<'a> Resolver<'a> {
19451962 return Some ( module. parent . unwrap ( ) ) ;
19461963 }
19471964
1948- let mut module_expansion = module. expansion . modern ( ) ; // for backward compatibility
1949- while let Some ( parent) = module. parent {
1950- let parent_expansion = parent. expansion . modern ( ) ;
1951- if module_expansion. is_descendant_of ( parent_expansion) &&
1952- parent_expansion != module_expansion {
1953- return if parent_expansion. is_descendant_of ( span. ctxt ( ) . outer ( ) ) {
1954- Some ( parent)
1955- } else {
1956- None
1957- } ;
1965+ None
1966+ }
1967+
1968+ fn hygienic_lexical_parent_with_compatibility_fallback (
1969+ & mut self , module : Module < ' a > , span : & mut Span ) -> ( Option < Module < ' a > > , /* poisoned */ bool
1970+ ) {
1971+ if let module @ Some ( ..) = self . hygienic_lexical_parent ( module, span) {
1972+ return ( module, false ) ;
1973+ }
1974+
1975+ // We need to support the next case under a deprecation warning
1976+ // ```
1977+ // struct MyStruct;
1978+ // ---- begin: this comes from a proc macro derive
1979+ // mod implementation_details {
1980+ // // Note that `MyStruct` is not in scope here.
1981+ // impl SomeTrait for MyStruct { ... }
1982+ // }
1983+ // ---- end
1984+ // ```
1985+ // So we have to fall back to the module's parent during lexical resolution in this case.
1986+ if let Some ( parent) = module. parent {
1987+ // Inner module is inside the macro, parent module is outside of the macro.
1988+ if module. expansion != parent. expansion &&
1989+ module. expansion . is_descendant_of ( parent. expansion ) {
1990+ // The macro is a proc macro derive
1991+ if module. expansion . looks_like_proc_macro_derive ( ) {
1992+ if parent. expansion . is_descendant_of ( span. ctxt ( ) . outer ( ) ) {
1993+ return ( module. parent , true ) ;
1994+ }
1995+ }
19581996 }
1959- module = parent;
1960- module_expansion = parent_expansion;
19611997 }
19621998
1963- None
1999+ ( None , false )
19642000 }
19652001
19662002 fn resolve_ident_in_module ( & mut self ,
@@ -1996,17 +2032,17 @@ impl<'a> Resolver<'a> {
19962032 let mut iter = ctxt. marks ( ) . into_iter ( ) . rev ( ) . peekable ( ) ;
19972033 let mut result = None ;
19982034 // Find the last modern mark from the end if it exists.
1999- while let Some ( & mark) = iter. peek ( ) {
2000- if mark . transparency ( ) == Transparency :: Opaque {
2035+ while let Some ( & ( mark, transparency ) ) = iter. peek ( ) {
2036+ if transparency == Transparency :: Opaque {
20012037 result = Some ( mark) ;
20022038 iter. next ( ) ;
20032039 } else {
20042040 break ;
20052041 }
20062042 }
20072043 // Then find the last legacy mark from the end if it exists.
2008- for mark in iter {
2009- if mark . transparency ( ) == Transparency :: SemiTransparent {
2044+ for ( mark, transparency ) in iter {
2045+ if transparency == Transparency :: SemiTransparent {
20102046 result = Some ( mark) ;
20112047 } else {
20122048 break ;
@@ -4037,8 +4073,9 @@ impl<'a> Resolver<'a> {
40374073 let mut search_module = self . current_module ;
40384074 loop {
40394075 self . get_traits_in_module_containing_item ( ident, ns, search_module, & mut found_traits) ;
4040- search_module =
4041- unwrap_or ! ( self . hygienic_lexical_parent( search_module, & mut ident. span) , break ) ;
4076+ search_module = unwrap_or ! (
4077+ self . hygienic_lexical_parent( search_module, & mut ident. span) , break
4078+ ) ;
40424079 }
40434080
40444081 if let Some ( prelude) = self . prelude {
@@ -4406,12 +4443,6 @@ impl<'a> Resolver<'a> {
44064443 ( TypeNS , _) => "type" ,
44074444 } ;
44084445
4409- let namespace = match ns {
4410- ValueNS => "value" ,
4411- MacroNS => "macro" ,
4412- TypeNS => "type" ,
4413- } ;
4414-
44154446 let msg = format ! ( "the name `{}` is defined multiple times" , name) ;
44164447
44174448 let mut err = match ( old_binding. is_extern_crate ( ) , new_binding. is_extern_crate ( ) ) {
@@ -4429,7 +4460,7 @@ impl<'a> Resolver<'a> {
44294460
44304461 err. note ( & format ! ( "`{}` must be defined only once in the {} namespace of this {}" ,
44314462 name,
4432- namespace ,
4463+ ns . descr ( ) ,
44334464 container) ) ;
44344465
44354466 err. span_label ( span, format ! ( "`{}` re{} here" , name, new_participle) ) ;
0 commit comments