Skip to content

Commit

Permalink
Refactor how global paths are represented (for both ast and hir).
Browse files Browse the repository at this point in the history
  • Loading branch information
jseyfried committed Dec 22, 2016
1 parent 164619a commit f10f50b
Show file tree
Hide file tree
Showing 27 changed files with 242 additions and 257 deletions.
46 changes: 22 additions & 24 deletions src/librustc/hir/lowering.rs
Expand Up @@ -81,7 +81,7 @@ pub struct LoweringContext<'a> {
}

pub trait Resolver {
// Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
// Resolve a hir path generated by the lowerer when expanding `for`, `if let`, etc.
fn resolve_hir_path(&mut self, path: &mut hir::Path, is_value: bool);

// Obtain the resolution for a node id
Expand Down Expand Up @@ -337,7 +337,6 @@ impl<'a> LoweringContext<'a> {

let proj_start = p.segments.len() - resolution.depth;
let path = P(hir::Path {
global: p.global,
def: resolution.base_def,
segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
let param_mode = match (qself_position, param_mode) {
Expand Down Expand Up @@ -404,12 +403,17 @@ impl<'a> LoweringContext<'a> {
id: NodeId,
p: &Path,
name: Option<Name>,
param_mode: ParamMode)
param_mode: ParamMode,
defaults_to_global: bool)
-> hir::Path {
let mut segments = p.segments.iter();
if defaults_to_global && p.is_global() {
segments.next();
}

hir::Path {
global: p.global,
def: self.expect_full_def(id),
segments: p.segments.iter().map(|segment| {
segments: segments.map(|segment| {
self.lower_path_segment(segment, param_mode)
}).chain(name.map(|name| {
hir::PathSegment {
Expand All @@ -424,9 +428,10 @@ impl<'a> LoweringContext<'a> {
fn lower_path(&mut self,
id: NodeId,
p: &Path,
param_mode: ParamMode)
param_mode: ParamMode,
defaults_to_global: bool)
-> hir::Path {
self.lower_path_extra(id, p, None, param_mode)
self.lower_path_extra(id, p, None, param_mode, defaults_to_global)
}

fn lower_path_segment(&mut self,
Expand Down Expand Up @@ -602,8 +607,8 @@ impl<'a> LoweringContext<'a> {
// Check if the where clause type is a plain type parameter.
match bound_pred.bounded_ty.node {
TyKind::Path(None, ref path)
if !path.global && path.segments.len() == 1 &&
bound_pred.bound_lifetimes.is_empty() => {
if path.segments.len() == 1 &&
bound_pred.bound_lifetimes.is_empty() => {
if let Some(Def::TyParam(def_id)) =
self.resolver.get_resolution(bound_pred.bounded_ty.id)
.map(|d| d.base_def) {
Expand Down Expand Up @@ -677,7 +682,7 @@ impl<'a> LoweringContext<'a> {
span}) => {
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
id: id,
path: self.lower_path(id, path, ParamMode::Explicit),
path: self.lower_path(id, path, ParamMode::Explicit, false),
ty: self.lower_ty(ty),
span: span,
})
Expand Down Expand Up @@ -707,7 +712,7 @@ impl<'a> LoweringContext<'a> {

fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
hir::TraitRef {
path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit),
path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit, false),
ref_id: p.ref_id,
}
}
Expand Down Expand Up @@ -800,7 +805,7 @@ impl<'a> LoweringContext<'a> {
};

let mut path = self.lower_path_extra(import.id, path, suffix,
ParamMode::Explicit);
ParamMode::Explicit, true);
path.span = span;
self.items.insert(import.id, hir::Item {
id: import.id,
Expand All @@ -814,7 +819,7 @@ impl<'a> LoweringContext<'a> {
path
}
};
let path = P(self.lower_path(id, path, ParamMode::Explicit));
let path = P(self.lower_path(id, path, ParamMode::Explicit, true));
let kind = match view_path.node {
ViewPathSimple(ident, _) => {
*name = ident.name;
Expand Down Expand Up @@ -1135,7 +1140,6 @@ impl<'a> LoweringContext<'a> {
Some(def) => {
hir::PatKind::Path(hir::QPath::Resolved(None, P(hir::Path {
span: pth1.span,
global: false,
def: def,
segments: hir_vec![
hir::PathSegment::from_name(pth1.node.name)
Expand Down Expand Up @@ -1878,7 +1882,7 @@ impl<'a> LoweringContext<'a> {
Visibility::Crate(_) => hir::Visibility::Crate,
Visibility::Restricted { ref path, id } => {
hir::Visibility::Restricted {
path: P(self.lower_path(id, path, ParamMode::Explicit)),
path: P(self.lower_path(id, path, ParamMode::Explicit, true)),
id: id
}
}
Expand Down Expand Up @@ -1971,7 +1975,6 @@ impl<'a> LoweringContext<'a> {

let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(hir::Path {
span: span,
global: false,
def: def,
segments: hir_vec![hir::PathSegment::from_name(id)],
})));
Expand Down Expand Up @@ -2139,17 +2142,12 @@ impl<'a> LoweringContext<'a> {
/// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
/// The path is also resolved according to `is_value`.
fn std_path(&mut self, span: Span, components: &[&str], is_value: bool) -> hir::Path {
let idents = self.crate_root.iter().chain(components);

let segments: Vec<_> = idents.map(|name| {
hir::PathSegment::from_name(Symbol::intern(name))
}).collect();

let mut path = hir::Path {
span: span,
global: true,
def: Def::Err,
segments: segments.into(),
segments: iter::once(keywords::CrateRoot.name()).chain({
self.crate_root.into_iter().chain(components.iter().cloned()).map(Symbol::intern)
}).map(hir::PathSegment::from_name).collect(),
};

self.resolver.resolve_hir_path(&mut path, is_value);
Expand Down
9 changes: 6 additions & 3 deletions src/librustc/hir/mod.rs
Expand Up @@ -105,15 +105,18 @@ pub struct LifetimeDef {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]
pub struct Path {
pub span: Span,
/// A `::foo` path, is relative to the crate root rather than current
/// module (like paths in an import).
pub global: bool,
/// The definition that the path resolved to.
pub def: Def,
/// The segments in the path: the things separated by `::`.
pub segments: HirVec<PathSegment>,
}

impl Path {
pub fn is_global(&self) -> bool {
!self.segments.is_empty() && self.segments[0].name == keywords::CrateRoot.name()
}
}

impl fmt::Debug for Path {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "path({})", print::path_to_string(self))
Expand Down
28 changes: 12 additions & 16 deletions src/librustc/hir/print.rs
Expand Up @@ -1643,17 +1643,14 @@ impl<'a> State<'a> {
-> io::Result<()> {
self.maybe_print_comment(path.span.lo)?;

let mut first = !path.global;
for segment in &path.segments {
if first {
first = false
} else {
for (i, segment) in path.segments.iter().enumerate() {
if i > 0 {
word(&mut self.s, "::")?
}

self.print_name(segment.name)?;

self.print_path_parameters(&segment.parameters, colons_before_params)?;
if segment.name != keywords::CrateRoot.name() {
self.print_name(segment.name)?;
self.print_path_parameters(&segment.parameters, colons_before_params)?;
}
}

Ok(())
Expand All @@ -1673,15 +1670,14 @@ impl<'a> State<'a> {
space(&mut self.s)?;
self.word_space("as")?;

let mut first = !path.global;
for segment in &path.segments[..path.segments.len() - 1] {
if first {
first = false
} else {
for (i, segment) in path.segments[..path.segments.len() - 1].iter().enumerate() {
if i > 0 {
word(&mut self.s, "::")?
}
self.print_name(segment.name)?;
self.print_path_parameters(&segment.parameters, colons_before_params)?;
if segment.name != keywords::CrateRoot.name() {
self.print_name(segment.name)?;
self.print_path_parameters(&segment.parameters, colons_before_params)?;
}
}

word(&mut self.s, ">")?;
Expand Down
1 change: 0 additions & 1 deletion src/librustc/infer/error_reporting.rs
Expand Up @@ -1620,7 +1620,6 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
new_segs.push(new_seg);
hir::Path {
span: path.span,
global: path.global,
def: path.def,
segments: new_segs.into()
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc_const_eval/_match.rs
Expand Up @@ -324,7 +324,6 @@ impl Witness {
let v = ctor.variant_for_adt(adt);
let qpath = hir::QPath::Resolved(None, P(hir::Path {
span: DUMMY_SP,
global: false,
def: Def::Err,
segments: vec![hir::PathSegment::from_name(v.name)].into(),
}));
Expand Down
2 changes: 0 additions & 2 deletions src/librustc_incremental/calculate_svh/svh_visitor.rs
Expand Up @@ -189,7 +189,6 @@ enum SawAbiComponent<'a> {
SawStructField,
SawVariant,
SawQPath,
SawPath(bool),
SawPathSegment,
SawPathParameters,
SawBlock,
Expand Down Expand Up @@ -678,7 +677,6 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has

fn visit_path(&mut self, path: &'tcx Path, _: ast::NodeId) {
debug!("visit_path: st={:?}", self.st);
SawPath(path.global).hash(self.st);
hash_span!(self, path.span);
visit::walk_path(self, path)
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_lint/bad_style.rs
Expand Up @@ -382,7 +382,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
// Lint for constants that look like binding identifiers (#7526)
if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.node {
if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
if path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
if let Def::Const(..) = path.def {
NonUpperCaseGlobals::check_upper_case(cx,
"constant in pattern",
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_passes/ast_validation.rs
Expand Up @@ -154,8 +154,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
}

fn visit_path(&mut self, path: &'a Path, id: NodeId) {
if path.global && path.segments.len() > 0 {
let ident = path.segments[0].identifier;
if path.segments.len() >= 2 && path.is_global() {
let ident = path.segments[1].identifier;
if token::Ident(ident).is_path_segment_keyword() {
self.session.add_lint(lint::builtin::SUPER_OR_SELF_IN_GLOBAL_PATH,
id,
Expand Down
31 changes: 18 additions & 13 deletions src/librustc_resolve/build_reduced_graph.rs
Expand Up @@ -40,6 +40,7 @@ use syntax::ext::base::Determinacy::Undetermined;
use syntax::ext::expand::mark_tts;
use syntax::ext::hygiene::Mark;
use syntax::ext::tt::macro_rules;
use syntax::parse::token;
use syntax::symbol::keywords;
use syntax::visit::{self, Visitor};

Expand Down Expand Up @@ -112,7 +113,7 @@ impl<'a> Resolver<'a> {
// Extract and intern the module part of the path. For
// globs and lists, the path is found directly in the AST;
// for simple paths we have to munge the path a little.
let module_path: Vec<_> = match view_path.node {
let mut module_path: Vec<_> = match view_path.node {
ViewPathSimple(_, ref full_path) => {
full_path.segments
.split_last()
Expand All @@ -132,6 +133,12 @@ impl<'a> Resolver<'a> {
}
};

// This can be removed once warning cycle #36888 is complete.
if module_path.len() >= 2 && module_path[0].name == keywords::CrateRoot.name() &&
token::Ident(module_path[1]).is_path_segment_keyword() {
module_path.remove(0);
}

// Build up the import directives.
let is_prelude = attr::contains_name(&item.attrs, "prelude_import");

Expand Down Expand Up @@ -193,18 +200,16 @@ impl<'a> Resolver<'a> {
let rename = node.rename.unwrap_or(node.name);
(module_path.clone(), node.name, rename)
} else {
let ident = match module_path.last() {
Some(&ident) => ident,
None => {
resolve_error(
self,
source_item.span,
ResolutionError::
SelfImportOnlyInImportListWithNonEmptyPrefix
);
continue;
}
};
let ident = *module_path.last().unwrap();
if ident.name == keywords::CrateRoot.name() {
resolve_error(
self,
source_item.span,
ResolutionError::
SelfImportOnlyInImportListWithNonEmptyPrefix
);
continue;
}
let module_path = module_path.split_last().unwrap().1;
let rename = node.rename.unwrap_or(ident);
(module_path.to_vec(), ident, rename)
Expand Down

0 comments on commit f10f50b

Please sign in to comment.