]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #48917 - petrochenkov:import, r=oli-obk
authorbors <bors@rust-lang.org>
Sun, 18 Mar 2018 01:50:52 +0000 (01:50 +0000)
committerbors <bors@rust-lang.org>
Sun, 18 Mar 2018 01:50:52 +0000 (01:50 +0000)
syntax: Make imports in AST closer to the source and cleanup their parsing

This is a continuation of https://github.com/rust-lang/rust/pull/45846 in some sense.

39 files changed:
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/ich/impls_hir.rs
src/librustc/session/config.rs
src/librustc_allocator/expand.rs
src/librustc_driver/driver.rs
src/librustc_lint/builtin.rs
src/librustc_lint/unused.rs
src/librustc_metadata/creader.rs
src/librustc_metadata/cstore_impl.rs
src/librustc_mir/build/mod.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_save_analysis/dump_visitor.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustdoc/visit_ast.rs
src/libsyntax/ast.rs
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/quote.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libsyntax/test.rs
src/libsyntax/visit.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/global_asm.rs
src/libsyntax_pos/lib.rs
src/test/compile-fail/lint-unnecessary-import-braces.rs

index b804cf7bf5a34d532f4917f7a385610770e2001f..972278bdf865fb5bd61db6acc405caa4e05f4c16 100644 (file)
@@ -444,10 +444,10 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
     visitor.visit_vis(&item.vis);
     visitor.visit_name(item.span, item.name);
     match item.node {
-        ItemExternCrate(opt_name) => {
+        ItemExternCrate(orig_name) => {
             visitor.visit_id(item.id);
-            if let Some(name) = opt_name {
-                visitor.visit_name(item.span, name);
+            if let Some(orig_name) = orig_name {
+                visitor.visit_name(item.span, orig_name);
             }
         }
         ItemUse(ref path, _) => {
index 49611689fc4af5c8b883254cbe10909b9bd24bd0..1439410f7e9aa2ac025f2d23b92363cc77a1f9ff 100644 (file)
@@ -879,7 +879,7 @@ fn lower_ty(&mut self, t: &Ty, itctx: ImplTraitContext) -> P<hir::Ty> {
             TyKind::Slice(ref ty) => hir::TySlice(self.lower_ty(ty, itctx)),
             TyKind::Ptr(ref mt) => hir::TyPtr(self.lower_mt(mt, itctx)),
             TyKind::Rptr(ref region, ref mt) => {
-                let span = t.span.with_hi(t.span.lo());
+                let span = t.span.shrink_to_lo();
                 let lifetime = match *region {
                     Some(ref lt) => self.lower_lifetime(lt),
                     None => self.elided_lifetime(span)
@@ -1355,17 +1355,11 @@ fn lower_path_extra(&mut self,
                         id: NodeId,
                         p: &Path,
                         name: Option<Name>,
-                        param_mode: ParamMode,
-                        defaults_to_global: bool)
+                        param_mode: ParamMode)
                         -> hir::Path {
-        let mut segments = p.segments.iter();
-        if defaults_to_global && p.is_global() {
-            segments.next();
-        }
-
         hir::Path {
             def: self.expect_full_def(id),
-            segments: segments.map(|segment| {
+            segments: p.segments.iter().map(|segment| {
                 self.lower_path_segment(p.span, segment, param_mode, 0,
                                         ParenthesizedGenericArgs::Err,
                                         ImplTraitContext::Disallowed)
@@ -1378,10 +1372,9 @@ fn lower_path_extra(&mut self,
     fn lower_path(&mut self,
                   id: NodeId,
                   p: &Path,
-                  param_mode: ParamMode,
-                  defaults_to_global: bool)
+                  param_mode: ParamMode)
                   -> hir::Path {
-        self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
+        self.lower_path_extra(id, p, None, param_mode)
     }
 
     fn lower_path_segment(&mut self,
@@ -1904,7 +1897,7 @@ fn lower_item_kind(&mut self,
                        i: &ItemKind)
                        -> hir::Item_ {
         match *i {
-            ItemKind::ExternCrate(string) => hir::ItemExternCrate(string),
+            ItemKind::ExternCrate(orig_name) => hir::ItemExternCrate(orig_name),
             ItemKind::Use(ref use_tree) => {
                 // Start with an empty prefix
                 let prefix = Path {
@@ -2047,8 +2040,8 @@ fn lower_use_tree(&mut self,
         let path = &tree.prefix;
 
         match tree.kind {
-            UseTreeKind::Simple(ident) => {
-                *name = ident.name;
+            UseTreeKind::Simple(rename) => {
+                *name = tree.ident().name;
 
                 // First apply the prefix to the path
                 let mut path = Path {
@@ -2064,12 +2057,12 @@ fn lower_use_tree(&mut self,
                 if path.segments.len() > 1 &&
                    path.segments.last().unwrap().identifier.name == keywords::SelfValue.name() {
                     let _ = path.segments.pop();
-                    if ident.name == keywords::SelfValue.name() {
+                    if rename.is_none() {
                         *name = path.segments.last().unwrap().identifier.name;
                     }
                 }
 
-                let path = P(self.lower_path(id, &path, ParamMode::Explicit, true));
+                let path = P(self.lower_path(id, &path, ParamMode::Explicit));
                 hir::ItemUse(path, hir::UseKind::Single)
             }
             UseTreeKind::Glob => {
@@ -2080,7 +2073,7 @@ fn lower_use_tree(&mut self,
                         .cloned()
                         .collect(),
                     span: path.span,
-                }, ParamMode::Explicit, true));
+                }, ParamMode::Explicit));
                 hir::ItemUse(path, hir::UseKind::Glob)
             }
             UseTreeKind::Nested(ref trees) => {
@@ -2136,7 +2129,7 @@ fn lower_use_tree(&mut self,
                 // Privatize the degenerate import base, used only to check
                 // the stability of `use a::{};`, to avoid it showing up as
                 // a re-export by accident when `pub`, e.g. in documentation.
-                let path = P(self.lower_path(id, &prefix, ParamMode::Explicit, true));
+                let path = P(self.lower_path(id, &prefix, ParamMode::Explicit));
                 *vis = hir::Inherited;
                 hir::ItemUse(path, hir::UseKind::ListStem)
             }
@@ -3379,7 +3372,7 @@ fn lower_visibility(&mut self,
             VisibilityKind::Crate(..) => hir::Visibility::Crate,
             VisibilityKind::Restricted { ref path, id, .. } => {
                 hir::Visibility::Restricted {
-                    path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
+                    path: P(self.lower_path(id, path, ParamMode::Explicit)),
                     id: if let Some(owner) = explicit_owner {
                         self.lower_node_id_with_owner(id, owner).node_id
                     } else {
index 83e855178dbe720149f83b5cb6b8b14a47ec7577..5ae84f5685eafca61a09c0716dd2de7ff76d7a56 100644 (file)
@@ -2011,9 +2011,9 @@ pub struct Item {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Item_ {
-    /// An `extern crate` item, with optional original crate name,
+    /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
     ///
-    /// e.g. `extern crate foo` or `extern crate foo_bar as foo`
+    /// E.g. `extern crate foo` or `extern crate foo_bar as foo`
     ItemExternCrate(Option<Name>),
 
     /// `use foo::bar::*;` or `use foo::bar::baz as quux;`
index 9e755f366a7de39bb8b1cc0d794f1266477e81a3..3d38c0c8ed9e57f396076d84786fdc54bdc13e43 100644 (file)
@@ -524,15 +524,10 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
         self.print_outer_attributes(&item.attrs)?;
         self.ann.pre(self, NodeItem(item))?;
         match item.node {
-            hir::ItemExternCrate(ref optional_path) => {
+            hir::ItemExternCrate(orig_name) => {
                 self.head(&visibility_qualified(&item.vis, "extern crate"))?;
-                if let Some(p) = *optional_path {
-                    let val = p.as_str();
-                    if val.contains("-") {
-                        self.print_string(&val, ast::StrStyle::Cooked)?;
-                    } else {
-                        self.print_name(p)?;
-                    }
+                if let Some(orig_name) = orig_name {
+                    self.print_name(orig_name)?;
                     self.s.space()?;
                     self.s.word("as")?;
                     self.s.space()?;
index c085b803085a853bb1eacbf6d630c577b0a28f86..e764cedd658b5df4070f031fcd0f5bc33c26c663 100644 (file)
@@ -851,7 +851,7 @@ fn hash_stable<W: StableHasherResult>(&self,
 }
 
 impl_stable_hash_for!(enum hir::Item_ {
-    ItemExternCrate(name),
+    ItemExternCrate(orig_name),
     ItemUse(path, use_kind),
     ItemStatic(ty, mutability, body_id),
     ItemConst(ty, body_id),
index 2cf09a002c9f58b55bcd4e0aa2a7d7f9d49f0d5d..0d91074e946bda028c813aebb2804082c91569fe 100644 (file)
@@ -385,7 +385,7 @@ pub struct Options {
         externs: Externs [UNTRACKED],
         crate_name: Option<String> [TRACKED],
         // An optional name to use as the crate for std during std injection,
-        // written `extern crate std = "name"`. Default to "std". Used by
+        // written `extern crate name as std`. Defaults to `std`. Used by
         // out-of-tree drivers.
         alt_std_name: Option<String> [TRACKED],
         // Indicates how the compiler should treat unstable features
index c088458c3557c7076e26c42cbe208e8a2c01d3f7..02e704b6841856779af8b5c5696d04caa96eaf0a 100644 (file)
@@ -99,7 +99,7 @@ fn fold_item(&mut self, item: P<Item>) -> SmallVector<P<Item>> {
             f.cx.item_extern_crate(f.span, f.alloc),
             f.cx.item_use_simple(
                 f.span,
-                respan(f.span.empty(), VisibilityKind::Inherited),
+                respan(f.span.shrink_to_lo(), VisibilityKind::Inherited),
                 super_path,
             ),
         ];
index b5e31bdf6686afb0dfb6c6bc84e443ef4099ba62..710fef8db40de1e244741e9b1aa9d20abbf27514 100644 (file)
@@ -683,7 +683,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session,
     });
 
     krate = time(sess, "crate injection", || {
-        let alt_std_name = sess.opts.alt_std_name.clone();
+        let alt_std_name = sess.opts.alt_std_name.as_ref().map(|s| &**s);
         syntax::std_inject::maybe_inject_crates_ref(krate, alt_std_name)
     });
 
index 031033f7208e1dff4767e43afdec28e79e56ffbb..bffa8628ff3530f527ff72589df83e826bcc9e76 100644 (file)
@@ -1082,7 +1082,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                     if !cx.access_levels.is_reachable(it.id) {
                         let msg = "function is marked #[no_mangle], but not exported";
                         let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_FNS, it.span, msg);
-                        let insertion_span = it.span.with_hi(it.span.lo());
+                        let insertion_span = it.span.shrink_to_lo();
                         if it.vis == hir::Visibility::Inherited {
                             err.span_suggestion(insertion_span,
                                                 "try making it public",
@@ -1107,7 +1107,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
                    !cx.access_levels.is_reachable(it.id) {
                        let msg = "static is marked #[no_mangle], but not exported";
                        let mut err = cx.struct_span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg);
-                       let insertion_span = it.span.with_hi(it.span.lo());
+                       let insertion_span = it.span.shrink_to_lo();
                        if it.vis == hir::Visibility::Inherited {
                            err.span_suggestion(insertion_span,
                                                "try making it public",
index d777f6f19b0ffd8ca7af3aa916ec0f13780533a5..86f79c553c3917fc9249e7cd49a8c69a7445f55a 100644 (file)
@@ -377,11 +377,12 @@ fn check_use_tree(&self, cx: &EarlyContext, use_tree: &ast::UseTree, item: &ast:
             // Trigger the lint if the nested item is a non-self single item
             let node_ident;
             match items[0].0.kind {
-                ast::UseTreeKind::Simple(ident) => {
-                    if ident.name == keywords::SelfValue.name() {
+                ast::UseTreeKind::Simple(rename) => {
+                    let orig_ident = items[0].0.prefix.segments.last().unwrap().identifier;
+                    if orig_ident.name == keywords::SelfValue.name() {
                         return;
                     } else {
-                        node_ident = ident;
+                        node_ident = rename.unwrap_or(orig_ident);
                     }
                 }
                 ast::UseTreeKind::Glob => {
index b2f014b930d602b540b137b63df2a4da218413d6..a0546b369a8ebba094105cdc45f61cbe485ee9b7 100644 (file)
@@ -1055,12 +1055,14 @@ fn postprocess(&mut self, krate: &ast::Crate) {
 
     fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
         match item.node {
-            ast::ItemKind::ExternCrate(rename) => {
-                debug!("resolving extern crate stmt. ident: {} rename: {:?}", item.ident, rename);
-                let rename = match rename {
-                    Some(rename) => {
-                        validate_crate_name(Some(self.sess), &rename.as_str(), Some(item.span));
-                        rename
+            ast::ItemKind::ExternCrate(orig_name) => {
+                debug!("resolving extern crate stmt. ident: {} orig_name: {:?}",
+                       item.ident, orig_name);
+                let orig_name = match orig_name {
+                    Some(orig_name) => {
+                        validate_crate_name(Some(self.sess), &orig_name.as_str(),
+                                            Some(item.span));
+                        orig_name
                     }
                     None => item.ident.name,
                 };
@@ -1071,7 +1073,7 @@ fn process_item(&mut self, item: &ast::Item, definitions: &Definitions) {
                 };
 
                 let (cnum, ..) = self.resolve_crate(
-                    &None, item.ident.name, rename, None, item.span, PathKind::Crate, dep_kind,
+                    &None, item.ident.name, orig_name, None, item.span, PathKind::Crate, dep_kind,
                 );
 
                 let def_id = definitions.opt_local_def_id(item.id).unwrap();
index 34c93097a51f52789051506057839616b037089d..2de27f3a1c3eac510b32a74ba637cfaf92528185 100644 (file)
@@ -533,7 +533,7 @@ fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {
                 tokens: body.into(),
                 legacy: def.legacy,
             }),
-            vis: codemap::respan(local_span.empty(), ast::VisibilityKind::Inherited),
+            vis: codemap::respan(local_span.shrink_to_lo(), ast::VisibilityKind::Inherited),
             tokens: None,
         })
     }
index 23c5499bb639648c15a0ac570b531f029087988e..8494c043f90fcd28ef2e6ea3b3b20a0d0a1dceca 100644 (file)
@@ -422,7 +422,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
             builder.args_and_body(block, &arguments, arg_scope, &body.value)
         }));
         // Attribute epilogue to function's closing brace
-        let fn_end = span.with_lo(span.hi());
+        let fn_end = span.shrink_to_hi();
         let source_info = builder.source_info(fn_end);
         let return_block = builder.return_block();
         builder.cfg.terminate(block, source_info,
index bf7b81c4d0e420938ad8ca08a906ec9c02330366..c192f349c2019723f6eb2bba0679db27a4c43220 100644 (file)
@@ -119,7 +119,8 @@ fn build_reduced_graph_for_use_tree(&mut self,
             .collect();
 
         match use_tree.kind {
-            ast::UseTreeKind::Simple(mut ident) => {
+            ast::UseTreeKind::Simple(rename) => {
+                let mut ident = use_tree.ident();
                 let mut source = module_path.pop().unwrap().node;
                 let mut type_ns_only = false;
 
@@ -142,7 +143,7 @@ fn build_reduced_graph_for_use_tree(&mut self,
                         // Replace `use foo::self;` with `use foo;`
                         let _ = module_path.pop();
                         source = last_segment.node;
-                        if ident.name == keywords::SelfValue.name() {
+                        if rename.is_none() {
                             ident = last_segment.node;
                         }
                     }
@@ -162,7 +163,7 @@ fn build_reduced_graph_for_use_tree(&mut self,
                             ModuleKind::Block(..) => unreachable!(),
                         };
                         source.name = crate_name;
-                        if ident.name == keywords::DollarCrate.name() {
+                        if rename.is_none() {
                             ident.name = crate_name;
                         }
 
@@ -206,8 +207,8 @@ fn build_reduced_graph_for_use_tree(&mut self,
 
                 // Ensure there is at most one `self` in the list
                 let self_spans = items.iter().filter_map(|&(ref use_tree, _)| {
-                    if let ast::UseTreeKind::Simple(ident) = use_tree.kind {
-                        if ident.name == keywords::SelfValue.name() {
+                    if let ast::UseTreeKind::Simple(..) = use_tree.kind {
+                        if use_tree.ident().name == keywords::SelfValue.name() {
                             return Some(use_tree.span);
                         }
                     }
@@ -244,9 +245,9 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
 
         match item.node {
             ItemKind::Use(ref use_tree) => {
-                // Just an empty prefix to start out
+                // Imports are resolved as global by default, add starting root segment.
                 let prefix = ast::Path {
-                    segments: vec![],
+                    segments: use_tree.prefix.make_root().into_iter().collect(),
                     span: use_tree.span,
                 };
 
@@ -255,7 +256,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                 );
             }
 
-            ItemKind::ExternCrate(as_name) => {
+            ItemKind::ExternCrate(orig_name) => {
                 self.crate_loader.process_item(item, &self.definitions);
 
                 // n.b. we don't need to look at the path option here, because cstore already did
@@ -274,7 +275,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, expansion: Mark) {
                     id: item.id,
                     parent,
                     imported_module: Cell::new(Some(module)),
-                    subclass: ImportDirectiveSubclass::ExternCrate(as_name),
+                    subclass: ImportDirectiveSubclass::ExternCrate(orig_name),
                     span: item.span,
                     module_path: Vec::new(),
                     vis: Cell::new(vis),
index c84caee13e82a0c4233f535661ed12dd35367912..dc22c23271d63855639e095e76df63fc701f8a18 100644 (file)
@@ -756,7 +756,7 @@ fn visit_mod(
                     // don't suggest placing a use before the prelude
                     // import or other generated ones
                     if item.span.ctxt().outer().expn_info().is_none() {
-                        self.span = Some(item.span.with_hi(item.span.lo()));
+                        self.span = Some(item.span.shrink_to_lo());
                         self.found_use = true;
                         return;
                     }
@@ -768,12 +768,12 @@ fn visit_mod(
                     if item.span.ctxt().outer().expn_info().is_none() {
                         // don't insert between attributes and an item
                         if item.attrs.is_empty() {
-                            self.span = Some(item.span.with_hi(item.span.lo()));
+                            self.span = Some(item.span.shrink_to_lo());
                         } else {
                             // find the first attribute on the item
                             for attr in &item.attrs {
                                 if self.span.map_or(true, |span| attr.span < span) {
-                                    self.span = Some(attr.span.with_hi(attr.span.lo()));
+                                    self.span = Some(attr.span.shrink_to_lo());
                                 }
                             }
                         }
@@ -2164,8 +2164,9 @@ fn resolve_item(&mut self, item: &Item) {
             }
 
             ItemKind::Use(ref use_tree) => {
+                // Imports are resolved as global by default, add starting root segment.
                 let path = Path {
-                    segments: vec![],
+                    segments: use_tree.prefix.make_root().into_iter().collect(),
                     span: use_tree.span,
                 };
                 self.resolve_use_tree(item.id, use_tree, &path);
@@ -2300,7 +2301,6 @@ fn with_optional_trait_ref<T, F>(&mut self, opt_trait_ref: Option<&TraitRef>, f:
                 None,
                 &path,
                 trait_ref.path.span,
-                trait_ref.path.segments.last().unwrap().span,
                 PathSource::Trait(AliasPossibility::No)
             ).base_def();
             if def != Def::Err {
@@ -2731,8 +2731,7 @@ fn smart_resolve_path(&mut self,
         let segments = &path.segments.iter()
             .map(|seg| respan(seg.span, seg.identifier))
             .collect::<Vec<_>>();
-        let ident_span = path.segments.last().map_or(path.span, |seg| seg.span);
-        self.smart_resolve_path_fragment(id, qself, segments, path.span, ident_span, source)
+        self.smart_resolve_path_fragment(id, qself, segments, path.span, source)
     }
 
     fn smart_resolve_path_fragment(&mut self,
@@ -2740,9 +2739,9 @@ fn smart_resolve_path_fragment(&mut self,
                                    qself: Option<&QSelf>,
                                    path: &[SpannedIdent],
                                    span: Span,
-                                   ident_span: Span,
                                    source: PathSource)
                                    -> PathResolution {
+        let ident_span = path.last().map_or(span, |ident| ident.span);
         let ns = source.namespace();
         let is_expected = &|def| source.is_expected(def);
         let is_enum_variant = &|def| if let Def::Variant(..) = def { true } else { false };
@@ -3090,7 +3089,7 @@ fn resolve_qpath(&mut self,
             // Make sure `A::B` in `<T as A>::B::C` is a trait item.
             let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
             let res = self.smart_resolve_path_fragment(id, None, &path[..qself.position + 1],
-                                                       span, span, PathSource::TraitItem(ns));
+                                                       span, PathSource::TraitItem(ns));
             return Some(PathResolution::with_unresolved_segments(
                 res.base_def(), res.unresolved_segments() + path.len() - qself.position - 1
             ));
@@ -3941,8 +3940,12 @@ fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
                 ty::Visibility::Restricted(self.current_module.normal_ancestor_id)
             }
             ast::VisibilityKind::Restricted { ref path, id, .. } => {
-                let def = self.smart_resolve_path(id, None, path,
-                                                  PathSource::Visibility).base_def();
+                // Visibilities are resolved as global by default, add starting root segment.
+                let segments = path.make_root().iter().chain(path.segments.iter())
+                    .map(|seg| respan(seg.span, seg.identifier))
+                    .collect::<Vec<_>>();
+                let def = self.smart_resolve_path_fragment(id, None, &segments, path.span,
+                                                           PathSource::Visibility).base_def();
                 if def == Def::Err {
                     ty::Visibility::Public
                 } else {
index 01c1ded94578ecc1fa45da7521930f70595598e7..4cbebdc3c1c39f9458fb732e4e0da80bf471d2f7 100644 (file)
@@ -667,11 +667,10 @@ fn finalize_import(&mut self, directive: &'b ImportDirective<'b>) -> Option<(Spa
             }
             PathResult::Failed(span, msg, true) => {
                 let (mut self_path, mut self_result) = (module_path.clone(), None);
-                if !self_path.is_empty() &&
-                    !token::Ident(self_path[0].node).is_path_segment_keyword() &&
-                    !(self_path.len() > 1 &&
-                      token::Ident(self_path[1].node).is_path_segment_keyword())
-                {
+                let is_special = |ident| token::Ident(ident).is_path_segment_keyword() &&
+                                         ident.name != keywords::CrateRoot.name();
+                if !self_path.is_empty() && !is_special(self_path[0].node) &&
+                   !(self_path.len() > 1 && is_special(self_path[1].node)) {
                     self_path[0].node.name = keywords::SelfValue.name();
                     self_result = Some(self.resolve_path(&self_path, None, false, span));
                 }
index d92025a6787d6f63597ab87accae8599e012f37b..3d4d8571c6e4242283bea932777f3e3c30ae9b4a 100644 (file)
@@ -1209,7 +1209,7 @@ fn process_macro_use(&mut self, span: Span) {
 
     fn process_trait_item(&mut self, trait_item: &'l ast::TraitItem, trait_id: DefId) {
         self.process_macro_use(trait_item.span);
-        let vis_span = trait_item.span.empty();
+        let vis_span = trait_item.span.shrink_to_lo();
         match trait_item.node {
             ast::TraitItemKind::Const(ref ty, ref expr) => {
                 self.process_assoc_const(
@@ -1342,7 +1342,8 @@ fn process_use_tree(&mut self,
             .map(::id_from_def_id);
 
         match use_tree.kind {
-            ast::UseTreeKind::Simple(ident) => {
+            ast::UseTreeKind::Simple(..) => {
+                let ident = use_tree.ident();
                 let path = ast::Path {
                     segments: prefix.segments
                         .iter()
index 5c20490f8230316b392c527d50de33a9f69c5c20..61afac97d6409b337a19522d934bc35519645f9e 100644 (file)
@@ -767,7 +767,7 @@ fn visit_mod(
                     // don't suggest placing a use before the prelude
                     // import or other generated ones
                     if item.span.ctxt().outer().expn_info().is_none() {
-                        self.span = Some(item.span.with_hi(item.span.lo()));
+                        self.span = Some(item.span.shrink_to_lo());
                         self.found_use = true;
                         return;
                     }
@@ -779,12 +779,12 @@ fn visit_mod(
                     if item.span.ctxt().outer().expn_info().is_none() {
                         // don't insert between attributes and an item
                         if item.attrs.is_empty() {
-                            self.span = Some(item.span.with_hi(item.span.lo()));
+                            self.span = Some(item.span.shrink_to_lo());
                         } else {
                             // find the first attribute on the item
                             for attr in &item.attrs {
                                 if self.span.map_or(true, |span| attr.span < span) {
-                                    self.span = Some(attr.span.with_hi(attr.span.lo()));
+                                    self.span = Some(attr.span.shrink_to_lo());
                                 }
                             }
                         }
index dc9455487ede708e45edc734b8b4d9c1e5eae476..4a685cfddb7a42f5e760d8a4427d26b622064335 100644 (file)
@@ -2520,7 +2520,7 @@ fn parameter_count_error<'tcx>(sess: &Session,
             if sugg_unit {
                 let sugg_span = sess.codemap().end_point(expr_sp);
                 // remove closing `)` from the span
-                let sugg_span = sugg_span.with_hi(sugg_span.lo());
+                let sugg_span = sugg_span.shrink_to_lo();
                 err.span_suggestion(
                     sugg_span,
                     "expected the unit value `()`; create it with empty parentheses",
index f692e05d6a2591c07c9c618cc1456685f4dbb884..f45a5b030db2bf354b0095e5ccc58c7004826bcd 100644 (file)
@@ -406,13 +406,13 @@ pub fn visit_item(&mut self, item: &hir::Item,
             // If we're inlining, skip private items.
             _ if self.inlining && item.vis != hir::Public => {}
             hir::ItemGlobalAsm(..) => {}
-            hir::ItemExternCrate(ref p) => {
+            hir::ItemExternCrate(orig_name) => {
                 let def_id = self.cx.tcx.hir.local_def_id(item.id);
                 om.extern_crates.push(ExternCrate {
                     cnum: self.cx.tcx.extern_mod_stmt_cnum(def_id)
                                 .unwrap_or(LOCAL_CRATE),
                     name,
-                    path: p.map(|x|x.to_string()),
+                    path: orig_name.map(|x|x.to_string()),
                     vis: item.vis.clone(),
                     attrs: item.attrs.clone(),
                     whence: item.span,
index 8b3a7164cccb6779d679b7f2c8daff76e5ce37cb..1f16b728cd23951cec66be533adae4fe0b6217e4 100644 (file)
@@ -108,17 +108,16 @@ pub fn from_ident(s: Span, identifier: Ident) -> Path {
         }
     }
 
-    // Add starting "crate root" segment to all paths except those that
-    // already have it or start with `self`, `super`, `Self` or `$crate`.
-    pub fn default_to_global(mut self) -> Path {
-        if !self.is_global() {
-            let ident = self.segments[0].identifier;
-            if !::parse::token::Ident(ident).is_path_segment_keyword() ||
-               ident.name == keywords::Crate.name() {
-                self.segments.insert(0, PathSegment::crate_root(self.span));
+    // Make a "crate root" segment for this path unless it already has it
+    // or starts with something like `self`/`super`/`$crate`/etc.
+    pub fn make_root(&self) -> Option<PathSegment> {
+        if let Some(ident) = self.segments.get(0).map(|seg| seg.identifier) {
+            if ::parse::token::Ident(ident).is_path_segment_keyword() &&
+               ident.name != keywords::Crate.name() {
+                return None;
             }
         }
-        self
+        Some(PathSegment::crate_root(self.span.shrink_to_lo()))
     }
 
     pub fn is_global(&self) -> bool {
@@ -1878,20 +1877,37 @@ pub struct Variant_ {
 
 pub type Variant = Spanned<Variant_>;
 
+/// Part of `use` item to the right of its prefix.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum UseTreeKind {
-    Simple(Ident),
-    Glob,
+    /// `use prefix` or `use prefix as rename`
+    Simple(Option<Ident>),
+    /// `use prefix::{...}`
     Nested(Vec<(UseTree, NodeId)>),
+    /// `use prefix::*`
+    Glob,
 }
 
+/// A tree of paths sharing common prefixes.
+/// Used in `use` items both at top-level and inside of braces in import groups.
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub struct UseTree {
-    pub kind: UseTreeKind,
     pub prefix: Path,
+    pub kind: UseTreeKind,
     pub span: Span,
 }
 
+impl UseTree {
+    pub fn ident(&self) -> Ident {
+        match self.kind {
+            UseTreeKind::Simple(Some(rename)) => rename,
+            UseTreeKind::Simple(None) =>
+                self.prefix.segments.last().expect("empty prefix in a simple import").identifier,
+            _ => panic!("`UseTree::ident` can only be used on a simple import"),
+        }
+    }
+}
+
 /// Distinguishes between Attributes that decorate items and Attributes that
 /// are contained as statements within items. These two cases need to be
 /// distinguished for pretty-printing.
@@ -2055,7 +2071,7 @@ pub struct Item {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum ItemKind {
-    /// An `extern crate` item, with optional original crate name.
+    /// An `extern crate` item, with optional *original* crate name if the crate was renamed.
     ///
     /// E.g. `extern crate foo` or `extern crate foo_bar as foo`
     ExternCrate(Option<Name>),
index 6c0fe525f55b08c4b9eacc18802b2727cee2811c..2c91844da96d70ecec36f6b9aa113ec102ad37a5 100644 (file)
@@ -220,7 +220,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
                 ty,
                 expr,
             ),
-            vis: codemap::respan(span.empty(), ast::VisibilityKind::Public),
+            vis: codemap::respan(span.shrink_to_lo(), ast::VisibilityKind::Public),
             span,
             tokens: None,
         })
index b88e064e7e56dd059c8d54290a9cd005c3a9d6f7..9b53553bf69d723b6d921078f60f4124180e06b3 100644 (file)
@@ -294,7 +294,7 @@ fn item_use(&self, sp: Span,
                 vis: ast::Visibility, vp: P<ast::UseTree>) -> P<ast::Item>;
     fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item>;
     fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
-                        ident: ast::Ident, path: ast::Path) -> P<ast::Item>;
+                        ident: Option<ast::Ident>, path: ast::Path) -> P<ast::Item>;
     fn item_use_list(&self, sp: Span, vis: ast::Visibility,
                      path: Vec<ast::Ident>, imports: &[ast::Ident]) -> P<ast::Item>;
     fn item_use_glob(&self, sp: Span,
@@ -329,9 +329,13 @@ fn path_all(&self,
             None
         };
         segments.push(ast::PathSegment { identifier: last_identifier, span, parameters });
-        let path = ast::Path { span, segments };
-
-        if global { path.default_to_global() } else { path }
+        let mut path = ast::Path { span, segments };
+        if global {
+            if let Some(seg) = path.make_root() {
+                path.segments.insert(0, seg);
+            }
+        }
+        path
     }
 
     /// Constructs a qualified path.
@@ -983,7 +987,7 @@ fn item(&self, span: Span, name: Ident,
             attrs,
             id: ast::DUMMY_NODE_ID,
             node,
-            vis: respan(span.empty(), ast::VisibilityKind::Inherited),
+            vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
             span,
             tokens: None,
         })
@@ -1029,7 +1033,7 @@ fn variant(&self, span: Span, name: Ident, tys: Vec<P<ast::Ty>> ) -> ast::Varian
                 span: ty.span,
                 ty,
                 ident: None,
-                vis: respan(span.empty(), ast::VisibilityKind::Inherited),
+                vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 attrs: Vec::new(),
                 id: ast::DUMMY_NODE_ID,
             }
@@ -1159,16 +1163,15 @@ fn item_use(&self, sp: Span,
     }
 
     fn item_use_simple(&self, sp: Span, vis: ast::Visibility, path: ast::Path) -> P<ast::Item> {
-        let last = path.segments.last().unwrap().identifier;
-        self.item_use_simple_(sp, vis, last, path)
+        self.item_use_simple_(sp, vis, None, path)
     }
 
     fn item_use_simple_(&self, sp: Span, vis: ast::Visibility,
-                        ident: ast::Ident, path: ast::Path) -> P<ast::Item> {
+                        rename: Option<ast::Ident>, path: ast::Path) -> P<ast::Item> {
         self.item_use(sp, vis, P(ast::UseTree {
             span: sp,
             prefix: path,
-            kind: ast::UseTreeKind::Simple(ident),
+            kind: ast::UseTreeKind::Simple(rename),
         }))
     }
 
@@ -1178,7 +1181,7 @@ fn item_use_list(&self, sp: Span, vis: ast::Visibility,
             (ast::UseTree {
                 span: sp,
                 prefix: self.path(sp, vec![*id]),
-                kind: ast::UseTreeKind::Simple(*id),
+                kind: ast::UseTreeKind::Simple(None),
             }, ast::DUMMY_NODE_ID)
         }).collect();
 
index 7ccace014d032d9b4ab6343552f165a414886919..34dd7696168a6d431ba160010d3ff3b17d00f2d1 100644 (file)
@@ -239,7 +239,7 @@ pub fn expand_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
             node: ast::ItemKind::Mod(krate.module),
             ident: keywords::Invalid.ident(),
             id: ast::DUMMY_NODE_ID,
-            vis: respan(krate.span.empty(), ast::VisibilityKind::Public),
+            vis: respan(krate.span.shrink_to_lo(), ast::VisibilityKind::Public),
             tokens: None,
         })));
 
index d6642b7b6c260f09f20c66c7fca401e7d47a5c92..6844532e7b375ece36530f74a3d9c56dfb85e9ef 100644 (file)
@@ -857,7 +857,7 @@ fn expand_wrapper(cx: &ExtCtxt,
         let path = path.iter().map(|s| s.to_string()).collect();
         let use_item = cx.item_use_glob(
             sp,
-            respan(sp.empty(), ast::VisibilityKind::Inherited),
+            respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
             ids_ext(path),
         );
         cx.stmt_item(sp, use_item)
index 0098f2ae89b55c7796ecaf170358ff84514fe3dd..a5af8564057f61cfbb1b71a077e649f593c6f3d4 100644 (file)
@@ -1438,7 +1438,7 @@ fn visit_name(&mut self, sp: Span, name: ast::Name) {
     }
 
     fn visit_use_tree(&mut self, use_tree: &'a ast::UseTree, id: NodeId, _nested: bool) {
-        if let ast::UseTreeKind::Simple(ident) = use_tree.kind {
+        if let ast::UseTreeKind::Simple(Some(ident)) = use_tree.kind {
             if ident.name == "_" {
                 gate_feature_post!(&self, underscore_imports, use_tree.span,
                                    "renaming imports with `_` is unstable");
index 2cf99e15d1f9b987d4975495a8b87704a93cbc7c..46e6027b094bc2d7a8e94713e1df71ef3081d59b 100644 (file)
@@ -323,7 +323,8 @@ pub fn noop_fold_use_tree<T: Folder>(use_tree: UseTree, fld: &mut T) -> UseTree
         span: fld.new_span(use_tree.span),
         prefix: fld.fold_path(use_tree.prefix),
         kind: match use_tree.kind {
-            UseTreeKind::Simple(ident) => UseTreeKind::Simple(fld.fold_ident(ident)),
+            UseTreeKind::Simple(rename) =>
+                UseTreeKind::Simple(rename.map(|ident| fld.fold_ident(ident))),
             UseTreeKind::Glob => UseTreeKind::Glob,
             UseTreeKind::Nested(items) => UseTreeKind::Nested(items.move_map(|(tree, id)| {
                 (fld.fold_use_tree(tree), fld.new_id(id))
@@ -886,7 +887,7 @@ pub fn noop_fold_block<T: Folder>(b: P<Block>, folder: &mut T) -> P<Block> {
 
 pub fn noop_fold_item_kind<T: Folder>(i: ItemKind, folder: &mut T) -> ItemKind {
     match i {
-        ItemKind::ExternCrate(string) => ItemKind::ExternCrate(string),
+        ItemKind::ExternCrate(orig_name) => ItemKind::ExternCrate(orig_name),
         ItemKind::Use(use_tree) => {
             ItemKind::Use(use_tree.map(|tree| folder.fold_use_tree(tree)))
         }
@@ -1018,7 +1019,7 @@ pub fn noop_fold_crate<T: Folder>(Crate {module, attrs, span}: Crate,
         ident: keywords::Invalid.ident(),
         attrs,
         id: ast::DUMMY_NODE_ID,
-        vis: respan(span.empty(), ast::VisibilityKind::Public),
+        vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Public),
         span,
         node: ast::ItemKind::Mod(module),
         tokens: None,
index 9d1bfba7b94462d7ccfc964a7e5aa4946e648ecb..0e20eb49d395ed213211ff0a02ce52be7ee3e748 100644 (file)
@@ -214,7 +214,7 @@ pub fn retokenize(sess: &'a ParseSess, mut span: Span) -> Self {
 
         // Make the range zero-length if the span is invalid.
         if span.lo() > span.hi() || begin.fm.start_pos != end.fm.start_pos {
-            span = span.with_hi(span.lo());
+            span = span.shrink_to_lo();
         }
 
         let mut sr = StringReader::new_raw_internal(sess, begin.fm);
index ff097c362fe6101761a1034f2dd9db4df8837777..f7e5d40b52468821e79a28e324a01cdd866fdb1f 100644 (file)
@@ -713,7 +713,7 @@ fn str2seg(s: &str, lo: u32, hi: u32) -> ast::PathSegment {
                         id: ast::DUMMY_NODE_ID,
                         node: ast::ExprKind::Path(None, ast::Path {
                             span: sp(0, 6),
-                            segments: vec![ast::PathSegment::crate_root(sp(0, 2)),
+                            segments: vec![ast::PathSegment::crate_root(sp(0, 0)),
                                         str2seg("a", 2, 3),
                                         str2seg("b", 5, 6)]
                         }),
index aa2a6f1cb47f112205ef723a94960141daf8161f..cb5010a638df4f67b899c06b824009c326d60415 100644 (file)
@@ -1508,7 +1508,7 @@ fn parse_ret_ty(&mut self, allow_plus: bool) -> PResult<'a, FunctionRetTy> {
         if self.eat(&token::RArrow) {
             Ok(FunctionRetTy::Ty(self.parse_ty_common(allow_plus, true)?))
         } else {
-            Ok(FunctionRetTy::Default(self.span.with_hi(self.span.lo())))
+            Ok(FunctionRetTy::Default(self.span.shrink_to_lo()))
         }
     }
 
@@ -1986,7 +1986,7 @@ pub fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool)
         let lo = self.meta_var_span.unwrap_or(self.span);
         let mut segments = Vec::new();
         if self.eat(&token::ModSep) {
-            segments.push(PathSegment::crate_root(lo));
+            segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
         }
         self.parse_path_segments(&mut segments, style, enable_warning)?;
 
@@ -2021,7 +2021,7 @@ fn parse_path_segments(&mut self,
         loop {
             segments.push(self.parse_path_segment(style, enable_warning)?);
 
-            if self.is_import_coupler(false) || !self.eat(&token::ModSep) {
+            if self.is_import_coupler() || !self.eat(&token::ModSep) {
                 return Ok(());
             }
         }
@@ -5863,7 +5863,7 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
                 // `pub(in path)`
                 self.bump(); // `(`
                 self.bump(); // `in`
-                let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `path`
+                let path = self.parse_path(PathStyle::Mod)?; // `path`
                 self.expect(&token::CloseDelim(token::Paren))?; // `)`
                 let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
                     path: P(path),
@@ -5876,7 +5876,7 @@ pub fn parse_visibility(&mut self, can_take_tuple: bool) -> PResult<'a, Visibili
             {
                 // `pub(self)` or `pub(super)`
                 self.bump(); // `(`
-                let path = self.parse_path(PathStyle::Mod)?.default_to_global(); // `super`/`self`
+                let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
                 self.expect(&token::CloseDelim(token::Paren))?; // `)`
                 let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted {
                     path: P(path),
@@ -6285,23 +6285,17 @@ fn parse_item_extern_crate(&mut self,
                                lo: Span,
                                visibility: Visibility,
                                attrs: Vec<Attribute>)
-                                -> PResult<'a, P<Item>> {
-
-        let crate_name = self.parse_ident()?;
-        let (maybe_path, ident) = if let Some(ident) = self.parse_rename()? {
-            (Some(crate_name.name), ident)
+                               -> PResult<'a, P<Item>> {
+        let orig_name = self.parse_ident()?;
+        let (item_name, orig_name) = if let Some(rename) = self.parse_rename()? {
+            (rename, Some(orig_name.name))
         } else {
-            (None, crate_name)
+            (orig_name, None)
         };
         self.expect(&token::Semi)?;
 
-        let prev_span = self.prev_span;
-
-        Ok(self.mk_item(lo.to(prev_span),
-                        ident,
-                        ItemKind::ExternCrate(maybe_path),
-                        visibility,
-                        attrs))
+        let span = lo.to(self.prev_span);
+        Ok(self.mk_item(span, item_name, ItemKind::ExternCrate(orig_name), visibility, attrs))
     }
 
     /// Parse `extern` for foreign ABIs
@@ -6480,12 +6474,11 @@ fn parse_item_(&mut self, attrs: Vec<Attribute>,
 
         if self.eat_keyword(keywords::Use) {
             // USE ITEM
-            let item_ = ItemKind::Use(P(self.parse_use_tree(false)?));
+            let item_ = ItemKind::Use(P(self.parse_use_tree()?));
             self.expect(&token::Semi)?;
 
-            let prev_span = self.prev_span;
-            let invalid = keywords::Invalid.ident();
-            let item = self.mk_item(lo.to(prev_span), invalid, item_, visibility, attrs);
+            let span = lo.to(self.prev_span);
+            let item = self.mk_item(span, keywords::Invalid.ident(), item_, visibility, attrs);
             return Ok(Some(item));
         }
 
@@ -6960,90 +6953,53 @@ pub fn parse_item(&mut self) -> PResult<'a, Option<P<Item>>> {
         }))
     }
 
-    /// `{` or `::{` or `*` or `::*`
-    /// `::{` or `::*` (also `{`  or `*` if unprefixed is true)
-    fn is_import_coupler(&mut self, unprefixed: bool) -> bool {
-        self.is_import_coupler_inner(&token::OpenDelim(token::Brace), unprefixed) ||
-            self.is_import_coupler_inner(&token::BinOp(token::Star), unprefixed)
-    }
-
-    fn is_import_coupler_inner(&mut self, token: &token::Token, unprefixed: bool) -> bool {
-        if self.check(&token::ModSep) {
-            self.look_ahead(1, |t| t == token)
-        } else if unprefixed {
-            self.check(token)
-        } else {
-            false
-        }
+    /// `::{` or `::*`
+    fn is_import_coupler(&mut self) -> bool {
+        self.check(&token::ModSep) &&
+            self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
+                                   *t == token::BinOp(token::Star))
     }
 
     /// Parse UseTree
     ///
-    /// USE_TREE = `*` |
-    ///            `{` USE_TREE_LIST `}` |
+    /// USE_TREE = [`::`] `*` |
+    ///            [`::`] `{` USE_TREE_LIST `}` |
     ///            PATH `::` `*` |
     ///            PATH `::` `{` USE_TREE_LIST `}` |
     ///            PATH [`as` IDENT]
-    fn parse_use_tree(&mut self, nested: bool) -> PResult<'a, UseTree> {
+    fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
         let lo = self.span;
 
-        let mut prefix = ast::Path {
-            segments: vec![],
-            span: lo.to(self.span),
-        };
-
-        let kind = if self.is_import_coupler(true) {
-            // `use *;` or `use ::*;` or `use {...};` `use ::{...};`
-
-            // Remove the first `::`
+        let mut prefix = ast::Path { segments: Vec::new(), span: lo.shrink_to_lo() };
+        let kind = if self.check(&token::OpenDelim(token::Brace)) ||
+                      self.check(&token::BinOp(token::Star)) ||
+                      self.is_import_coupler() {
+            // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
             if self.eat(&token::ModSep) {
-                prefix.segments.push(PathSegment::crate_root(self.prev_span));
-            } else if !nested {
-                prefix.segments.push(PathSegment::crate_root(self.span));
+                prefix.segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
             }
 
             if self.eat(&token::BinOp(token::Star)) {
-                // `use *;`
                 UseTreeKind::Glob
-            } else if self.check(&token::OpenDelim(token::Brace)) {
-                // `use {...};`
-                UseTreeKind::Nested(self.parse_use_tree_list()?)
             } else {
-                return self.unexpected();
+                UseTreeKind::Nested(self.parse_use_tree_list()?)
             }
         } else {
-            // `use path::...;`
-            let mut parsed = self.parse_path(PathStyle::Mod)?;
-            if !nested {
-                parsed = parsed.default_to_global();
-            }
-
-            prefix.segments.append(&mut parsed.segments);
-            prefix.span = prefix.span.to(parsed.span);
+            // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
+            prefix = self.parse_path(PathStyle::Mod)?;
 
             if self.eat(&token::ModSep) {
                 if self.eat(&token::BinOp(token::Star)) {
-                    // `use path::*;`
                     UseTreeKind::Glob
-                } else if self.check(&token::OpenDelim(token::Brace)) {
-                    // `use path::{...};`
-                    UseTreeKind::Nested(self.parse_use_tree_list()?)
                 } else {
-                    return self.unexpected();
+                    UseTreeKind::Nested(self.parse_use_tree_list()?)
                 }
             } else {
-                // `use path::foo;` or `use path::foo as bar;`
-                let rename = self.parse_rename()?.
-                                  unwrap_or(prefix.segments.last().unwrap().identifier);
-                UseTreeKind::Simple(rename)
+                UseTreeKind::Simple(self.parse_rename()?)
             }
         };
 
-        Ok(UseTree {
-            span: lo.to(self.prev_span),
-            kind,
-            prefix,
-        })
+        Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) })
     }
 
     /// Parse UseTreeKind::Nested(list)
@@ -7053,7 +7009,7 @@ fn parse_use_tree_list(&mut self) -> PResult<'a, Vec<(UseTree, ast::NodeId)>> {
         self.parse_unspanned_seq(&token::OpenDelim(token::Brace),
                                  &token::CloseDelim(token::Brace),
                                  SeqSep::trailing_allowed(token::Comma), |this| {
-            Ok((this.parse_use_tree(true)?, ast::DUMMY_NODE_ID))
+            Ok((this.parse_use_tree()?, ast::DUMMY_NODE_ID))
         })
     }
 
index 5c051e9b3584d721e9c37936b5dce875d9a915fa..4ada9e20f2cc0db63af93a20cf04bdf6be3e9856 100644 (file)
@@ -361,6 +361,7 @@ pub fn is_path_segment_keyword(&self) -> bool {
                         id.name == keywords::SelfType.name() ||
                         id.name == keywords::Extern.name() ||
                         id.name == keywords::Crate.name() ||
+                        id.name == keywords::CrateRoot.name() ||
                         id.name == keywords::DollarCrate.name(),
             None => false,
         }
index 36698a8637451a2a77c5dc4d6c3efeed63ba3d9e..7adb2848f8d94fae5f43842e0b3693f293bb56db 100644 (file)
@@ -352,7 +352,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
 }
 
 pub fn path_to_string(p: &ast::Path) -> String {
-    to_string(|s| s.print_path(p, false, 0, false))
+    to_string(|s| s.print_path(p, false, 0))
 }
 
 pub fn path_segment_to_string(p: &ast::PathSegment) -> String {
@@ -1050,7 +1050,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> io::Result<()> {
                                  &f.generic_params)?;
             }
             ast::TyKind::Path(None, ref path) => {
-                self.print_path(path, false, 0, false)?;
+                self.print_path(path, false, 0)?;
             }
             ast::TyKind::Path(Some(ref qself), ref path) => {
                 self.print_qpath(path, qself, false)?
@@ -1173,15 +1173,10 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
         self.print_outer_attributes(&item.attrs)?;
         self.ann.pre(self, NodeItem(item))?;
         match item.node {
-            ast::ItemKind::ExternCrate(ref optional_path) => {
+            ast::ItemKind::ExternCrate(orig_name) => {
                 self.head(&visibility_qualified(&item.vis, "extern crate"))?;
-                if let Some(p) = *optional_path {
-                    let val = p.as_str();
-                    if val.contains('-') {
-                        self.print_string(&val, ast::StrStyle::Cooked)?;
-                    } else {
-                        self.print_name(p)?;
-                    }
+                if let Some(orig_name) = orig_name {
+                    self.print_name(orig_name)?;
                     self.s.space()?;
                     self.s.word("as")?;
                     self.s.space()?;
@@ -1382,7 +1377,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
                 self.s.word(";")?;
             }
             ast::ItemKind::Mac(codemap::Spanned { ref node, .. }) => {
-                self.print_path(&node.path, false, 0, false)?;
+                self.print_path(&node.path, false, 0)?;
                 self.s.word("! ")?;
                 self.print_ident(item.ident)?;
                 self.cbox(INDENT_UNIT)?;
@@ -1407,7 +1402,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
     }
 
     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> io::Result<()> {
-        self.print_path(&t.path, false, 0, false)
+        self.print_path(&t.path, false, 0)
     }
 
     fn print_formal_generic_params(
@@ -1464,7 +1459,7 @@ pub fn print_visibility(&mut self, vis: &ast::Visibility) -> io::Result<()> {
                 ast::CrateSugar::JustCrate => self.word_nbsp("crate")
             }
             ast::VisibilityKind::Restricted { ref path, .. } => {
-                let path = to_string(|s| s.print_path(path, false, 0, true));
+                let path = to_string(|s| s.print_path(path, false, 0));
                 if path == "self" || path == "super" {
                     self.word_nbsp(&format!("pub({})", path))
                 } else {
@@ -1572,7 +1567,7 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
                     ti.ident,
                     ty,
                     default.as_ref().map(|expr| &**expr),
-                    &codemap::respan(ti.span.empty(), ast::VisibilityKind::Inherited),
+                    &codemap::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 )?;
             }
             ast::TraitItemKind::Method(ref sig, ref body) => {
@@ -1583,7 +1578,7 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
                     ti.ident,
                     &ti.generics,
                     sig,
-                    &codemap::respan(ti.span.empty(), ast::VisibilityKind::Inherited),
+                    &codemap::respan(ti.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 )?;
                 if let Some(ref body) = *body {
                     self.nbsp()?;
@@ -1598,7 +1593,7 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
             }
             ast::TraitItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
-                self.print_path(&node.path, false, 0, false)?;
+                self.print_path(&node.path, false, 0)?;
                 self.s.word("! ")?;
                 self.cbox(INDENT_UNIT)?;
                 self.popen()?;
@@ -1632,7 +1627,7 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
             }
             ast::ImplItemKind::Macro(codemap::Spanned { ref node, .. }) => {
                 // code copied from ItemKind::Mac:
-                self.print_path(&node.path, false, 0, false)?;
+                self.print_path(&node.path, false, 0)?;
                 self.s.word("! ")?;
                 self.cbox(INDENT_UNIT)?;
                 self.popen()?;
@@ -1818,7 +1813,7 @@ pub fn print_if_let(&mut self, pats: &[P<ast::Pat>], expr: &ast::Expr, blk: &ast
 
     pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
                      -> io::Result<()> {
-        self.print_path(&m.node.path, false, 0, false)?;
+        self.print_path(&m.node.path, false, 0)?;
         self.s.word("!")?;
         match delim {
             token::Paren => self.popen()?,
@@ -1919,7 +1914,7 @@ fn print_expr_struct(&mut self,
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>,
                          attrs: &[Attribute]) -> io::Result<()> {
-        self.print_path(path, true, 0, false)?;
+        self.print_path(path, true, 0)?;
         self.s.word("{")?;
         self.print_inner_attributes_inline(attrs)?;
         self.commasep_cmnt(
@@ -2240,7 +2235,7 @@ fn print_expr_outer_attr_style(&mut self,
                 }
             }
             ast::ExprKind::Path(None, ref path) => {
-                self.print_path(path, true, 0, false)?
+                self.print_path(path, true, 0)?
             }
             ast::ExprKind::Path(Some(ref qself), ref path) => {
                 self.print_qpath(path, qself, true)?
@@ -2400,17 +2395,12 @@ pub fn print_for_decl(&mut self, loc: &ast::Local,
     fn print_path(&mut self,
                   path: &ast::Path,
                   colons_before_params: bool,
-                  depth: usize,
-                  defaults_to_global: bool)
+                  depth: usize)
                   -> io::Result<()>
     {
         self.maybe_print_comment(path.span.lo())?;
 
-        let mut segments = path.segments[..path.segments.len()-depth].iter();
-        if defaults_to_global && path.is_global() {
-            segments.next();
-        }
-        for (i, segment) in segments.enumerate() {
+        for (i, segment) in path.segments[..path.segments.len() - depth].iter().enumerate() {
             if i > 0 {
                 self.s.word("::")?
             }
@@ -2449,7 +2439,7 @@ fn print_qpath(&mut self,
             self.s.space()?;
             self.word_space("as")?;
             let depth = path.segments.len() - qself.position;
-            self.print_path(path, false, depth, false)?;
+            self.print_path(path, false, depth)?;
         }
         self.s.word(">")?;
         self.s.word("::")?;
@@ -2552,7 +2542,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 }
             }
             PatKind::TupleStruct(ref path, ref elts, ddpos) => {
-                self.print_path(path, true, 0, false)?;
+                self.print_path(path, true, 0)?;
                 self.popen()?;
                 if let Some(ddpos) = ddpos {
                     self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(p))?;
@@ -2570,13 +2560,13 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                 self.pclose()?;
             }
             PatKind::Path(None, ref path) => {
-                self.print_path(path, true, 0, false)?;
+                self.print_path(path, true, 0)?;
             }
             PatKind::Path(Some(ref qself), ref path) => {
                 self.print_qpath(path, qself, false)?;
             }
             PatKind::Struct(ref path, ref fields, etc) => {
-                self.print_path(path, true, 0, false)?;
+                self.print_path(path, true, 0)?;
                 self.nbsp()?;
                 self.word_space("{")?;
                 self.commasep_cmnt(
@@ -2953,18 +2943,17 @@ pub fn print_where_clause(&mut self, where_clause: &ast::WhereClause)
 
     pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
         match tree.kind {
-            ast::UseTreeKind::Simple(ref ident) => {
-                self.print_path(&tree.prefix, false, 0, true)?;
-
-                if tree.prefix.segments.last().unwrap().identifier.name != ident.name {
+            ast::UseTreeKind::Simple(rename) => {
+                self.print_path(&tree.prefix, false, 0)?;
+                if let Some(rename) = rename {
                     self.s.space()?;
                     self.word_space("as")?;
-                    self.print_ident(*ident)?;
+                    self.print_ident(rename)?;
                 }
             }
             ast::UseTreeKind::Glob => {
                 if !tree.prefix.segments.is_empty() {
-                    self.print_path(&tree.prefix, false, 0, true)?;
+                    self.print_path(&tree.prefix, false, 0)?;
                     self.s.word("::")?;
                 }
                 self.s.word("*")?;
@@ -2973,7 +2962,7 @@ pub fn print_use_tree(&mut self, tree: &ast::UseTree) -> io::Result<()> {
                 if tree.prefix.segments.is_empty() {
                     self.s.word("{")?;
                 } else {
-                    self.print_path(&tree.prefix, false, 0, true)?;
+                    self.print_path(&tree.prefix, false, 0)?;
                     self.s.word("::{")?;
                 }
                 self.commasep(Inconsistent, &items[..], |this, &(ref tree, _)| {
index da24107f4c33b53485f44008d93b9de19183d68a..fdbc795b2d365500e81ac29da08ba6733008de8f 100644 (file)
@@ -43,7 +43,7 @@ pub fn injected_crate_name() -> Option<&'static str> {
     static INJECTED_CRATE_NAME: Cell<Option<&'static str>> = Cell::new(None);
 }
 
-pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<String>) -> ast::Crate {
+pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<&str>) -> ast::Crate {
     let name = if attr::contains_name(&krate.attrs, "no_core") {
         return krate;
     } else if attr::contains_name(&krate.attrs, "no_std") {
@@ -54,14 +54,12 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<Strin
 
     INJECTED_CRATE_NAME.with(|opt_name| opt_name.set(Some(name)));
 
-    let crate_name = Symbol::intern(&alt_std_name.unwrap_or_else(|| name.to_string()));
-
     krate.module.items.insert(0, P(ast::Item {
         attrs: vec![attr::mk_attr_outer(DUMMY_SP,
                                         attr::mk_attr_id(),
                                         attr::mk_word_item(Symbol::intern("macro_use")))],
         vis: dummy_spanned(ast::VisibilityKind::Inherited),
-        node: ast::ItemKind::ExternCrate(Some(crate_name)),
+        node: ast::ItemKind::ExternCrate(alt_std_name.map(Symbol::intern)),
         ident: ast::Ident::from_str(name),
         id: ast::DUMMY_NODE_ID,
         span: DUMMY_SP,
@@ -78,10 +76,10 @@ pub fn maybe_inject_crates_ref(mut krate: ast::Crate, alt_std_name: Option<Strin
             is_sugared_doc: false,
             span,
         }],
-        vis: respan(span.empty(), ast::VisibilityKind::Inherited),
+        vis: respan(span.shrink_to_lo(), ast::VisibilityKind::Inherited),
         node: ast::ItemKind::Use(P(ast::UseTree {
             prefix: ast::Path {
-                segments: ["{{root}}", name, "prelude", "v1"].into_iter().map(|name| {
+                segments: [name, "prelude", "v1"].into_iter().map(|name| {
                     ast::PathSegment::from_ident(ast::Ident::from_str(name), DUMMY_SP)
                 }).collect(),
                 span,
index 39306229c82b2e8f28cc73a957946c67f1b910c5..9edfa767d31958df8c0ff07e7850c49708c072b0 100644 (file)
@@ -78,7 +78,7 @@ pub fn modify_for_testing(sess: &ParseSess,
                           span_diagnostic: &errors::Handler,
                           features: &Features) -> ast::Crate {
     // Check for #[reexport_test_harness_main = "some_name"] which
-    // creates a `use some_name = __test::main;`. This needs to be
+    // creates a `use __test::main as some_name;`. This needs to be
     // unconditional, so that the attribute is still marked as used in
     // non-test builds.
     let reexport_test_harness_main =
@@ -240,7 +240,8 @@ fn mk_reexport_mod(cx: &mut TestCtxt,
                                   cx.ext_cx.path(DUMMY_SP, vec![super_, r]))
     }).chain(tested_submods.into_iter().map(|(r, sym)| {
         let path = cx.ext_cx.path(DUMMY_SP, vec![super_, r, sym]);
-        cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public), r, path)
+        cx.ext_cx.item_use_simple_(DUMMY_SP, dummy_spanned(ast::VisibilityKind::Public),
+                                   Some(r), path)
     })).collect();
 
     let reexport_mod = ast::Mod {
@@ -502,7 +503,7 @@ fn mk_std(cx: &TestCtxt) -> P<ast::Item> {
         (ast::ItemKind::Use(P(ast::UseTree {
             span: DUMMY_SP,
             prefix: path_node(vec![id_test]),
-            kind: ast::UseTreeKind::Simple(id_test),
+            kind: ast::UseTreeKind::Simple(None),
         })),
          ast::VisibilityKind::Public, keywords::Invalid.ident())
     } else {
@@ -590,13 +591,13 @@ fn mk_test_module(cx: &mut TestCtxt) -> (P<ast::Item>, Option<P<ast::Item>>) {
         tokens: None,
     })).pop().unwrap();
     let reexport = cx.reexport_test_harness_main.map(|s| {
-        // building `use <ident> = __test::main`
-        let reexport_ident = Ident::with_empty_ctxt(s);
+        // building `use __test::main as <ident>;`
+        let rename = Ident::with_empty_ctxt(s);
 
         let use_path = ast::UseTree {
             span: DUMMY_SP,
             prefix: path_node(vec![mod_ident, Ident::from_str("main")]),
-            kind: ast::UseTreeKind::Simple(reexport_ident),
+            kind: ast::UseTreeKind::Simple(Some(rename)),
         };
 
         expander.fold_item(P(ast::Item {
index 5a24c61cb5aaf8588f28ab255251aadbf2e3ab40..bbf1fe124f1ba3f4f4b29fe124873bc3dab25bc6 100644 (file)
@@ -213,9 +213,9 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
     visitor.visit_vis(&item.vis);
     visitor.visit_ident(item.span, item.ident);
     match item.node {
-        ItemKind::ExternCrate(opt_name) => {
-            if let Some(name) = opt_name {
-                visitor.visit_name(item.span, name);
+        ItemKind::ExternCrate(orig_name) => {
+            if let Some(orig_name) = orig_name {
+                visitor.visit_name(item.span, orig_name);
             }
         }
         ItemKind::Use(ref use_tree) => {
@@ -354,10 +354,11 @@ pub fn walk_use_tree<'a, V: Visitor<'a>>(
     visitor: &mut V, use_tree: &'a UseTree, id: NodeId,
 ) {
     visitor.visit_path(&use_tree.prefix, id);
-
     match use_tree.kind {
-        UseTreeKind::Simple(ident) => {
-            visitor.visit_ident(use_tree.span, ident);
+        UseTreeKind::Simple(rename) => {
+            if let Some(rename) = rename {
+                visitor.visit_ident(use_tree.span, rename);
+            }
         }
         UseTreeKind::Glob => {},
         UseTreeKind::Nested(ref use_trees) => {
index 1b3917efdd1e78a631da4c48c257ebf35b67e9b2..49c372b751b506d4b694807aefddaf20810a2bda 100644 (file)
@@ -530,7 +530,7 @@ fn create_derived_impl(&self,
                 id: ast::DUMMY_NODE_ID,
                 span: self.span,
                 ident,
-                vis: respan(self.span.empty(), ast::VisibilityKind::Inherited),
+                vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
                 defaultness: ast::Defaultness::Final,
                 attrs: Vec::new(),
                 generics: Generics::default(),
@@ -977,7 +977,7 @@ fn create_method(&self,
             attrs: self.attributes.clone(),
             generics: fn_generics,
             span: trait_.span,
-            vis: respan(trait_.span.empty(), ast::VisibilityKind::Inherited),
+            vis: respan(trait_.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
             defaultness: ast::Defaultness::Final,
             ident: method_ident,
             node: ast::ImplItemKind::Method(ast::MethodSig {
index 9605f6b5c5a9d30b60e24ad724e04d0ea089241e..f01a0aacb0a734a5cc2337d55bd82779b796d409 100644 (file)
@@ -60,7 +60,7 @@ pub fn expand_global_asm<'cx>(cx: &'cx mut ExtCtxt,
             asm,
             ctxt: cx.backtrace(),
         })),
-        vis: respan(sp.empty(), ast::VisibilityKind::Inherited),
+        vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
         span: sp,
         tokens: None,
     })))
index 4711d43bfab1a2e289769b24ed3f36a9d423db1a..9b83d5510fb7d836dec3d37406c80dc7b21ef566 100644 (file)
@@ -239,8 +239,15 @@ pub fn with_ctxt(self, ctxt: SyntaxContext) -> Span {
 
     /// Returns a new span representing an empty span at the beginning of this span
     #[inline]
-    pub fn empty(self) -> Span {
-        self.with_hi(self.lo())
+    pub fn shrink_to_lo(self) -> Span {
+        let span = self.data();
+        span.with_hi(span.lo)
+    }
+    /// Returns a new span representing an empty span at the end of this span
+    #[inline]
+    pub fn shrink_to_hi(self) -> Span {
+        let span = self.data();
+        span.with_lo(span.hi)
     }
 
     /// Returns `self` if `self` is not the dummy span, and `other` otherwise.
index 1c0401ec56b853bbbde4ced5ec2aef8f51b75ab3..214a03c13f4e56bde68d486ad77b99e0427e2687 100644 (file)
@@ -9,12 +9,12 @@
 // except according to those terms.
 
 #![deny(unused_import_braces)]
-#![allow(dead_code)]
-#![allow(unused_imports)]
 
 use test::{A}; //~ ERROR braces around A is unnecessary
 
 mod test {
+    use test::{self}; // OK
+    use test::{self as rename}; // OK
     pub struct A;
 }