@@ -564,6 +564,20 @@ 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+ // Check that `super` segments are only at the start of the path.
568+ let mut meet_non_super = false ;
569+ for seg in & prefix {
570+ if seg. ident . name != kw:: Super {
571+ meet_non_super = true ;
572+ } else if meet_non_super {
573+ self . r . dcx ( ) . span_err (
574+ seg. ident . span ,
575+ "`super` is only supposed to be used in start position, or after another `super`" ,
576+ ) ;
577+ return ;
578+ }
579+ }
580+
567581 let empty_for_self = |prefix : & [ Segment ] | {
568582 prefix. is_empty ( ) || prefix. len ( ) == 1 && prefix[ 0 ] . ident . name == kw:: PathRoot
569583 } ;
@@ -572,63 +586,54 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
572586 let mut ident = use_tree. ident ( ) ;
573587 let mut module_path = prefix;
574588 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 ;
581-
582- if empty_for_self ( & module_path) {
583- self . r . report_error (
584- use_tree. span ,
585- ResolutionError :: SelfImportOnlyInImportListWithNonEmptyPrefix ,
589+ let type_ns_only = nested
590+ && source. ident . name == kw:: SelfLower
591+ && use_tree. prefix . segments . len ( ) == 1 ;
592+
593+ match source. ident . name {
594+ kw:: Crate => {
595+ if !module_path. is_empty ( ) {
596+ self . r . dcx ( ) . span_err (
597+ source. ident . span ,
598+ "`crate` in paths can only be used in start position" ,
586599 ) ;
587600 return ;
588601 }
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) ;
596- }
597602 }
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;`
603+ kw:: SelfLower => {
622604 if let Some ( parent) = module_path. pop ( ) {
605+ let span_with_rename = match rename {
606+ Some ( rename) => source. ident . span . to ( rename. span ) ,
607+ None => source. ident . span ,
608+ } ;
609+
610+ // Suggest `use prefix::{self};` for `use prefix::self;`
611+ if !type_ns_only && parent. ident . name != kw:: PathRoot {
612+ self . r . report_error (
613+ parent. ident . span . shrink_to_hi ( ) . to ( source. ident . span ) ,
614+ ResolutionError :: SelfImportsOnlyAllowedWithin {
615+ root : false ,
616+ span_with_rename,
617+ } ,
618+ ) ;
619+ }
620+
621+ let self_span = source. ident . span ;
623622 source = parent;
624623 if rename. is_none ( ) {
625- ident = source. ident ;
624+ ident = Ident :: new ( source. ident . name , self_span ) ;
626625 }
627626 }
628627 }
628+ kw:: DollarCrate => {
629+ if !module_path. is_empty ( ) {
630+ self . r . dcx ( ) . span_err (
631+ source. ident . span ,
632+ "`$crate` in paths can only be used in start position" ,
633+ ) ;
634+ return ;
635+ }
629636
630- // Disallow `use $crate;`
631- if source. ident . name == kw:: DollarCrate && module_path. is_empty ( ) {
632637 let crate_root = self . r . resolve_crate_root ( source. ident ) ;
633638 let crate_name = match crate_root. kind {
634639 ModuleKind :: Def ( .., name) => name,
@@ -645,16 +650,53 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
645650 ) ) ;
646651 source. ident . name = crate_name;
647652 }
648- if rename. is_none ( ) {
649- ident. name = sym:: dummy;
650- }
651-
652- self . r . dcx ( ) . emit_err ( errors:: CrateImported { span : item. span } ) ;
653653 }
654+ _ => { }
654655 }
655656
656- if ident. name == kw:: Crate {
657- self . r . dcx ( ) . emit_err ( errors:: UnnamedCrateRootImport { span : ident. span } ) ;
657+ // Deny `use ::{self};`
658+ if source. ident . name == kw:: PathRoot {
659+ self . r . dcx ( ) . span_err ( use_tree. span , "crate root cannot be imported" ) ;
660+ return ;
661+ }
662+
663+ if rename. is_none ( ) {
664+ match ident. name {
665+ // Deny `use crate;` and `use crate::{self};`
666+ kw:: Crate => {
667+ self . r
668+ . dcx ( )
669+ . emit_err ( errors:: UnnamedCrateRootImport { span : ident. span } ) ;
670+ return ;
671+ }
672+ // Deny `use $crate;` and `use $crate::{self};`
673+ kw:: DollarCrate => {
674+ self . r . dcx ( ) . emit_err ( errors:: CrateImported { span : ident. span } ) ;
675+ return ;
676+ }
677+ // Deny `use super;`, `use super::{self};`, `use self;` and `use self::{self};`
678+ kw:: Super | kw:: SelfLower => {
679+ let ident = use_tree. ident ( ) ;
680+
681+ // Don't suggest `use super::self as name;` for `use super::self;`
682+ // But it's OK to suggest `use super::{self as name};` for `use super::{self};`
683+ let sugg = if !type_ns_only && ident. name == kw:: SelfLower {
684+ None
685+ } else {
686+ Some ( errors:: UnnamedSuperOrSelfImportSugg {
687+ span : ident. span ,
688+ ident,
689+ } )
690+ } ;
691+
692+ self . r . dcx ( ) . emit_err ( errors:: UnnamedSuperOrSelfImport {
693+ span : ident. span ,
694+ sugg,
695+ } ) ;
696+ return ;
697+ }
698+ _ => ( ) ,
699+ }
658700 }
659701
660702 let kind = ImportKind :: Single {
@@ -684,32 +726,6 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
684726 }
685727 }
686728 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-
713729 for & ( ref tree, id) in items {
714730 self . build_reduced_graph_for_use_tree (
715731 // This particular use tree
0 commit comments