@@ -564,97 +564,98 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
564564 let prefix = crate_root. into_iter ( ) . chain ( prefix_iter) . collect :: < Vec < _ > > ( ) ;
565565 debug ! ( "build_reduced_graph_for_use_tree: prefix={:?}" , prefix) ;
566566
567- let empty_for_self = |prefix : & [ Segment ] | {
568- prefix. is_empty ( ) || prefix. len ( ) == 1 && prefix[ 0 ] . ident . name == kw:: PathRoot
569- } ;
570567 match use_tree. kind {
571568 ast:: UseTreeKind :: Simple ( rename) => {
572569 let mut ident = use_tree. ident ( ) ;
573570 let mut module_path = prefix;
574571 let mut source = module_path. pop ( ) . unwrap ( ) ;
575- let mut type_ns_only = false ;
576-
577- if nested {
578- // Correctly handle `self`
579- if source. ident . name == kw:: SelfLower {
580- type_ns_only = true ;
581572
582- if empty_for_self ( & module_path) {
583- self . r . report_error (
584- use_tree. span ,
585- ResolutionError :: SelfImportOnlyInImportListWithNonEmptyPrefix ,
573+ // `true` for `...::{self [as target]}` imports, `false` otherwise.
574+ let type_ns_only = nested
575+ && source. ident . name == kw:: SelfLower
576+ && use_tree. prefix . segments . len ( ) == 1 ;
577+
578+ match source. ident . name {
579+ kw:: DollarCrate => {
580+ if !module_path. is_empty ( ) {
581+ self . r . dcx ( ) . span_err (
582+ source. ident . span ,
583+ "`$crate` in paths can only be used in start position" ,
586584 ) ;
587585 return ;
588586 }
589-
590- // Replace `use foo::{ self };` with `use foo;`
591- let self_span = source. ident . span ;
592- source = module_path. pop ( ) . unwrap ( ) ;
593- if rename. is_none ( ) {
594- // Keep the span of `self`, but the name of `foo`
595- ident = Ident :: new ( source. ident . name , self_span) ;
587+ }
588+ kw:: Crate => {
589+ if !module_path. is_empty ( ) {
590+ self . r . dcx ( ) . span_err (
591+ source. ident . span ,
592+ "`crate` in paths can only be used in start position" ,
593+ ) ;
594+ return ;
596595 }
597596 }
598- } else {
599- // Disallow `self`
600- if source. ident . name == kw:: SelfLower {
601- let parent = module_path. last ( ) ;
602-
603- let span = match parent {
604- // only `::self` from `use foo::self as bar`
605- Some ( seg) => seg. ident . span . shrink_to_hi ( ) . to ( source. ident . span ) ,
606- None => source. ident . span ,
607- } ;
608- let span_with_rename = match rename {
609- // only `self as bar` from `use foo::self as bar`
610- Some ( rename) => source. ident . span . to ( rename. span ) ,
611- None => source. ident . span ,
612- } ;
613- self . r . report_error (
614- span,
615- ResolutionError :: SelfImportsOnlyAllowedWithin {
616- root : parent. is_none ( ) ,
617- span_with_rename,
618- } ,
619- ) ;
620-
621- // Error recovery: replace `use foo::self;` with `use foo;`
597+ kw:: Super => {
598+ if module_path. iter ( ) . any ( |seg| seg. ident . name != kw:: Super ) {
599+ self . r . dcx ( ) . span_err (
600+ source. ident . span ,
601+ "`super` in paths can only be used in start position or after another `super`" ,
602+ ) ;
603+ return ;
604+ }
605+ }
606+ kw:: SelfLower => {
622607 if let Some ( parent) = module_path. pop ( ) {
608+ // Suggest `use prefix::{self};` for `use prefix::self;`
609+ if !type_ns_only
610+ && ( parent. ident . name != kw:: PathRoot
611+ || self . r . path_root_is_crate_root ( parent. ident ) )
612+ {
613+ let span_with_rename = match rename {
614+ Some ( rename) => source. ident . span . to ( rename. span ) ,
615+ None => source. ident . span ,
616+ } ;
617+
618+ self . r . report_error (
619+ parent. ident . span . shrink_to_hi ( ) . to ( source. ident . span ) ,
620+ ResolutionError :: SelfImportsOnlyAllowedWithin {
621+ root : parent. ident . name == kw:: PathRoot ,
622+ span_with_rename,
623+ } ,
624+ ) ;
625+ }
626+
627+ let self_span = source. ident . span ;
623628 source = parent;
624629 if rename. is_none ( ) {
625- ident = source. ident ;
630+ ident = Ident :: new ( source. ident . name , self_span ) ;
626631 }
627632 }
628633 }
634+ _ => { }
635+ }
629636
630- // Disallow `use $crate;`
631- if source. ident . name == kw:: DollarCrate && module_path. is_empty ( ) {
632- let crate_root = self . r . resolve_crate_root ( source. ident ) ;
633- let crate_name = match crate_root. kind {
634- ModuleKind :: Def ( .., name) => name,
635- ModuleKind :: Block => unreachable ! ( ) ,
636- } ;
637- // HACK(eddyb) unclear how good this is, but keeping `$crate`
638- // in `source` breaks `tests/ui/imports/import-crate-var.rs`,
639- // while the current crate doesn't have a valid `crate_name`.
640- if let Some ( crate_name) = crate_name {
641- // `crate_name` should not be interpreted as relative.
642- module_path. push ( Segment :: from_ident_and_id (
643- Ident :: new ( kw:: PathRoot , source. ident . span ) ,
644- self . r . next_node_id ( ) ,
645- ) ) ;
646- source. ident . name = crate_name;
647- }
648- if rename. is_none ( ) {
649- ident. name = sym:: dummy;
650- }
651-
652- self . r . dcx ( ) . emit_err ( errors:: CrateImported { span : item. span } ) ;
653- }
637+ // Deny `use ::{self};` after edition 2015
638+ if source. ident . name == kw:: PathRoot
639+ && !self . r . path_root_is_crate_root ( source. ident )
640+ {
641+ self . r . dcx ( ) . span_err ( use_tree. span , "extern prelude cannot be imported" ) ;
642+ return ;
654643 }
655644
656- if ident. name == kw:: Crate {
657- self . r . dcx ( ) . emit_err ( errors:: UnnamedCrateRootImport { span : ident. span } ) ;
645+ // Deny importing path-kw without renaming
646+ if rename. is_none ( ) && ident. is_path_segment_keyword ( ) {
647+ let ident = use_tree. ident ( ) ;
648+
649+ // Don't suggest `use xx::self as name;` for `use xx::self;`
650+ // But it's OK to suggest `use xx::{self as name};` for `use xx::{self};`
651+ let sugg = if !type_ns_only && ident. name == kw:: SelfLower {
652+ None
653+ } else {
654+ Some ( errors:: UnnamedImportSugg { span : ident. span , ident } )
655+ } ;
656+
657+ self . r . dcx ( ) . emit_err ( errors:: UnnamedImport { span : ident. span , sugg } ) ;
658+ return ;
658659 }
659660
660661 let kind = ImportKind :: Single {
@@ -684,32 +685,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
684685 }
685686 }
686687 ast:: UseTreeKind :: Nested { ref items, .. } => {
687- // Ensure there is at most one `self` in the list
688- let self_spans = items
689- . iter ( )
690- . filter_map ( |( use_tree, _) | {
691- if let ast:: UseTreeKind :: Simple ( ..) = use_tree. kind
692- && use_tree. ident ( ) . name == kw:: SelfLower
693- {
694- return Some ( use_tree. span ) ;
695- }
696-
697- None
698- } )
699- . collect :: < Vec < _ > > ( ) ;
700- if self_spans. len ( ) > 1 {
701- let mut e = self . r . into_struct_error (
702- self_spans[ 0 ] ,
703- ResolutionError :: SelfImportCanOnlyAppearOnceInTheList ,
704- ) ;
705-
706- for other_span in self_spans. iter ( ) . skip ( 1 ) {
707- e. span_label ( * other_span, "another `self` import appears here" ) ;
708- }
709-
710- e. emit ( ) ;
711- }
712-
713688 for & ( ref tree, id) in items {
714689 self . build_reduced_graph_for_use_tree (
715690 // This particular use tree
@@ -721,7 +696,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
721696 // Empty groups `a::b::{}` are turned into synthetic `self` imports
722697 // `a::b::c::{self as _}`, so that their prefixes are correctly
723698 // resolved and checked for privacy/stability/etc.
724- if items. is_empty ( ) && !empty_for_self ( & prefix) {
699+ if items. is_empty ( )
700+ && !prefix. is_empty ( )
701+ && ( prefix. len ( ) > 1 || prefix[ 0 ] . ident . name != kw:: PathRoot )
702+ {
725703 let new_span = prefix[ prefix. len ( ) - 1 ] . ident . span ;
726704 let tree = ast:: UseTree {
727705 prefix : ast:: Path :: from_ident ( Ident :: new ( kw:: SelfLower , new_span) ) ,
0 commit comments