@@ -21,9 +21,9 @@ use rustc::ty;
21
21
use rustc:: lint:: builtin:: PUB_USE_OF_PRIVATE_EXTERN_CRATE ;
22
22
use rustc:: hir:: def_id:: DefId ;
23
23
use rustc:: hir:: def:: * ;
24
- use rustc:: util:: nodemap:: FxHashMap ;
24
+ use rustc:: util:: nodemap:: { FxHashMap , FxHashSet } ;
25
25
26
- use syntax:: ast:: { Ident , NodeId } ;
26
+ use syntax:: ast:: { Ident , SpannedIdent , NodeId } ;
27
27
use syntax:: ext:: base:: Determinacy :: { self , Determined , Undetermined } ;
28
28
use syntax:: ext:: hygiene:: Mark ;
29
29
use syntax:: parse:: token;
@@ -57,7 +57,7 @@ pub enum ImportDirectiveSubclass<'a> {
57
57
pub struct ImportDirective < ' a > {
58
58
pub id : NodeId ,
59
59
pub parent : Module < ' a > ,
60
- pub module_path : Vec < Ident > ,
60
+ pub module_path : Vec < SpannedIdent > ,
61
61
pub imported_module : Cell < Option < Module < ' a > > > , // the resolution of `module_path`
62
62
pub subclass : ImportDirectiveSubclass < ' a > ,
63
63
pub span : Span ,
@@ -256,7 +256,7 @@ impl<'a> Resolver<'a> {
256
256
257
257
// Add an import directive to the current module.
258
258
pub fn add_import_directive ( & mut self ,
259
- module_path : Vec < Ident > ,
259
+ module_path : Vec < SpannedIdent > ,
260
260
subclass : ImportDirectiveSubclass < ' a > ,
261
261
span : Span ,
262
262
id : NodeId ,
@@ -478,9 +478,10 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
478
478
}
479
479
480
480
let mut errors = false ;
481
+ let mut seen_spans = FxHashSet ( ) ;
481
482
for i in 0 .. self . determined_imports . len ( ) {
482
483
let import = self . determined_imports [ i] ;
483
- if let Some ( err) = self . finalize_import ( import) {
484
+ if let Some ( ( span , err) ) = self . finalize_import ( import) {
484
485
errors = true ;
485
486
486
487
if let SingleImport { source, ref result, .. } = import. subclass {
@@ -496,9 +497,14 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
496
497
// If the error is a single failed import then create a "fake" import
497
498
// resolution for it so that later resolve stages won't complain.
498
499
self . import_dummy_binding ( import) ;
499
- let path = import_path_to_string ( & import. module_path , & import. subclass ) ;
500
- let error = ResolutionError :: UnresolvedImport ( Some ( ( & path, & err) ) ) ;
501
- resolve_error ( self . resolver , import. span , error) ;
500
+ if !seen_spans. contains ( & span) {
501
+ let path = import_path_to_string ( & import. module_path [ ..] ,
502
+ & import. subclass ,
503
+ span) ;
504
+ let error = ResolutionError :: UnresolvedImport ( Some ( ( span, & path, & err) ) ) ;
505
+ resolve_error ( self . resolver , span, error) ;
506
+ seen_spans. insert ( span) ;
507
+ }
502
508
}
503
509
}
504
510
@@ -516,7 +522,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
516
522
/// If successful, the resolved bindings are written into the module.
517
523
fn resolve_import ( & mut self , directive : & ' b ImportDirective < ' b > ) -> bool {
518
524
debug ! ( "(resolving import for module) resolving import `{}::...` in `{}`" ,
519
- names_to_string( & directive. module_path) ,
525
+ names_to_string( & directive. module_path[ .. ] ) ,
520
526
module_to_string( self . current_module) ) ;
521
527
522
528
self . current_module = directive. parent ;
@@ -528,7 +534,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
528
534
// For better failure detection, pretend that the import will not define any names
529
535
// while resolving its module path.
530
536
directive. vis . set ( ty:: Visibility :: Invisible ) ;
531
- let result = self . resolve_path ( & directive. module_path , None , false , directive. span ) ;
537
+ let result = self . resolve_path ( & directive. module_path [ .. ] , None , false , directive. span ) ;
532
538
directive. vis . set ( vis) ;
533
539
534
540
match result {
@@ -593,23 +599,25 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
593
599
}
594
600
595
601
// If appropriate, returns an error to report.
596
- fn finalize_import ( & mut self , directive : & ' b ImportDirective < ' b > ) -> Option < String > {
602
+ fn finalize_import ( & mut self , directive : & ' b ImportDirective < ' b > ) -> Option < ( Span , String ) > {
597
603
self . current_module = directive. parent ;
598
604
599
605
let ImportDirective { ref module_path, span, .. } = * directive;
600
606
let module_result = self . resolve_path ( & module_path, None , true , span) ;
601
607
let module = match module_result {
602
608
PathResult :: Module ( module) => module,
603
- PathResult :: Failed ( msg, _) => {
609
+ PathResult :: Failed ( span , msg, _) => {
604
610
let ( mut self_path, mut self_result) = ( module_path. clone ( ) , None ) ;
605
- if !self_path. is_empty ( ) && !token:: Ident ( self_path[ 0 ] ) . is_path_segment_keyword ( ) {
606
- self_path[ 0 ] . name = keywords:: SelfValue . name ( ) ;
611
+ if !self_path. is_empty ( ) &&
612
+ !token:: Ident ( self_path[ 0 ] . node ) . is_path_segment_keyword ( )
613
+ {
614
+ self_path[ 0 ] . node . name = keywords:: SelfValue . name ( ) ;
607
615
self_result = Some ( self . resolve_path ( & self_path, None , false , span) ) ;
608
616
}
609
617
return if let Some ( PathResult :: Module ( ..) ) = self_result {
610
- Some ( format ! ( "Did you mean `{}`?" , names_to_string( & self_path) ) )
618
+ Some ( ( span , format ! ( "Did you mean `{}`?" , names_to_string( & self_path[ .. ] ) ) ) )
611
619
} else {
612
- Some ( msg)
620
+ Some ( ( span , msg) )
613
621
} ;
614
622
} ,
615
623
_ => return None ,
@@ -619,7 +627,8 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
619
627
SingleImport { source, ref result, type_ns_only, .. } => ( source, result, type_ns_only) ,
620
628
GlobImport { .. } if module. def_id ( ) == directive. parent . def_id ( ) => {
621
629
// Importing a module into itself is not allowed.
622
- return Some ( "Cannot glob-import a module into itself." . to_string ( ) ) ;
630
+ return Some ( ( directive. span ,
631
+ "Cannot glob-import a module into itself." . to_string ( ) ) ) ;
623
632
}
624
633
GlobImport { is_prelude, ref max_vis } => {
625
634
if !is_prelude &&
@@ -708,7 +717,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
708
717
} else {
709
718
format ! ( "no `{}` in `{}`{}" , ident, module_str, lev_suggestion)
710
719
} ;
711
- Some ( msg)
720
+ Some ( ( span , msg) )
712
721
} else {
713
722
// `resolve_ident_in_module` reported a privacy error.
714
723
self . import_dummy_binding ( directive) ;
@@ -888,16 +897,24 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> {
888
897
}
889
898
}
890
899
891
- fn import_path_to_string ( names : & [ Ident ] , subclass : & ImportDirectiveSubclass ) -> String {
892
- let global = !names. is_empty ( ) && names[ 0 ] . name == keywords:: CrateRoot . name ( ) ;
893
- let names = if global { & names[ 1 ..] } else { names } ;
894
- if names. is_empty ( ) {
895
- import_directive_subclass_to_string ( subclass)
900
+ fn import_path_to_string ( names : & [ SpannedIdent ] ,
901
+ subclass : & ImportDirectiveSubclass ,
902
+ span : Span ) -> String {
903
+ let pos = names. iter ( )
904
+ . position ( |p| span == p. span && p. node . name != keywords:: CrateRoot . name ( ) ) ;
905
+ let global = !names. is_empty ( ) && names[ 0 ] . node . name == keywords:: CrateRoot . name ( ) ;
906
+ if let Some ( pos) = pos {
907
+ let names = if global { & names[ 1 ..pos + 1 ] } else { & names[ ..pos + 1 ] } ;
908
+ names_to_string ( names)
896
909
} else {
897
- ( format ! ( "{}::{}" ,
898
- names_to_string( names) ,
899
- import_directive_subclass_to_string( subclass) ) )
900
- . to_string ( )
910
+ let names = if global { & names[ 1 ..] } else { names } ;
911
+ if names. is_empty ( ) {
912
+ import_directive_subclass_to_string ( subclass)
913
+ } else {
914
+ ( format ! ( "{}::{}" ,
915
+ names_to_string( names) ,
916
+ import_directive_subclass_to_string( subclass) ) )
917
+ }
901
918
}
902
919
}
903
920
0 commit comments