99// except according to those terms.
1010
1111use { AmbiguityError , AmbiguityKind , AmbiguityErrorMisc } ;
12- use { CrateLint , DeterminacyExt , Resolver , ResolutionError , is_known_tool , resolve_error } ;
12+ use { CrateLint , DeterminacyExt , Resolver , ResolutionError } ;
1313use { Module , ModuleKind , NameBinding , NameBindingKind , PathResult , ToNameBinding } ;
14+ use { is_known_tool, names_to_string, resolve_error} ;
1415use ModuleOrUniformRoot ;
1516use Namespace :: { self , * } ;
1617use build_reduced_graph:: { BuildReducedGraphVisitor , IsMacroExport } ;
@@ -450,6 +451,9 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
450451 return Err ( Determinacy :: Determined ) ;
451452 }
452453 }
454+ Def :: Err => {
455+ return Err ( Determinacy :: Determined ) ;
456+ }
453457 _ => panic ! ( "expected `Def::Macro` or `Def::NonMacroAttr`" ) ,
454458 }
455459
@@ -476,29 +480,19 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
476480 if path. len ( ) > 1 {
477481 let def = match self . resolve_path ( & path, Some ( MacroNS ) , parent_scope,
478482 false , path_span, CrateLint :: No ) {
479- PathResult :: NonModule ( path_res) => match path_res. base_def ( ) {
480- Def :: Err => Err ( Determinacy :: Determined ) ,
481- def @ _ => {
482- if path_res. unresolved_segments ( ) > 0 {
483- self . found_unresolved_macro = true ;
484- self . session . span_err ( path_span,
485- "fail to resolve non-ident macro path" ) ;
486- Err ( Determinacy :: Determined )
487- } else {
488- Ok ( def)
489- }
490- }
491- } ,
492- PathResult :: Module ( ..) => unreachable ! ( ) ,
483+ PathResult :: NonModule ( path_res) if path_res. unresolved_segments ( ) == 0 => {
484+ Ok ( path_res. base_def ( ) )
485+ }
493486 PathResult :: Indeterminate if !force => return Err ( Determinacy :: Undetermined ) ,
494- _ => {
487+ PathResult :: NonModule ( .. ) | PathResult :: Indeterminate | PathResult :: Failed ( .. ) => {
495488 self . found_unresolved_macro = true ;
496489 Err ( Determinacy :: Determined )
497- } ,
490+ }
491+ PathResult :: Module ( ..) => unreachable ! ( ) ,
498492 } ;
499493
500- parent_scope. module . macro_resolutions . borrow_mut ( )
501- . push ( ( path, parent_scope. clone ( ) , path_span ) ) ;
494+ parent_scope. module . multi_segment_macro_resolutions . borrow_mut ( )
495+ . push ( ( path, path_span , kind , parent_scope. clone ( ) , def . ok ( ) ) ) ;
502496
503497 def
504498 } else {
@@ -511,7 +505,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
511505 Err ( Determinacy :: Undetermined ) => return Err ( Determinacy :: Undetermined ) ,
512506 }
513507
514- parent_scope. module . legacy_macro_resolutions . borrow_mut ( )
508+ parent_scope. module . single_segment_macro_resolutions . borrow_mut ( )
515509 . push ( ( path[ 0 ] , kind, parent_scope. clone ( ) , binding. ok ( ) ) ) ;
516510
517511 binding. map ( |binding| binding. def_ignoring_ambiguity ( ) )
@@ -918,48 +912,66 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
918912 pub fn finalize_current_module_macro_resolutions ( & mut self ) {
919913 let module = self . current_module ;
920914
915+ let check_consistency = |this : & mut Self , path : & [ Ident ] , span,
916+ kind : MacroKind , initial_def, def| {
917+ if let Some ( initial_def) = initial_def {
918+ if def != initial_def && def != Def :: Err && this. ambiguity_errors . is_empty ( ) {
919+ // Make sure compilation does not succeed if preferred macro resolution
920+ // has changed after the macro had been expanded. In theory all such
921+ // situations should be reported as ambiguity errors, so this is a bug.
922+ span_bug ! ( span, "inconsistent resolution for a macro" ) ;
923+ }
924+ } else {
925+ // It's possible that the macro was unresolved (indeterminate) and silently
926+ // expanded into a dummy fragment for recovery during expansion.
927+ // Now, post-expansion, the resolution may succeed, but we can't change the
928+ // past and need to report an error.
929+ // However, non-speculative `resolve_path` can successfully return private items
930+ // even if speculative `resolve_path` returned nothing previously, so we skip this
931+ // less informative error if the privacy error is reported elsewhere.
932+ if this. privacy_errors . is_empty ( ) {
933+ let msg = format ! ( "cannot determine resolution for the {} `{}`" ,
934+ kind. descr( ) , names_to_string( path) ) ;
935+ let msg_note = "import resolution is stuck, try simplifying macro imports" ;
936+ this. session . struct_span_err ( span, & msg) . note ( msg_note) . emit ( ) ;
937+ }
938+ }
939+ } ;
940+
921941 let macro_resolutions =
922- mem:: replace ( & mut * module. macro_resolutions . borrow_mut ( ) , Vec :: new ( ) ) ;
923- for ( path, parent_scope, path_span ) in macro_resolutions {
942+ mem:: replace ( & mut * module. multi_segment_macro_resolutions . borrow_mut ( ) , Vec :: new ( ) ) ;
943+ for ( path, path_span , kind , parent_scope, initial_def ) in macro_resolutions {
924944 match self . resolve_path ( & path, Some ( MacroNS ) , & parent_scope,
925945 true , path_span, CrateLint :: No ) {
926- PathResult :: NonModule ( _) => { } ,
927- PathResult :: Failed ( span, msg, _) => {
946+ PathResult :: NonModule ( path_res) if path_res. unresolved_segments ( ) == 0 => {
947+ let def = path_res. base_def ( ) ;
948+ check_consistency ( self , & path, path_span, kind, initial_def, def) ;
949+ }
950+ path_res @ PathResult :: NonModule ( ..) | path_res @ PathResult :: Failed ( ..) => {
951+ let ( span, msg) = if let PathResult :: Failed ( span, msg, ..) = path_res {
952+ ( span, msg)
953+ } else {
954+ ( path_span, format ! ( "partially resolved path in {} {}" ,
955+ kind. article( ) , kind. descr( ) ) )
956+ } ;
928957 resolve_error ( self , span, ResolutionError :: FailedToResolve ( & msg) ) ;
929958 }
930- _ => unreachable ! ( ) ,
959+ PathResult :: Module ( .. ) | PathResult :: Indeterminate => unreachable ! ( ) ,
931960 }
932961 }
933962
934- let legacy_macro_resolutions =
935- mem:: replace ( & mut * module. legacy_macro_resolutions . borrow_mut ( ) , Vec :: new ( ) ) ;
936- for ( ident, kind, parent_scope, initial_binding) in legacy_macro_resolutions {
937- let binding = self . early_resolve_ident_in_lexical_scope (
938- ident, MacroNS , Some ( kind) , false , & parent_scope, true , true , ident. span
939- ) ;
940- match binding {
963+ let macro_resolutions =
964+ mem:: replace ( & mut * module. single_segment_macro_resolutions . borrow_mut ( ) , Vec :: new ( ) ) ;
965+ for ( ident, kind, parent_scope, initial_binding) in macro_resolutions {
966+ match self . early_resolve_ident_in_lexical_scope ( ident, MacroNS , Some ( kind) , false ,
967+ & parent_scope, true , true , ident. span ) {
941968 Ok ( binding) => {
942- let def = binding. def_ignoring_ambiguity ( ) ;
943- if let Some ( initial_binding) = initial_binding {
969+ let initial_def = initial_binding. map ( |initial_binding| {
944970 self . record_use ( ident, MacroNS , initial_binding) ;
945- let initial_def = initial_binding. def_ignoring_ambiguity ( ) ;
946- if self . ambiguity_errors . is_empty ( ) &&
947- def != initial_def && def != Def :: Err {
948- // Make sure compilation does not succeed if preferred macro resolution
949- // has changed after the macro had been expanded. In theory all such
950- // situations should be reported as ambiguity errors, so this is a bug.
951- span_bug ! ( ident. span, "inconsistent resolution for a macro" ) ;
952- }
953- } else {
954- // It's possible that the macro was unresolved (indeterminate) and silently
955- // expanded into a dummy fragment for recovery during expansion.
956- // Now, post-expansion, the resolution may succeed, but we can't change the
957- // past and need to report an error.
958- let msg = format ! ( "cannot determine resolution for the {} `{}`" ,
959- kind. descr( ) , ident) ;
960- let msg_note = "import resolution is stuck, try simplifying macro imports" ;
961- self . session . struct_span_err ( ident. span , & msg) . note ( msg_note) . emit ( ) ;
962- }
971+ initial_binding. def_ignoring_ambiguity ( )
972+ } ) ;
973+ let def = binding. def_ignoring_ambiguity ( ) ;
974+ check_consistency ( self , & [ ident] , ident. span , kind, initial_def, def) ;
963975 }
964976 Err ( ..) => {
965977 assert ! ( initial_binding. is_none( ) ) ;
0 commit comments