9
9
// except according to those terms.
10
10
11
11
use { AmbiguityError , AmbiguityKind , AmbiguityErrorMisc } ;
12
- use { CrateLint , DeterminacyExt , Resolver , ResolutionError , is_known_tool , resolve_error } ;
12
+ use { CrateLint , DeterminacyExt , Resolver , ResolutionError } ;
13
13
use { Module , ModuleKind , NameBinding , NameBindingKind , PathResult , ToNameBinding } ;
14
+ use { is_known_tool, names_to_string, resolve_error} ;
14
15
use ModuleOrUniformRoot ;
15
16
use Namespace :: { self , * } ;
16
17
use build_reduced_graph:: { BuildReducedGraphVisitor , IsMacroExport } ;
@@ -480,29 +481,19 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
480
481
if path. len ( ) > 1 {
481
482
let def = match self . resolve_path ( & path, Some ( MacroNS ) , parent_scope,
482
483
false , path_span, CrateLint :: No ) {
483
- PathResult :: NonModule ( path_res) => match path_res. base_def ( ) {
484
- Def :: Err => Err ( Determinacy :: Determined ) ,
485
- def @ _ => {
486
- if path_res. unresolved_segments ( ) > 0 {
487
- self . found_unresolved_macro = true ;
488
- self . session . span_err ( path_span,
489
- "fail to resolve non-ident macro path" ) ;
490
- Err ( Determinacy :: Determined )
491
- } else {
492
- Ok ( def)
493
- }
494
- }
495
- } ,
496
- PathResult :: Module ( ..) => unreachable ! ( ) ,
484
+ PathResult :: NonModule ( path_res) if path_res. unresolved_segments ( ) == 0 => {
485
+ Ok ( path_res. base_def ( ) )
486
+ }
497
487
PathResult :: Indeterminate if !force => return Err ( Determinacy :: Undetermined ) ,
498
- _ => {
488
+ PathResult :: NonModule ( .. ) | PathResult :: Indeterminate | PathResult :: Failed ( .. ) => {
499
489
self . found_unresolved_macro = true ;
500
490
Err ( Determinacy :: Determined )
501
- } ,
491
+ }
492
+ PathResult :: Module ( ..) => unreachable ! ( ) ,
502
493
} ;
503
494
504
- parent_scope. module . macro_resolutions . borrow_mut ( )
505
- . push ( ( path, parent_scope. clone ( ) , path_span ) ) ;
495
+ parent_scope. module . multi_segment_macro_resolutions . borrow_mut ( )
496
+ . push ( ( path, path_span , kind , parent_scope. clone ( ) , def . ok ( ) ) ) ;
506
497
507
498
def
508
499
} else {
@@ -515,7 +506,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
515
506
Err ( Determinacy :: Undetermined ) => return Err ( Determinacy :: Undetermined ) ,
516
507
}
517
508
518
- parent_scope. module . legacy_macro_resolutions . borrow_mut ( )
509
+ parent_scope. module . single_segment_macro_resolutions . borrow_mut ( )
519
510
. push ( ( path[ 0 ] . ident , kind, parent_scope. clone ( ) , binding. ok ( ) ) ) ;
520
511
521
512
binding. map ( |binding| binding. def_ignoring_ambiguity ( ) )
@@ -922,50 +913,68 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
922
913
pub fn finalize_current_module_macro_resolutions ( & mut self ) {
923
914
let module = self . current_module ;
924
915
916
+ let check_consistency = |this : & mut Self , path : & [ Ident ] , span,
917
+ kind : MacroKind , initial_def, def| {
918
+ if let Some ( initial_def) = initial_def {
919
+ if def != initial_def && def != Def :: Err && this. ambiguity_errors . is_empty ( ) {
920
+ // Make sure compilation does not succeed if preferred macro resolution
921
+ // has changed after the macro had been expanded. In theory all such
922
+ // situations should be reported as ambiguity errors, so this is a bug.
923
+ span_bug ! ( span, "inconsistent resolution for a macro" ) ;
924
+ }
925
+ } else {
926
+ // It's possible that the macro was unresolved (indeterminate) and silently
927
+ // expanded into a dummy fragment for recovery during expansion.
928
+ // Now, post-expansion, the resolution may succeed, but we can't change the
929
+ // past and need to report an error.
930
+ // However, non-speculative `resolve_path` can successfully return private items
931
+ // even if speculative `resolve_path` returned nothing previously, so we skip this
932
+ // less informative error if the privacy error is reported elsewhere.
933
+ if this. privacy_errors . is_empty ( ) {
934
+ let msg = format ! ( "cannot determine resolution for the {} `{}`" ,
935
+ kind. descr( ) , names_to_string( path) ) ;
936
+ let msg_note = "import resolution is stuck, try simplifying macro imports" ;
937
+ this. session . struct_span_err ( span, & msg) . note ( msg_note) . emit ( ) ;
938
+ }
939
+ }
940
+ } ;
941
+
925
942
let macro_resolutions =
926
- mem:: replace ( & mut * module. macro_resolutions . borrow_mut ( ) , Vec :: new ( ) ) ;
927
- for ( mut path, parent_scope, path_span ) in macro_resolutions {
943
+ mem:: replace ( & mut * module. multi_segment_macro_resolutions . borrow_mut ( ) , Vec :: new ( ) ) ;
944
+ for ( mut path, path_span , kind , parent_scope, initial_def ) in macro_resolutions {
928
945
// FIXME: Path resolution will ICE if segment IDs present.
929
946
for seg in & mut path { seg. id = None ; }
930
947
match self . resolve_path ( & path, Some ( MacroNS ) , & parent_scope,
931
948
true , path_span, CrateLint :: No ) {
932
- PathResult :: NonModule ( _) => { } ,
933
- PathResult :: Failed ( span, msg, _) => {
949
+ PathResult :: NonModule ( path_res) if path_res. unresolved_segments ( ) == 0 => {
950
+ let def = path_res. base_def ( ) ;
951
+ check_consistency ( self , & path, path_span, kind, initial_def, def) ;
952
+ }
953
+ path_res @ PathResult :: NonModule ( ..) | path_res @ PathResult :: Failed ( ..) => {
954
+ let ( span, msg) = if let PathResult :: Failed ( span, msg, ..) = path_res {
955
+ ( span, msg)
956
+ } else {
957
+ ( path_span, format ! ( "partially resolved path in {} {}" ,
958
+ kind. article( ) , kind. descr( ) ) )
959
+ } ;
934
960
resolve_error ( self , span, ResolutionError :: FailedToResolve ( & msg) ) ;
935
961
}
936
- _ => unreachable ! ( ) ,
962
+ PathResult :: Module ( .. ) | PathResult :: Indeterminate => unreachable ! ( ) ,
937
963
}
938
964
}
939
965
940
- let legacy_macro_resolutions =
941
- mem:: replace ( & mut * module. legacy_macro_resolutions . borrow_mut ( ) , Vec :: new ( ) ) ;
942
- for ( ident, kind, parent_scope, initial_binding) in legacy_macro_resolutions {
943
- let binding = self . early_resolve_ident_in_lexical_scope (
944
- ident, MacroNS , Some ( kind) , false , & parent_scope, true , true , ident. span
945
- ) ;
946
- match binding {
966
+ let macro_resolutions =
967
+ mem:: replace ( & mut * module. single_segment_macro_resolutions . borrow_mut ( ) , Vec :: new ( ) ) ;
968
+ for ( ident, kind, parent_scope, initial_binding) in macro_resolutions {
969
+ match self . early_resolve_ident_in_lexical_scope ( ident, MacroNS , Some ( kind) , false ,
970
+ & parent_scope, true , true , ident. span ) {
947
971
Ok ( binding) => {
948
- let def = binding. def_ignoring_ambiguity ( ) ;
949
- if let Some ( initial_binding) = initial_binding {
972
+ let initial_def = initial_binding. map ( |initial_binding| {
950
973
self . record_use ( ident, MacroNS , initial_binding) ;
951
- let initial_def = initial_binding. def_ignoring_ambiguity ( ) ;
952
- if self . ambiguity_errors . is_empty ( ) &&
953
- def != initial_def && def != Def :: Err {
954
- // Make sure compilation does not succeed if preferred macro resolution
955
- // has changed after the macro had been expanded. In theory all such
956
- // situations should be reported as ambiguity errors, so this is a bug.
957
- span_bug ! ( ident. span, "inconsistent resolution for a macro" ) ;
958
- }
959
- } else {
960
- // It's possible that the macro was unresolved (indeterminate) and silently
961
- // expanded into a dummy fragment for recovery during expansion.
962
- // Now, post-expansion, the resolution may succeed, but we can't change the
963
- // past and need to report an error.
964
- let msg = format ! ( "cannot determine resolution for the {} `{}`" ,
965
- kind. descr( ) , ident) ;
966
- let msg_note = "import resolution is stuck, try simplifying macro imports" ;
967
- self . session . struct_span_err ( ident. span , & msg) . note ( msg_note) . emit ( ) ;
968
- }
974
+ initial_binding. def_ignoring_ambiguity ( )
975
+ } ) ;
976
+ let def = binding. def_ignoring_ambiguity ( ) ;
977
+ check_consistency ( self , & [ ident] , ident. span , kind, initial_def, def) ;
969
978
}
970
979
Err ( ..) => {
971
980
assert ! ( initial_binding. is_none( ) ) ;
0 commit comments