]> git.lizzy.rs Git - rust.git/commitdiff
rustc: desugar `use a::{b,c};` into `use a::b; use a::c;` in HIR.
authorEduard-Mihai Burtescu <edy.burt@gmail.com>
Thu, 24 Nov 2016 04:11:31 +0000 (06:11 +0200)
committerEduard-Mihai Burtescu <edy.burt@gmail.com>
Mon, 28 Nov 2016 02:18:10 +0000 (04:18 +0200)
29 files changed:
src/librustc/hir/intravisit.rs
src/librustc/hir/lowering.rs
src/librustc/hir/map/collector.rs
src/librustc/hir/map/def_collector.rs
src/librustc/hir/map/mod.rs
src/librustc/hir/mod.rs
src/librustc/hir/print.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/middle/dead.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc_incremental/calculate_svh/svh_visitor.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_lint/unused.rs
src/librustc_metadata/encoder.rs
src/librustc_passes/hir_stats.rs
src/librustc_typeck/check_unused.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/variance/constraints.rs
src/librustc_typeck/variance/terms.rs
src/librustdoc/clean/mod.rs
src/librustdoc/doctree.rs
src/librustdoc/html/format.rs
src/librustdoc/visit_ast.rs
src/test/rustdoc/viewpath-rename.rs
src/test/rustdoc/viewpath-self.rs

index 743eed74d0cea6856babb2bc15c5e4021810f958..3de788b8c1af1818800e2efecacb6a4fcc656485 100644 (file)
@@ -250,9 +250,6 @@ fn visit_qpath(&mut self, qpath: &'v QPath, id: NodeId, span: Span) {
     fn visit_path(&mut self, path: &'v Path, _id: NodeId) {
         walk_path(self, path)
     }
-    fn visit_path_list_item(&mut self, prefix: &'v Path, item: &'v PathListItem) {
-        walk_path_list_item(self, prefix, item)
-    }
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
         walk_path_segment(self, path_span, path_segment)
     }
@@ -352,23 +349,9 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_id(item.id);
             walk_opt_name(visitor, item.span, opt_name)
         }
-        ItemUse(ref vp) => {
+        ItemUse(ref path, _) => {
             visitor.visit_id(item.id);
-            match vp.node {
-                ViewPathSimple(name, ref path) => {
-                    visitor.visit_name(vp.span, name);
-                    visitor.visit_path(path, item.id);
-                }
-                ViewPathGlob(ref path) => {
-                    visitor.visit_path(path, item.id);
-                }
-                ViewPathList(ref prefix, ref list) => {
-                    visitor.visit_path(prefix, item.id);
-                    for item in list {
-                        visitor.visit_path_list_item(prefix, item)
-                    }
-                }
-            }
+            visitor.visit_path(path, item.id);
         }
         ItemStatic(ref typ, _, ref expr) |
         ItemConst(ref typ, ref expr) => {
@@ -529,14 +512,6 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
     }
 }
 
-pub fn walk_path_list_item<'v, V>(visitor: &mut V, _prefix: &'v Path, item: &'v PathListItem)
-    where V: Visitor<'v>,
-{
-    visitor.visit_id(item.node.id);
-    visitor.visit_name(item.span, item.node.name);
-    walk_opt_name(visitor, item.span, item.node.rename);
-}
-
 pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
                                              path_span: Span,
                                              segment: &'v PathSegment) {
index 056c1b906206a5492f344d258fa65e458d731b1c..af0448cc27755993d13d70fc3b28cf0cb22bc29b 100644 (file)
@@ -55,6 +55,7 @@
 use syntax::codemap::{respan, Spanned};
 use syntax::std_inject;
 use syntax::symbol::{Symbol, keywords};
+use syntax::util::small_vector::SmallVector;
 use syntax::visit::{self, Visitor};
 use syntax_pos::Span;
 
@@ -67,6 +68,11 @@ pub struct LoweringContext<'a> {
     // a definition, then we can properly create the def id.
     parent_def: Option<DefIndex>,
     resolver: &'a mut Resolver,
+
+    /// The items being lowered are collected here.
+    items: BTreeMap<NodeId, hir::Item>,
+
+    impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
 }
 
 pub trait Resolver {
@@ -98,6 +104,8 @@ pub fn lower_crate(sess: &Session,
         sess: sess,
         parent_def: None,
         resolver: resolver,
+        items: BTreeMap::new(),
+        impl_items: BTreeMap::new(),
     }.lower_crate(krate)
 }
 
@@ -110,41 +118,35 @@ enum ParamMode {
 }
 
 impl<'a> LoweringContext<'a> {
-    fn lower_crate(&mut self, c: &Crate) -> hir::Crate {
+    fn lower_crate(mut self, c: &Crate) -> hir::Crate {
         struct ItemLowerer<'lcx, 'interner: 'lcx> {
-            items: BTreeMap<NodeId, hir::Item>,
-            impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem>,
             lctx: &'lcx mut LoweringContext<'interner>,
         }
 
         impl<'lcx, 'interner> Visitor for ItemLowerer<'lcx, 'interner> {
             fn visit_item(&mut self, item: &Item) {
-                self.items.insert(item.id, self.lctx.lower_item(item));
+                let hir_item = self.lctx.lower_item(item);
+                self.lctx.items.insert(item.id, hir_item);
                 visit::walk_item(self, item);
             }
 
             fn visit_impl_item(&mut self, item: &ImplItem) {
                 let id = self.lctx.lower_impl_item_ref(item).id;
-                self.impl_items.insert(id, self.lctx.lower_impl_item(item));
+                let hir_item = self.lctx.lower_impl_item(item);
+                self.lctx.impl_items.insert(id, hir_item);
                 visit::walk_impl_item(self, item);
             }
         }
 
-        let (items, impl_items) = {
-            let mut item_lowerer = ItemLowerer { items: BTreeMap::new(),
-                                                 impl_items: BTreeMap::new(),
-                                                 lctx: self };
-            visit::walk_crate(&mut item_lowerer, c);
-            (item_lowerer.items, item_lowerer.impl_items)
-        };
+        visit::walk_crate(&mut ItemLowerer { lctx: &mut self }, c);
 
         hir::Crate {
             module: self.lower_mod(&c.module),
             attrs: self.lower_attrs(&c.attrs),
             span: c.span,
             exported_macros: c.exported_macros.iter().map(|m| self.lower_macro_def(m)).collect(),
-            items: items,
-            impl_items: impl_items,
+            items: self.items,
+            impl_items: self.impl_items,
         }
     }
 
@@ -183,38 +185,6 @@ fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
         attrs.clone().into()
     }
 
