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, _) => {
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)
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)
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,
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 {
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 {
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 => {
.cloned()
.collect(),
span: path.span,
- }, ParamMode::Explicit, true));
+ }, ParamMode::Explicit));
hir::ItemUse(path, hir::UseKind::Glob)
}
UseTreeKind::Nested(ref trees) => {
// 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)
}
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 {
#[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;`
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()?;
}
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),
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
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,
),
];
});
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)
});
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",
!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",
// 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 => {
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,
};
};
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();
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,
})
}
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,
.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;
// 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;
}
}
ModuleKind::Block(..) => unreachable!(),
};
source.name = crate_name;
- if ident.name == keywords::DollarCrate.name() {
+ if rename.is_none() {
ident.name = crate_name;
}
// 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);
}
}
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,
};
);
}
- 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
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),
// 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;
}
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());
}
}
}
}
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);
None,
&path,
trait_ref.path.span,
- trait_ref.path.segments.last().unwrap().span,
PathSource::Trait(AliasPossibility::No)
).base_def();
if def != Def::Err {
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,
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 };
// 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
));
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 {
}
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));
}
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(
.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()
// 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;
}
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());
}
}
}
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",
// 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,
}
}
- // 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 {
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.
#[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>),
ty,
expr,
),
- vis: codemap::respan(span.empty(), ast::VisibilityKind::Public),
+ vis: codemap::respan(span.shrink_to_lo(), ast::VisibilityKind::Public),
span,
tokens: None,
})
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,
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.
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,
})
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,
}
}
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),
}))
}
(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();
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,
})));
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)
}
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");
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))
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)))
}
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,
// 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);
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)]
}),
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()))
}
}
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)?;
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(());
}
}
// `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),
{
// `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),
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
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));
}
}))
}
- /// `{` 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)
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))
})
}
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,
}
}
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 {
&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)?
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()?;
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)?;
}
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(
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 {
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) => {
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()?;
}
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()?;
}
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()?;
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()?,
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(
}
}
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)?
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("::")?
}
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("::")?;
}
}
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))?;
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(
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("*")?;
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, _)| {
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") {
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,
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,
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 =
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 {
(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 {
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 {
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) => {
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) => {
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(),
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 {
asm,
ctxt: cx.backtrace(),
})),
- vis: respan(sp.empty(), ast::VisibilityKind::Inherited),
+ vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
span: sp,
tokens: None,
})))
/// 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.
// 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;
}