@@ -620,9 +620,9 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
620
620
}
621
621
622
622
#[ derive( Default ) ]
623
- struct UniformPathsCanaryResult {
624
- module_scope : Option < Span > ,
625
- block_scopes : Vec < Span > ,
623
+ struct UniformPathsCanaryResult < ' a > {
624
+ module_scope : Option < & ' a NameBinding < ' a > > ,
625
+ block_scopes : Vec < & ' a NameBinding < ' a > > ,
626
626
}
627
627
// Collect all tripped `uniform_paths` canaries separately.
628
628
let mut uniform_paths_canaries: BTreeMap <
@@ -663,20 +663,12 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
663
663
664
664
self . per_ns ( |_, ns| {
665
665
if let Some ( result) = result[ ns] . get ( ) . ok ( ) {
666
- if let NameBindingKind :: Import { directive, .. } = result. kind {
667
- // Skip canaries that resolve to the import itself.
668
- // These come from `use crate_name;`, which isn't really
669
- // ambiguous, as the import can't actually shadow itself.
670
- if directive. id == import. id {
671
- return ;
672
- }
673
- }
674
666
if has_explicit_self {
675
667
// There should only be one `self::x` (module-scoped) canary.
676
- assert_eq ! ( canary_results[ ns] . module_scope, None ) ;
677
- canary_results[ ns] . module_scope = Some ( result. span ) ;
668
+ assert ! ( canary_results[ ns] . module_scope. is_none ( ) ) ;
669
+ canary_results[ ns] . module_scope = Some ( result) ;
678
670
} else {
679
- canary_results[ ns] . block_scopes . push ( result. span ) ;
671
+ canary_results[ ns] . block_scopes . push ( result) ;
680
672
}
681
673
}
682
674
} ) ;
@@ -716,18 +708,39 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
716
708
}
717
709
}
718
710
711
+ let uniform_paths_feature = self . session . features_untracked ( ) . uniform_paths ;
719
712
for ( ( span, _) , ( name, results) ) in uniform_paths_canaries {
720
713
self . per_ns ( |this, ns| {
721
- let results = & results[ ns] ;
714
+ let external_crate = if ns == TypeNS && this. extern_prelude . contains ( & name) {
715
+ let crate_id =
716
+ this. crate_loader . process_path_extern ( name, span) ;
717
+ Some ( DefId { krate : crate_id, index : CRATE_DEF_INDEX } )
718
+ } else {
719
+ None
720
+ } ;
721
+ let result_filter = |result : & & NameBinding | {
722
+ // Ignore canaries that resolve to an import of the same crate.
723
+ // That is, we allow `use crate_name; use crate_name::foo;`.
724
+ if let Some ( def_id) = external_crate {
725
+ if let Some ( module) = result. module ( ) {
726
+ if module. normal_ancestor_id == def_id {
727
+ return false ;
728
+ }
729
+ }
730
+ }
722
731
723
- let has_external_crate =
724
- ns == TypeNS && this. extern_prelude . contains ( & name) ;
732
+ true
733
+ } ;
734
+ let module_scope = results[ ns] . module_scope . filter ( result_filter) ;
735
+ let block_scopes = || {
736
+ results[ ns] . block_scopes . iter ( ) . cloned ( ) . filter ( result_filter)
737
+ } ;
725
738
726
739
// An ambiguity requires more than one possible resolution.
727
740
let possible_resultions =
728
- ( has_external_crate as usize ) +
729
- ( results . module_scope . is_some ( ) as usize ) +
730
- ( !results . block_scopes . is_empty ( ) as usize ) ;
741
+ ( external_crate . is_some ( ) as usize ) +
742
+ ( module_scope. is_some ( ) as usize ) +
743
+ ( block_scopes ( ) . next ( ) . is_some ( ) as usize ) ;
731
744
if possible_resultions <= 1 {
732
745
return ;
733
746
}
@@ -737,25 +750,34 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
737
750
let msg = format ! ( "`{}` import is ambiguous" , name) ;
738
751
let mut err = this. session . struct_span_err ( span, & msg) ;
739
752
let mut suggestion_choices = String :: new ( ) ;
740
- if has_external_crate {
753
+ if external_crate . is_some ( ) {
741
754
write ! ( suggestion_choices, "`::{}`" , name) ;
742
755
err. span_label ( span,
743
756
format ! ( "can refer to external crate `::{}`" , name) ) ;
744
757
}
745
- if let Some ( span ) = results . module_scope {
758
+ if let Some ( result ) = module_scope {
746
759
if !suggestion_choices. is_empty ( ) {
747
760
suggestion_choices. push_str ( " or " ) ;
748
761
}
749
762
write ! ( suggestion_choices, "`self::{}`" , name) ;
750
- err. span_label ( span,
751
- format ! ( "can refer to `self::{}`" , name) ) ;
763
+ if uniform_paths_feature {
764
+ err. span_label ( result. span ,
765
+ format ! ( "can refer to `self::{}`" , name) ) ;
766
+ } else {
767
+ err. span_label ( result. span ,
768
+ format ! ( "may refer to `self::{}` in the future" , name) ) ;
769
+ }
752
770
}
753
- for & span in & results . block_scopes {
754
- err. span_label ( span,
771
+ for result in block_scopes ( ) {
772
+ err. span_label ( result . span ,
755
773
format ! ( "shadowed by block-scoped `{}`" , name) ) ;
756
774
}
757
775
err. help ( & format ! ( "write {} explicitly instead" , suggestion_choices) ) ;
758
- err. note ( "relative `use` paths enabled by `#![feature(uniform_paths)]`" ) ;
776
+ if uniform_paths_feature {
777
+ err. note ( "relative `use` paths enabled by `#![feature(uniform_paths)]`" ) ;
778
+ } else {
779
+ err. note ( "in the future, `#![feature(uniform_paths)]` may become the default" ) ;
780
+ }
759
781
err. emit ( ) ;
760
782
} ) ;
761
783
}
@@ -968,11 +990,15 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
968
990
_ => unreachable ! ( ) ,
969
991
} ;
970
992
993
+ // Do not record uses from canaries, to avoid interfering with other
994
+ // diagnostics or suggestions that rely on some items not being used.
995
+ let record_used = !directive. is_uniform_paths_canary ;
996
+
971
997
let mut all_ns_err = true ;
972
998
self . per_ns ( |this, ns| if !type_ns_only || ns == TypeNS {
973
999
if let Ok ( binding) = result[ ns] . get ( ) {
974
1000
all_ns_err = false ;
975
- if this. record_use ( ident, ns, binding) {
1001
+ if record_used && this. record_use ( ident, ns, binding) {
976
1002
if let ModuleOrUniformRoot :: Module ( module) = module {
977
1003
this. resolution ( module, ident, ns) . borrow_mut ( ) . binding =
978
1004
Some ( this. dummy_binding ) ;
@@ -984,7 +1010,7 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
984
1010
if all_ns_err {
985
1011
let mut all_ns_failed = true ;
986
1012
self . per_ns ( |this, ns| if !type_ns_only || ns == TypeNS {
987
- match this. resolve_ident_in_module ( module, ident, ns, true , span) {
1013
+ match this. resolve_ident_in_module ( module, ident, ns, record_used , span) {
988
1014
Ok ( _) => all_ns_failed = false ,
989
1015
_ => { }
990
1016
}
0 commit comments