-    fn lower_view_path(&mut self, view_path: &ViewPath) -> P<hir::ViewPath> {
-        P(Spanned {
-            node: match view_path.node {
-                ViewPathSimple(ident, ref path) => {
-                    hir::ViewPathSimple(ident.name,
-                                        self.lower_path(path, ParamMode::Explicit))
-                }
-                ViewPathGlob(ref path) => {
-                    hir::ViewPathGlob(self.lower_path(path, ParamMode::Explicit))
-                }
-                ViewPathList(ref path, ref path_list_idents) => {
-                    hir::ViewPathList(self.lower_path(path, ParamMode::Explicit),
-                                      path_list_idents.iter()
-                                                      .map(|item| self.lower_path_list_item(item))
-                                                      .collect())
-                }
-            },
-            span: view_path.span,
-        })
-    }
-
-    fn lower_path_list_item(&mut self, path_list_ident: &PathListItem) -> hir::PathListItem {
-        Spanned {
-            node: hir::PathListItem_ {
-                id: path_list_ident.node.id,
-                name: path_list_ident.node.name.name,
-                rename: path_list_ident.node.rename.map(|rename| rename.name),
-            },
-            span: path_list_ident.span,
-        }
-    }
-
     fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {
         hir::Arm {
             attrs: self.lower_attrs(&arm.attrs),
@@ -382,19 +352,32 @@ fn lower_qpath(&mut self,
                   proj_start, p.segments.len())
     }
 
-    fn lower_path(&mut self,
-                  p: &Path,
-                  param_mode: ParamMode)
-                  -> hir::Path {
+    fn lower_path_extra(&mut self,
+                        p: &Path,
+                        name: Option<Name>,
+                        param_mode: ParamMode)
+                        -> hir::Path {
         hir::Path {
             global: p.global,
             segments: p.segments.iter().map(|segment| {
                 self.lower_path_segment(segment, param_mode)
-            }).collect(),
+            }).chain(name.map(|name| {
+                hir::PathSegment {
+                    name: name,
+                    parameters: hir::PathParameters::none()
+                }
+            })).collect(),
             span: p.span,
         }
     }
 
+    fn lower_path(&mut self,
+                  p: &Path,
+                  param_mode: ParamMode)
+                  -> hir::Path {
+        self.lower_path_extra(p, None, param_mode)
+    }
+
     fn lower_path_segment(&mut self,
                           segment: &PathSegment,
                           param_mode: ParamMode)
@@ -661,12 +644,10 @@ fn lower_bounds(&mut self, bounds: &TyParamBounds) -> hir::TyParamBounds {
     }
 
     fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
-        let mut stmts = Vec::new();
         let mut expr = None;
 
-        if let Some((last, rest)) = b.stmts.split_last() {
-            stmts = rest.iter().map(|s| self.lower_stmt(s)).collect::<Vec<_>>();
-            let last = self.lower_stmt(last);
+        let mut stmts = b.stmts.iter().flat_map(|s| self.lower_stmt(s)).collect::<Vec<_>>();
+        if let Some(last) = stmts.pop() {
             if let hir::StmtExpr(e, _) = last.node {
                 expr = Some(e);
             } else {
@@ -683,11 +664,65 @@ fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
         })
     }
 
-    fn lower_item_kind(&mut self, i: &ItemKind) -> hir::Item_ {
+    fn lower_item_kind(&mut self,
+                       name: &mut Name,
+                       attrs: &hir::HirVec<Attribute>,
+                       vis: &mut hir::Visibility,
+                       i: &ItemKind)
+                       -> hir::Item_ {
         match *i {
             ItemKind::ExternCrate(string) => hir::ItemExternCrate(string),
             ItemKind::Use(ref view_path) => {
-                hir::ItemUse(self.lower_view_path(view_path))
+                let path = match view_path.node {
+                    ViewPathSimple(_, ref path) => path,
+                    ViewPathGlob(ref path) => path,
+                    ViewPathList(ref path, ref path_list_idents) => {
+                        for &Spanned { node: ref import, span } in path_list_idents {
+                            // `use a::{self as x, b as y};` lowers to
+                            // `use a as x; use a::b as y;`
+                            let mut ident = import.name;
+                            let suffix = if ident.name == keywords::SelfValue.name() {
+                                if let Some(last) = path.segments.last() {
+                                    ident = last.identifier;
+                                }
+                                None
+                            } else {
+                                Some(ident.name)
+                            };
+
+                            let mut path = self.lower_path_extra(path, suffix,
+                                                                 ParamMode::Explicit);
+                            path.span = span;
+                            self.items.insert(import.id, hir::Item {
+                                id: import.id,
+                                name: import.rename.unwrap_or(ident).name,
+                                attrs: attrs.clone(),
+                                node: hir::ItemUse(P(path), hir::UseKind::Single),
+                                vis: vis.clone(),
+                                span: span,
+                            });
+                        }
+                        path
+                    }
+                };
+                let path = P(self.lower_path(path, ParamMode::Explicit));
+                let kind = match view_path.node {
+                    ViewPathSimple(ident, _) => {
+                        *name = ident.name;
+                        hir::UseKind::Single
+                    }
+                    ViewPathGlob(_) => {
+                        hir::UseKind::Glob
+                    }
+                    ViewPathList(..) => {
+                        // Privatize the degenerate import base, used only to check
+                        // the stability of `use a::{};`, to avoid it showing up as
+                        // a reexport by accident when `pub`, e.g. in documentation.
+                        *vis = hir::Inherited;
+                        hir::UseKind::ListStem
+                    }
+                };
+                hir::ItemUse(path, kind)
             }
             ItemKind::Static(ref t, m, ref e) => {
                 hir::ItemStatic(self.lower_ty(t),
@@ -835,7 +870,7 @@ fn lower_impl_item_ref(&mut self, i: &ImplItem) -> hir::ImplItemRef {
     fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
         hir::Mod {
             inner: m.inner,
-            item_ids: m.items.iter().map(|x| self.lower_item_id(x)).collect(),
+            item_ids: m.items.iter().flat_map(|x| self.lower_item_id(x)).collect(),
         }
     }
 
@@ -851,21 +886,30 @@ fn lower_macro_def(&mut self, m: &MacroDef) -> hir::MacroDef {
         }
     }
 
-    fn lower_item_id(&mut self, i: &Item) -> hir::ItemId {
-        hir::ItemId { id: i.id }
+    fn lower_item_id(&mut self, i: &Item) -> SmallVector<hir::ItemId> {
+        if let ItemKind::Use(ref view_path) = i.node {
+            if let ViewPathList(_, ref imports) = view_path.node {
+                return iter::once(i.id).chain(imports.iter().map(|import| import.node.id))
+                    .map(|id| hir::ItemId { id: id }).collect();
+            }
+        }
+        SmallVector::one(hir::ItemId { id: i.id })
     }
 
     pub fn lower_item(&mut self, i: &Item) -> hir::Item {
+        let mut name = i.ident.name;
+        let attrs = self.lower_attrs(&i.attrs);
+        let mut vis = self.lower_visibility(&i.vis);
         let node = self.with_parent_def(i.id, |this| {
-            this.lower_item_kind(&i.node)
+            this.lower_item_kind(&mut name, &attrs, &mut vis, &i.node)
         });
 
         hir::Item {
             id: i.id,
-            name: i.ident.name,
-            attrs: self.lower_attrs(&i.attrs),
+            name: name,
+            attrs: attrs,
             node: node,
-            vis: self.lower_visibility(&i.vis),
+            vis: vis,
             span: i.span,
         }
     }
@@ -1701,8 +1745,8 @@ fn make_struct(this: &mut LoweringContext,
         }
     }
 
-    fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt {
-        match s.node {
+    fn lower_stmt(&mut self, s: &Stmt) -> SmallVector<hir::Stmt> {
+        SmallVector::one(match s.node {
             StmtKind::Local(ref l) => Spanned {
                 node: hir::StmtDecl(P(Spanned {
                     node: hir::DeclLocal(self.lower_local(l)),
@@ -1710,13 +1754,17 @@ fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt {
                 }), s.id),
                 span: s.span,
             },
-            StmtKind::Item(ref it) => Spanned {
-                node: hir::StmtDecl(P(Spanned {
-                    node: hir::DeclItem(self.lower_item_id(it)),
+            StmtKind::Item(ref it) => {
+                // Can only use the ID once.
+                let mut id = Some(s.id);
+                return self.lower_item_id(it).into_iter().map(|item_id| Spanned {
+                    node: hir::StmtDecl(P(Spanned {
+                        node: hir::DeclItem(item_id),
+                        span: s.span,
+                    }), id.take().unwrap_or_else(|| self.next_id())),
                     span: s.span,
-                }), s.id),
-                span: s.span,
-            },
+                }).collect();
+            }
             StmtKind::Expr(ref e) => {
                 Spanned {
                     node: hir::StmtExpr(P(self.lower_expr(e)), s.id),
@@ -1730,7 +1778,7 @@ fn lower_stmt(&mut self, s: &Stmt) -> hir::Stmt {
                 }
             }
             StmtKind::Mac(..) => panic!("Shouldn't exist here"),
-        }
+        })
     }
 
     fn lower_capture_clause(&mut self, c: CaptureBy) -> hir::CaptureClause {
index 64bf4bbf08039d45737d102ae889cfe00847dae4..67e9b24f42d2200d2c54107990bfbb23b8aaa239 100644 (file)
@@ -124,16 +124,6 @@ fn visit_item(&mut self, i: &'ast Item) {
                         this.insert(struct_def.id(), NodeStructCtor(struct_def));
                     }
                 }
-                ItemUse(ref view_path) => {
-                    match view_path.node {
-                        ViewPathList(_, ref paths) => {
-                            for path in paths {
-                                this.insert(path.node.id, NodeItem(i));
-                            }
-                        }
-                        _ => ()
-                    }
-                }
                 _ => {}
             }
             intravisit::walk_item(this, i);
index 7486d954c480233fde7058411c821c964a26a25f..9d1c7d41faa261278490480ed1476bd8f90375a3 100644 (file)
@@ -155,7 +155,20 @@ fn visit_item(&mut self, i: &Item) {
                 DefPathData::ValueNs(i.ident.name.as_str()),
             ItemKind::Mac(..) if i.id == DUMMY_NODE_ID => return, // Scope placeholder
             ItemKind::Mac(..) => return self.visit_macro_invoc(i.id, false),
-            ItemKind::Use(..) => DefPathData::Misc,
+            ItemKind::Use(ref view_path) => {
+                match view_path.node {
+                    ViewPathGlob(..) => {}
+
+                    // FIXME(eddyb) Should use the real name. Which namespace?
+                    ViewPathSimple(..) => {}
+                    ViewPathList(_, ref imports) => {
+                        for import in imports {
+                            self.create_def(import.node.id, DefPathData::Misc);
+                        }
+                    }
+                }
+                DefPathData::Misc
+            }
         };
         let def = self.create_def(i.id, def_data);
 
index 7f6c85eeaac8d40f50430cba5f25423666a52177..a8986530d1d3d91242604767d25189d5da672231 100644 (file)
@@ -250,16 +250,8 @@ fn dep_node(&self, id0: NodeId) -> DepNode<DefId> {
             loop {
                 match map[id.as_usize()] {
                     EntryItem(_, item) => {
-                        let def_id = self.local_def_id(item.id);
-                        // NB                          ^~~~~~~
-                        //
-                        // You would expect that `item.id == id`, but this
-                        // is not always the case. In particular, for a
-                        // ViewPath item like `use self::{mem, foo}`, we
-                        // map the ids for `mem` and `foo` to the
-                        // enclosing view path item. This seems mega super
-                        // ultra wrong, but then who am I to judge?
-                        // -nmatsakis
+                        assert_eq!(id, item.id);
+                        let def_id = self.local_def_id(id);
                         assert!(!self.is_inlined_def_id(def_id));
                         return DepNode::Hir(def_id);
                     }
index e9e84eed3e78c02c96381542d7124d073894a01e..da759b2d4daca5eb4b35b9cd6b6992fbb86fc517 100644 (file)
@@ -27,7 +27,6 @@
 pub use self::TyParamBound::*;
 pub use self::UnOp::*;
 pub use self::UnsafeSource::*;
-pub use self::ViewPath_::*;
 pub use self::Visibility::{Public, Inherited};
 pub use self::PathParameters::*;
 
@@ -1385,32 +1384,20 @@ pub struct Variant_ {
 
 pub type Variant = Spanned<Variant_>;
 
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
-pub struct PathListItem_ {
-    pub name: Name,
-    /// renamed in list, eg `use foo::{bar as baz};`
-    pub rename: Option<Name>,
-    pub id: NodeId,
-}
-
-pub type PathListItem = Spanned<PathListItem_>;
-
-pub type ViewPath = Spanned<ViewPath_>;
-
-#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum ViewPath_ {
-    /// `foo::bar::baz as quux`
-    ///
-    /// or just
-    ///
-    /// `foo::bar::baz` (with `as baz` implicitly on the right)
-    ViewPathSimple(Name, Path),
+#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
+pub enum UseKind {
+    /// One import, e.g. `use foo::bar` or `use foo::bar as baz`.
+    /// Also produced for each element of a list `use`, e.g.
+    // `use foo::{a, b}` lowers to `use foo::a; use foo::b;`.
+    Single,
 
-    /// `foo::bar::*`
-    ViewPathGlob(Path),
+    /// Glob import, e.g. `use foo::*`.
+    Glob,
 
-    /// `foo::bar::{a,b,c}`
-    ViewPathList(Path, HirVec<PathListItem>),
+    /// Degenerate list import, e.g. `use foo::{a, b}` produces
+    /// an additional `use foo::{}` for performing checks such as
+    /// unstable feature gating. May be removed in the future.
+    ListStem,
 }
 
 /// TraitRef's appear in impls.
@@ -1544,8 +1531,13 @@ pub enum Item_ {
     ///
     /// e.g. `extern crate foo` or `extern crate foo_bar as foo`
     ItemExternCrate(Option<Name>),
-    /// A `use` or `pub use` item
-    ItemUse(P<ViewPath>),
+
+    /// `use foo::bar::*;` or `use foo::bar::baz as quux;`
+    ///
+    /// or just
+    ///
+    /// `use foo::bar::baz;` (with `as baz` implicitly on the right)
+    ItemUse(P<Path>, UseKind),
 
     /// A `static` item
     ItemStatic(P<Ty>, Mutability, P<Expr>),
index f6f40a91bf491097a2f1e8933a20f02349ad720d..4dd08def251e96c9053d7f41d5d876675a65e12c 100644 (file)
@@ -669,10 +669,22 @@ pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> {
                 self.end()?; // end inner head-block
                 self.end()?; // end outer head-block
             }
-            hir::ItemUse(ref vp) => {
+            hir::ItemUse(ref path, kind) => {
                 self.head(&visibility_qualified(&item.vis, "use"))?;
-                self.print_view_path(&vp)?;
-                word(&mut self.s, ";")?;
+                self.print_path(path, false)?;
+
+                match kind {
+                    hir::UseKind::Single => {
+                        if path.segments.last().unwrap().name != item.name {
+                            space(&mut self.s)?;
+                            self.word_space("as")?;
+                            self.print_name(item.name)?;
+                        }
+                        word(&mut self.s, ";")?;
+                    }
+                    hir::UseKind::Glob => word(&mut self.s, "::*;")?,
+                    hir::UseKind::ListStem => word(&mut self.s, "::{};")?
+                }
                 self.end()?; // end inner head-block
                 self.end()?; // end outer head-block
             }
@@ -2153,38 +2165,6 @@ pub fn print_where_clause(&mut self, where_clause: &hir::WhereClause) -> io::Res
         Ok(())
     }
 
-    pub fn print_view_path(&mut self, vp: &hir::ViewPath) -> io::Result<()> {
-        match vp.node {
-            hir::ViewPathSimple(name, ref path) => {
-                self.print_path(path, false)?;
-
-                if path.segments.last().unwrap().name != name {
-                    space(&mut self.s)?;
-                    self.word_space("as")?;
-                    self.print_name(name)?;
-                }
-
-                Ok(())
-            }
-
-            hir::ViewPathGlob(ref path) => {
-                self.print_path(path, false)?;
-                word(&mut self.s, "::*")
-            }
-
-            hir::ViewPathList(ref path, ref segments) => {
-                if path.segments.is_empty() {
-                    word(&mut self.s, "{")?;
-                } else {
-                    self.print_path(path, false)?;
-                    word(&mut self.s, "::{")?;
-                }
-                self.commasep(Inconsistent, &segments[..], |s, w| s.print_name(w.node.name))?;
-                word(&mut self.s, "}")
-            }
-        }
-    }
-
     pub fn print_mutability(&mut self, mutbl: hir::Mutability) -> io::Result<()> {
         match mutbl {
             hir::MutMutable => self.word_nbsp("mut"),
index 4a082944010b2838fb73d12cc26d84f9d7bea0eb..41c8d413486dc72c37bf4fcec4a64d26be0b733a 100644 (file)
@@ -948,11 +948,6 @@ fn visit_path(&mut self, p: &'tcx hir::Path, id: ast::NodeId) {
         hir_visit::walk_path(self, p);
     }
 
-    fn visit_path_list_item(&mut self, prefix: &'tcx hir::Path, item: &'tcx hir::PathListItem) {
-        run_lints!(self, check_path_list_item, late_passes, item);
-        hir_visit::walk_path_list_item(self, prefix, item);
-    }
-
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
         check_lint_name_attribute(self, attr);
         run_lints!(self, check_attribute, late_passes, attr);
index 6f7102229f8d6150ecef22853b687cfe78b26216..4e06e0abf0148b6543348e1eac670a8c59a3274d 100644 (file)
@@ -168,7 +168,6 @@ fn check_variant_post(&mut self, _: &LateContext, _: &hir::Variant, _: &hir::Gen
     fn check_lifetime(&mut self, _: &LateContext, _: &hir::Lifetime) { }
     fn check_lifetime_def(&mut self, _: &LateContext, _: &hir::LifetimeDef) { }
     fn check_path(&mut self, _: &LateContext, _: &hir::Path, _: ast::NodeId) { }
-    fn check_path_list_item(&mut self, _: &LateContext, _: &hir::PathListItem) { }
     fn check_attribute(&mut self, _: &LateContext, _: &ast::Attribute) { }
 
     /// Called when entering a syntax node that can have lint attributes such
index efbec7bf13b9ea03a75d57dce04b0720a7ec80cf..ec064e264ab3ce89fd12fa8bf493dc81fcaac791 100644 (file)
@@ -297,11 +297,6 @@ fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
         self.lookup_and_handle_definition(id);
         intravisit::walk_path(self, path);
     }
-
-    fn visit_path_list_item(&mut self, path: &hir::Path, item: &hir::PathListItem) {
-        self.lookup_and_handle_definition(item.node.id);
-        intravisit::walk_path_list_item(self, path, item);
-    }
 }
 
 fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
index 0329b4c4a3019bbb77fa6a65e132dfe9d6809757..91c1c63d89063609f2f0671dd4748b8ff685ad99 100644 (file)
@@ -265,7 +265,7 @@ fn propagate_node(&mut self, node: &ast_map::Node,
                     // These are normal, nothing reachable about these
                     // inherently and their children are already in the
                     // worklist, as determined by the privacy pass
-                    hir::ItemExternCrate(_) | hir::ItemUse(_) |
+                    hir::ItemExternCrate(_) | hir::ItemUse(..) |
                     hir::ItemTy(..) | hir::ItemStatic(..) |
                     hir::ItemMod(..) | hir::ItemForeignMod(..) |
                     hir::ItemImpl(..) | hir::ItemTrait(..) |
index c65fd25950deab808fe80638c0d01258a81c6919..f256d6d9b4f847b766c7fef37546381bbb52d2f5 100644 (file)
@@ -151,7 +151,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
                     intravisit::walk_item(this, item);
                 }
                 hir::ItemExternCrate(_) |
-                hir::ItemUse(_) |
+                hir::ItemUse(..) |
                 hir::ItemMod(..) |
                 hir::ItemDefaultImpl(..) |
                 hir::ItemForeignMod(..) |
index a044ffd9a7f85e27b06147f4f7e96e6928f5f131..d7a29e190a8f1203ad0dd550269f89c468c784be 100644 (file)
@@ -474,12 +474,6 @@ fn visit_path(&mut self, path: &'tcx hir::Path, id: ast::NodeId) {
         intravisit::walk_path(self, path)
     }
 
-    fn visit_path_list_item(&mut self, prefix: &'tcx hir::Path, item: &'tcx hir::PathListItem) {
-        check_path_list_item(self.tcx, item,
-                   &mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
-        intravisit::walk_path_list_item(self, prefix, item)
-    }
-
     fn visit_pat(&mut self, pat: &'tcx hir::Pat) {
         check_pat(self.tcx, pat,
                   &mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
@@ -628,14 +622,6 @@ pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     }
 }
 
-pub fn check_path_list_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                      item: &hir::PathListItem,
-                                      cb: &mut FnMut(DefId, Span,
-                                                     &Option<&Stability>,
-                                                     &Option<DeprecationEntry>)) {
-    maybe_do_stability_check(tcx, tcx.expect_def(item.node.id).def_id(), item.span, cb);
-}
-
 pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
                            cb: &mut FnMut(DefId, Span,
                                           &Option<&Stability>,
index ec405311012592231027300d7cb2f21bffd6e5f6..8c6d8dffa1db53857c011164df584144f5026386 100644 (file)
@@ -189,7 +189,6 @@ enum SawAbiComponent<'a> {
     SawPath(bool),
     SawPathSegment,
     SawPathParameters,
-    SawPathListItem,
     SawBlock,
     SawPat(SawPatComponent),
     SawLocal,
@@ -357,7 +356,7 @@ fn saw_lit(lit: &ast::Lit) -> SawExprComponent<'static> {
 #[derive(Hash)]
 enum SawItemComponent {
     SawItemExternCrate,
-    SawItemUse,
+    SawItemUse(UseKind),
     SawItemStatic(Mutability),
     SawItemConst,
     SawItemFn(Unsafety, Constness, Abi),
@@ -375,7 +374,7 @@ enum SawItemComponent {
 fn saw_item(node: &Item_) -> SawItemComponent {
     match *node {
         ItemExternCrate(..) => SawItemExternCrate,
-        ItemUse(..) => SawItemUse,
+        ItemUse(_, kind) => SawItemUse(kind),
         ItemStatic(_, mutability, _) => SawItemStatic(mutability),
         ItemConst(..) =>SawItemConst,
         ItemFn(_, unsafety, constness, abi, _, _) => SawItemFn(unsafety, constness, abi),
@@ -747,14 +746,6 @@ fn visit_poly_trait_ref(&mut self, t: &'tcx PolyTraitRef, m: &'tcx TraitBoundMod
         visit::walk_poly_trait_ref(self, t, m)
     }
 
-    fn visit_path_list_item(&mut self, prefix: &'tcx Path, item: &'tcx PathListItem) {
-        debug!("visit_path_list_item: st={:?}", self.st);
-        SawPathListItem.hash(self.st);
-        self.hash_discriminant(&item.node);
-        hash_span!(self, item.span);
-        visit::walk_path_list_item(self, prefix, item)
-    }
-
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'tcx PathSegment) {
         debug!("visit_path_segment: st={:?}", self.st);
         SawPathSegment.hash(self.st);
index 7be591293c91bb2583c2577e9e914125d722ced4..d91327bc86bf8406e7c76aa26eef6cf0f5b59db8 100644 (file)
@@ -704,14 +704,6 @@ fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) {
                               &mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr));
     }
 
-    fn check_path_list_item(&mut self, cx: &LateContext, item: &hir::PathListItem) {
-        stability::check_path_list_item(cx.tcx,
-                                        item,
-                                        &mut |id, sp, stab, depr| {
-                                            self.lint(cx, id, sp, &stab, &depr)
-                                        });
-    }
-
     fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
         stability::check_pat(cx.tcx,
                              pat,
index 1a3ea5db871ebedc1363cba4e1f9550f9623fcbc..0b92107c81708e945c5375600de629247d57da77 100644 (file)
@@ -111,6 +111,7 @@ macro_rules! add_lint_group {
 
     add_early_builtin!(sess,
                        UnusedParens,
+                       UnusedImportBraces,
                        );
 
     add_early_builtin_with_new!(sess,
@@ -129,7 +130,6 @@ macro_rules! add_lint_group {
                  NonCamelCaseTypes,
                  NonSnakeCase,
                  NonUpperCaseGlobals,
-                 UnusedImportBraces,
                  NonShorthandFieldPatterns,
                  UnusedUnsafe,
                  UnsafeCode,
index d0ad682fb58a60a7547a9e918a6eda22b4cf7f0f..324cbd17ab36bc90c8b599a46fa213c10bc4c580 100644 (file)
@@ -406,11 +406,11 @@ fn get_lints(&self) -> LintArray {
     }
 }
 
-impl LateLintPass for UnusedImportBraces {
-    fn check_item(&mut self, cx: &LateContext, item: &hir::Item) {
-        if let hir::ItemUse(ref view_path) = item.node {
-            if let hir::ViewPathList(_, ref items) = view_path.node {
-                if items.len() == 1 && items[0].node.name != keywords::SelfValue.name() {
+impl EarlyLintPass for UnusedImportBraces {
+    fn check_item(&mut self, cx: &EarlyContext, item: &ast::Item) {
+        if let ast::ItemKind::Use(ref view_path) = item.node {
+            if let ast::ViewPathList(_, ref items) = view_path.node {
+                if items.len() == 1 && items[0].node.name.name != keywords::SelfValue.name() {
                     let msg = format!("braces around {} is unnecessary", items[0].node.name);
                     cx.span_lint(UNUSED_IMPORT_BRACES, item.span, &msg);
                 }
index 665f3de0a3ba7fda9a389cc3c257d19f4ae19708..8f3e8a48b1ab5969b926f3b8c211cbd4edf68b8e 100644 (file)
@@ -729,7 +729,7 @@ fn encode_info_for_item(&mut self, (def_id, item): (DefId, &hir::Item)) -> Entry
                 EntryKind::Trait(self.lazy(&data))
             }
             hir::ItemExternCrate(_) |
-            hir::ItemUse(_) => bug!("cannot encode info for item {:?}", item),
+            hir::ItemUse(..) => bug!("cannot encode info for item {:?}", item),
         };
 
         Entry {
@@ -982,7 +982,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
         let def_id = self.index.tcx.map.local_def_id(item.id);
         match item.node {
             hir::ItemExternCrate(_) |
-            hir::ItemUse(_) => (), // ignore these
+            hir::ItemUse(..) => (), // ignore these
             _ => self.index.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)),
         }
         self.index.encode_addl_info_for_item(item);
index 9028821ef116d760719f7a673c75bf30297c50f5..ba236ea93a4bc37df3c71b5a4e5fa83ed0979256 100644 (file)
@@ -226,12 +226,6 @@ fn visit_path(&mut self, path: &'v hir::Path, _id: NodeId) {
         self.record("Path", Id::None, path);
         hir_visit::walk_path(self, path)
     }
-    fn visit_path_list_item(&mut self,
-                            prefix: &'v hir::Path,
-                            item: &'v hir::PathListItem) {
-        self.record("PathListItem", Id::Node(item.node.id), item);
-        hir_visit::walk_path_list_item(self, prefix, item)
-    }
     fn visit_path_segment(&mut self,
                           path_span: Span,
                           path_segment: &'v hir::PathSegment) {
index b4a10c52270e2f9f5560ec8e02e1a1668dcfa1d0..0034a85f8e29e0b156da2ddf5d281f872b691189 100644 (file)
@@ -45,17 +45,8 @@ fn visit_item(&mut self, item: &hir::Item) {
         if item.vis == hir::Public || item.span == DUMMY_SP {
             return;
         }
-        if let hir::ItemUse(ref path) = item.node {
-            match path.node {
-                hir::ViewPathSimple(..) | hir::ViewPathGlob(..) => {
-                    self.check_import(item.id, path.span);
-                }
-                hir::ViewPathList(_, ref path_list) => {
-                    for path_item in path_list {
-                        self.check_import(path_item.node.id, path_item.span);
-                    }
-                }
-            }
+        if let hir::ItemUse(ref path, _) = item.node {
+            self.check_import(item.id, path.span);
         }
     }
 
index ca5208b7a035aae6dbdcb1f0c62cb6d27f67db70..b83e453b2de783cb61fc465d46c3d61360ba2a47 100644 (file)
@@ -696,7 +696,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
     debug!("convert: item {} with id {}", it.name, it.id);
     match it.node {
         // These don't define types.
-        hir::ItemExternCrate(_) | hir::ItemUse(_) | hir::ItemMod(_) => {
+        hir::ItemExternCrate(_) | hir::ItemUse(..) | hir::ItemMod(_) => {
         }
         hir::ItemForeignMod(ref foreign_mod) => {
             for item in &foreign_mod.items {
index 8a0c1c68322d078c9b135610d7898745c0a1756b..686d1a4a7716d823e38a204e5346d68c7b85d2aa 100644 (file)
@@ -104,7 +104,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             }
 
             hir::ItemExternCrate(_) |
-            hir::ItemUse(_) |
+            hir::ItemUse(..) |
             hir::ItemStatic(..) |
             hir::ItemConst(..) |
             hir::ItemFn(..) |
index 0a3238480d9080efaf2821bf4623890f5140d448..851cfcd87231f8a8790a1c6fafa1ec75ba1c8d48 100644 (file)
@@ -246,7 +246,7 @@ fn visit_item(&mut self, item: &hir::Item) {
             }
 
             hir::ItemExternCrate(_) |
-            hir::ItemUse(_) |
+            hir::ItemUse(..) |
             hir::ItemDefaultImpl(..) |
             hir::ItemImpl(..) |
             hir::ItemStatic(..) |
index aff384043497e0b5988e8f7411d2eabd4c6f132c..5e1b12e80d4fbcbb9b505e7d6b21be16532ad176 100644 (file)
@@ -2589,47 +2589,19 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
                 None => false,
             }
         });
-        let (mut ret, inner) = match self.node {
-            hir::ViewPathGlob(ref p) => {
-                (vec![], Import::Glob(resolve_use_source(cx, p.clean(cx), self.id)))
-            }
-            hir::ViewPathList(ref p, ref list) => {
-                // Attempt to inline all reexported items, but be sure
-                // to keep any non-inlineable reexports so they can be
-                // listed in the documentation.
-                let mut ret = vec![];
-                let remaining = if !denied {
-                    let mut remaining = vec![];
-                    for path in list {
-                        match inline::try_inline(cx, path.node.id, path.node.rename) {
-                            Some(items) => {
-                                ret.extend(items);
-                            }
-                            None => {
-                                remaining.push(path.clean(cx));
-                            }
-                        }
-                    }
-                    remaining
-                } else {
-                    list.clean(cx)
-                };
-                if remaining.is_empty() {
-                    return ret;
-                }
-                (ret, Import::List(resolve_use_source(cx, p.clean(cx), self.id), remaining))
-            }
-            hir::ViewPathSimple(name, ref p) => {
-                if !denied {
-                    if let Some(items) = inline::try_inline(cx, self.id, Some(name)) {
-                        return items;
-                    }
+        let path = self.path.clean(cx);
+        let inner = if self.glob {
+            Import::Glob(resolve_use_source(cx, path, self.id))
+        } else {
+            let name = self.name;
+            if !denied {
+                if let Some(items) = inline::try_inline(cx, self.id, Some(name)) {
+                    return items;
                 }
-                (vec![], Import::Simple(name.clean(cx),
-                                        resolve_use_source(cx, p.clean(cx), self.id)))
             }
+            Import::Simple(name.clean(cx), resolve_use_source(cx, path, self.id))
         };
-        ret.push(Item {
+        vec![Item {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
@@ -2638,8 +2610,7 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
             stability: None,
             deprecation: None,
             inner: ImportItem(inner)
-        });
-        ret
+        }]
     }
 }
 
@@ -2648,9 +2619,7 @@ pub enum Import {
     // use source as str;
     Simple(String, ImportSource),
     // use source::*;
-    Glob(ImportSource),
-    // use source::{a, b, c};
-    List(ImportSource, Vec<ViewListIdent>),
+    Glob(ImportSource)
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
@@ -2659,23 +2628,6 @@ pub struct ImportSource {
     pub did: Option<DefId>,
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
-pub struct ViewListIdent {
-    pub name: String,
-    pub rename: Option<String>,
-    pub source: Option<DefId>,
-}
-
-impl Clean<ViewListIdent> for hir::PathListItem {
-    fn clean(&self, cx: &DocContext) -> ViewListIdent {
-        ViewListIdent {
-            name: self.node.name.clean(cx),
-            rename: self.node.rename.map(|r| r.clean(cx)),
-            source: resolve_def(cx, self.node.id)
-        }
-    }
-}
-
 impl Clean<Vec<Item>> for hir::ForeignMod {
     fn clean(&self, cx: &DocContext) -> Vec<Item> {
         let mut items = self.items.clean(cx);
index 609ae0c0e6daf60f9cee7a8bc22d1cb0c4d4bc5c..21fc135eaadae7c0822de78e97d2130bce50702e 100644 (file)
@@ -254,10 +254,12 @@ pub struct ExternCrate {
 }
 
 pub struct Import {
+    pub name: Name,
     pub id: NodeId,
     pub vis: hir::Visibility,
     pub attrs: hir::HirVec<ast::Attribute>,
-    pub node: hir::ViewPath_,
+    pub path: hir::Path,
+    pub glob: bool,
     pub whence: Span,
 }
 
index eef530081abe358b00ec2da39f707682f4fc76f1..aed41916f5c536594c73d9f557e681e36bf832af 100644 (file)
@@ -969,16 +969,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             clean::Import::Glob(ref src) => {
                 write!(f, "use {}::*;", *src)
             }
-            clean::Import::List(ref src, ref names) => {
-                write!(f, "use {}::{{", *src)?;
-                for (i, n) in names.iter().enumerate() {
-                    if i > 0 {
-                        write!(f, ", ")?;
-                    }
-                    write!(f, "{}", *n)?;
-                }
-                write!(f, "}};")
-            }
         }
     }
 }
@@ -1000,23 +990,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-impl fmt::Display for clean::ViewListIdent {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self.source {
-            Some(did) => {
-                let path = clean::Path::singleton(self.name.clone());
-                resolved_path(f, did, &path, false)?;
-            }
-            _ => write!(f, "{}", self.name)?,
-        }
-
-        if let Some(ref name) = self.rename {
-            write!(f, " as {}", name)?;
-        }
-        Ok(())
-    }
-}
-
 impl fmt::Display for clean::TypeBinding {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         if f.alternate() {
index 8ed0567d820ac4af27ea5df04f26f3700374e3ee..fcf747a7c1796a4d0700da845e07261787ba52a0 100644 (file)
@@ -225,42 +225,6 @@ pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<ast::Attribu
         om
     }
 
-    fn visit_view_path(&mut self, path: hir::ViewPath_,
-                       om: &mut Module,
-                       id: ast::NodeId,
-                       please_inline: bool) -> Option<hir::ViewPath_> {
-        match path {
-            hir::ViewPathSimple(dst, base) => {
-                if self.maybe_inline_local(id, Some(dst), false, om, please_inline) {
-                    None
-                } else {
-                    Some(hir::ViewPathSimple(dst, base))
-                }
-            }
-            hir::ViewPathList(p, paths) => {
-                let mine = paths.into_iter().filter(|path| {
-                    !self.maybe_inline_local(path.node.id, path.node.rename,
-                                             false, om, please_inline)
-                }).collect::<hir::HirVec<hir::PathListItem>>();
-
-                if mine.is_empty() {
-                    None
-                } else {
-                    Some(hir::ViewPathList(p, mine))
-                }
-            }
-
-            hir::ViewPathGlob(base) => {
-                if self.maybe_inline_local(id, None, true, om, please_inline) {
-                    None
-                } else {
-                    Some(hir::ViewPathGlob(base))
-                }
-            }
-        }
-
-    }
-
     /// Tries to resolve the target of a `pub use` statement and inlines the
     /// target if it is defined locally and would not be documented otherwise,
     /// or when it is specifically requested with `please_inline`.
@@ -388,11 +352,13 @@ pub fn visit_item(&mut self, item: &hir::Item,
                     whence: item.span,
                 })
             }
-            hir::ItemUse(ref vpath) => {
-                let node = vpath.node.clone();
+            hir::ItemUse(_, hir::UseKind::ListStem) => {}
+            hir::ItemUse(ref path, kind) => {
+                let is_glob = kind == hir::UseKind::Glob;
+
                 // If there was a private module in the current path then don't bother inlining
                 // anything as it will probably be stripped anyway.
-                let node = if item.vis == hir::Public && self.inside_public_path {
+                if item.vis == hir::Public && self.inside_public_path {
                     let please_inline = item.attrs.iter().any(|item| {
                         match item.meta_item_list() {
                             Some(list) if item.check_name("doc") => {
@@ -401,18 +367,19 @@ pub fn visit_item(&mut self, item: &hir::Item,
                             _ => false,
                         }
                     });
-                    match self.visit_view_path(node, om, item.id, please_inline) {
-                        None => return,
-                        Some(p) => p
+                    let name = if is_glob { None } else { Some(name) };
+                    if self.maybe_inline_local(item.id, name, is_glob, om, please_inline) {
+                        return;
                     }
-                } else {
-                    node
-                };
+                }
+
                 om.imports.push(Import {
+                    name: item.name,
                     id: item.id,
                     vis: item.vis.clone(),
                     attrs: item.attrs.clone(),
-                    node: node,
+                    path: (**path).clone(),
+                    glob: is_glob,
                     whence: item.span,
                 });
             }
index ccc0acab7f379bc6c6ef8508f1b646e50ecd322e..4b6843d33f7ac367dac45ea5b5122b3ac335ce46 100644 (file)
@@ -21,8 +21,11 @@ pub enum Maybe<A> {
 
 // @has foo/prelude/index.html
 pub mod prelude {
-    // @has foo/prelude/index.html '//code' 'pub use io::{self as FooIo, Reader as FooReader}'
+    // @has foo/prelude/index.html '//code' 'pub use io as FooIo;'
+    // @has foo/prelude/index.html '//code' 'pub use io::Reader as FooReader;'
     #[doc(no_inline)] pub use io::{self as FooIo, Reader as FooReader};
-    // @has foo/prelude/index.html '//code' 'pub use Maybe::{self, Just as MaybeJust, Nothing}'
+    // @has foo/prelude/index.html '//code' 'pub use Maybe;'
+    // @has foo/prelude/index.html '//code' 'pub use Maybe::Just as MaybeJust;'
+    // @has foo/prelude/index.html '//code' 'pub use Maybe::Nothing;'
     #[doc(no_inline)] pub use Maybe::{self, Just as MaybeJust, Nothing};
 }
index 65a981353f0df6f0e3d2cf8d16b2785fa2159b2e..000960ad972abf867eeedb2e18c797a1615227da 100644 (file)
@@ -21,8 +21,11 @@ pub enum Maybe<A> {
 
 // @has foo/prelude/index.html
 pub mod prelude {
-    // @has foo/prelude/index.html '//code' 'pub use io::{self, Reader}'
+    // @has foo/prelude/index.html '//code' 'pub use io;'
+    // @has foo/prelude/index.html '//code' 'pub use io::Reader;'
     #[doc(no_inline)] pub use io::{self, Reader};
-    // @has foo/prelude/index.html '//code' 'pub use Maybe::{self, Just, Nothing}'
+    // @has foo/prelude/index.html '//code' 'pub use Maybe;'
+    // @has foo/prelude/index.html '//code' 'pub use Maybe::Just;'
+    // @has foo/prelude/index.html '//code' 'pub use Maybe::Nothing;'
     #[doc(no_inline)] pub use Maybe::{self, Just, Nothing};
 }