Skip to content

[7/n] rustc: desugar UFCS in HIR and don't use DefMap for associated resolutions. #37676

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Nov 28, 2016
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/etc/generate-deriving-span-tests.py
Original file line number Diff line number Diff line change
@@ -37,8 +37,6 @@
// This file was auto-generated using 'src/etc/generate-deriving-span-tests.py'
extern crate rand;
{error_deriving}
struct Error;
{code}
@@ -106,7 +104,6 @@ def write_file(name, string):
ALL = STRUCT | ENUM

traits = {
'Zero': (STRUCT, [], 1),
'Default': (STRUCT, [], 1),
'FromPrimitive': (0, [], 0), # only works for C-like enums

@@ -116,7 +113,7 @@ def write_file(name, string):

for (trait, supers, errs) in [('Clone', [], 1),
('PartialEq', [], 2),
('PartialOrd', ['PartialEq'], 8),
('PartialOrd', ['PartialEq'], 9),
('Eq', ['PartialEq'], 1),
('Ord', ['Eq', 'PartialOrd', 'PartialEq'], 1),
('Debug', [], 1),
31 changes: 11 additions & 20 deletions src/librustc/cfg/construct.rs
Original file line number Diff line number Diff line change
@@ -10,8 +10,6 @@

use rustc_data_structures::graph;
use cfg::*;
use hir::def::Def;
use hir::pat_util;
use ty::{self, TyCtxt};
use syntax::ast;
use syntax::ptr::P;
@@ -100,7 +98,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
match pat.node {
PatKind::Binding(.., None) |
PatKind::Path(..) |
PatKind::Path(_) |
PatKind::Lit(..) |
PatKind::Range(..) |
PatKind::Wild => {
@@ -284,15 +282,15 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {

hir::ExprBreak(label, ref opt_expr) => {
let v = self.opt_expr(opt_expr, pred);
let loop_scope = self.find_scope(expr, label.map(|l| l.node));
let loop_scope = self.find_scope(expr, label);
let b = self.add_ast_node(expr.id, &[v]);
self.add_exiting_edge(expr, b,
loop_scope, loop_scope.break_index);
self.add_unreachable_node()
}

hir::ExprAgain(label) => {
let loop_scope = self.find_scope(expr, label.map(|l| l.node));
let loop_scope = self.find_scope(expr, label);
let a = self.add_ast_node(expr.id, &[pred]);
self.add_exiting_edge(expr, a,
loop_scope, loop_scope.continue_index);
@@ -361,7 +359,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {

hir::ExprClosure(..) |
hir::ExprLit(..) |
hir::ExprPath(..) => {
hir::ExprPath(_) => {
self.straightline(expr, pred, None::<hir::Expr>.iter())
}
}
@@ -457,7 +455,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
// Visit the guard expression
let guard_exit = self.expr(&guard, guard_start);

let this_has_bindings = pat_util::pat_contains_bindings_or_wild(&pat);
let this_has_bindings = pat.contains_bindings_or_wild();

// If both this pattern and the previous pattern
// were free of bindings, they must consist only
@@ -570,23 +568,16 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {

fn find_scope(&self,
expr: &hir::Expr,
label: Option<ast::Name>) -> LoopScope {
if label.is_none() {
return *self.loop_scopes.last().unwrap();
}

match self.tcx.expect_def(expr.id) {
Def::Label(loop_id) => {
label: Option<hir::Label>) -> LoopScope {
match label {
None => *self.loop_scopes.last().unwrap(),
Some(label) => {
for l in &self.loop_scopes {
if l.loop_id == loop_id {
if l.loop_id == label.loop_id {
return *l;
}
}
span_bug!(expr.span, "no loop scope for id {}", loop_id);
}

r => {
span_bug!(expr.span, "bad entry `{:?}` in def_map for label", r);
span_bug!(expr.span, "no loop scope for id {}", label.loop_id);
}
}
}
4 changes: 2 additions & 2 deletions src/librustc/dep_graph/dep_node.rs
Original file line number Diff line number Diff line change
@@ -90,7 +90,7 @@ pub enum DepNode<D: Clone + Debug> {
RvalueCheck(D),
Reachability,
DeadCheck,
StabilityCheck,
StabilityCheck(D),
LateLintCheck,
TransCrate,
TransCrateItem(D),
@@ -189,7 +189,6 @@ impl<D: Clone + Debug> DepNode<D> {
Privacy => Some(Privacy),
Reachability => Some(Reachability),
DeadCheck => Some(DeadCheck),
StabilityCheck => Some(StabilityCheck),
LateLintCheck => Some(LateLintCheck),
TransCrate => Some(TransCrate),
TransWriteMetadata => Some(TransWriteMetadata),
@@ -217,6 +216,7 @@ impl<D: Clone + Debug> DepNode<D> {
Mir(ref d) => op(d).map(Mir),
BorrowCheck(ref d) => op(d).map(BorrowCheck),
RvalueCheck(ref d) => op(d).map(RvalueCheck),
StabilityCheck(ref d) => op(d).map(StabilityCheck),
TransCrateItem(ref d) => op(d).map(TransCrateItem),
TransInlinedItem(ref d) => op(d).map(TransInlinedItem),
AssociatedItems(ref d) => op(d).map(AssociatedItems),
8 changes: 0 additions & 8 deletions src/librustc/hir/def.rs
Original file line number Diff line number Diff line change
@@ -83,14 +83,6 @@ impl PathResolution {
PathResolution { base_def: def, depth: 0 }
}

/// Get the definition, if fully resolved, otherwise panic.
pub fn full_def(&self) -> Def {
if self.depth != 0 {
bug!("path not fully resolved: {:?}", self);
}
self.base_def
}

pub fn kind_name(&self) -> &'static str {
if self.depth != 0 {
"associated item"
102 changes: 49 additions & 53 deletions src/librustc/hir/intravisit.rs
Original file line number Diff line number Diff line change
@@ -38,6 +38,7 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
use syntax::codemap::Spanned;
use syntax_pos::Span;
use hir::*;
use hir::def::Def;
use hir::map::Map;
use super::itemlikevisit::DeepVisitor;

@@ -155,6 +156,9 @@ pub trait Visitor<'v> : Sized {
fn visit_id(&mut self, _node_id: NodeId) {
// Nothing to do.
}
fn visit_def_mention(&mut self, _def: Def) {
// Nothing to do.
}
fn visit_name(&mut self, _span: Span, _name: Name) {
// Nothing to do.
}
@@ -244,12 +248,12 @@ pub trait Visitor<'v> : Sized {
fn visit_lifetime_def(&mut self, lifetime: &'v LifetimeDef) {
walk_lifetime_def(self, lifetime)
}
fn visit_qpath(&mut self, qpath: &'v QPath, id: NodeId, span: Span) {
walk_qpath(self, qpath, id, 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)
}
@@ -349,23 +353,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) => {
@@ -481,11 +471,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
walk_fn_decl(visitor, &function_declaration.decl);
walk_list!(visitor, visit_lifetime_def, &function_declaration.lifetimes);
}
TyPath(ref maybe_qself, ref path) => {
if let Some(ref qself) = *maybe_qself {
visitor.visit_ty(&qself.ty);
}
visitor.visit_path(path, typ.id);
TyPath(ref qpath) => {
visitor.visit_qpath(qpath, typ.id, typ.span);
}
TyObjectSum(ref ty, ref bounds) => {
visitor.visit_ty(ty);
@@ -508,20 +495,28 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
}
}

pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: NodeId, span: Span) {
match *qpath {
QPath::Resolved(ref maybe_qself, ref path) => {
if let Some(ref qself) = *maybe_qself {
visitor.visit_ty(qself);
}
visitor.visit_path(path, id)
}
QPath::TypeRelative(ref qself, ref segment) => {
visitor.visit_ty(qself);
visitor.visit_path_segment(span, segment);
}
}
}

pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
visitor.visit_def_mention(path.def);
for segment in &path.segments {
visitor.visit_path_segment(path.span, segment);
}
}

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) {
@@ -555,18 +550,15 @@ pub fn walk_assoc_type_binding<'v, V: Visitor<'v>>(visitor: &mut V,
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
visitor.visit_id(pattern.id);
match pattern.node {
PatKind::TupleStruct(ref path, ref children, _) => {
visitor.visit_path(path, pattern.id);
PatKind::TupleStruct(ref qpath, ref children, _) => {
visitor.visit_qpath(qpath, pattern.id, pattern.span);
walk_list!(visitor, visit_pat, children);
}
PatKind::Path(ref opt_qself, ref path) => {
if let Some(ref qself) = *opt_qself {
visitor.visit_ty(&qself.ty);
}
visitor.visit_path(path, pattern.id)
PatKind::Path(ref qpath) => {
visitor.visit_qpath(qpath, pattern.id, pattern.span);
}
PatKind::Struct(ref path, ref fields, _) => {
visitor.visit_path(path, pattern.id);
PatKind::Struct(ref qpath, ref fields, _) => {
visitor.visit_qpath(qpath, pattern.id, pattern.span);
for field in fields {
visitor.visit_name(field.span, field.node.name);
visitor.visit_pat(&field.node.pat)
@@ -579,7 +571,8 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
PatKind::Ref(ref subpattern, _) => {
visitor.visit_pat(subpattern)
}
PatKind::Binding(_, ref pth1, ref optional_subpattern) => {
PatKind::Binding(_, def_id, ref pth1, ref optional_subpattern) => {
visitor.visit_def_mention(Def::Local(def_id));
visitor.visit_name(pth1.span, pth1.node);
walk_list!(visitor, visit_pat, optional_subpattern);
}
@@ -840,8 +833,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_expr(element);
visitor.visit_expr(count)
}
ExprStruct(ref path, ref fields, ref optional_base) => {
visitor.visit_path(path, expression.id);
ExprStruct(ref qpath, ref fields, ref optional_base) => {
visitor.visit_qpath(qpath, expression.id, expression.span);
for field in fields {
visitor.visit_name(field.name.span, field.name.node);
visitor.visit_expr(&field.expr)
@@ -917,18 +910,21 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
visitor.visit_expr(main_expression);
visitor.visit_expr(index_expression)
}
ExprPath(ref maybe_qself, ref path) => {
if let Some(ref qself) = *maybe_qself {
visitor.visit_ty(&qself.ty);
}
visitor.visit_path(path, expression.id)
ExprPath(ref qpath) => {
visitor.visit_qpath(qpath, expression.id, expression.span);
}
ExprBreak(ref opt_sp_name, ref opt_expr) => {
walk_opt_sp_name(visitor, opt_sp_name);
ExprBreak(None, ref opt_expr) => {
walk_list!(visitor, visit_expr, opt_expr);
}
ExprAgain(ref opt_sp_name) => {
walk_opt_sp_name(visitor, opt_sp_name);
ExprBreak(Some(label), ref opt_expr) => {
visitor.visit_def_mention(Def::Label(label.loop_id));
visitor.visit_name(label.span, label.name);
walk_list!(visitor, visit_expr, opt_expr);
}
ExprAgain(None) => {}
ExprAgain(Some(label)) => {
visitor.visit_def_mention(Def::Label(label.loop_id));
visitor.visit_name(label.span, label.name);
}
ExprRet(ref optional_expression) => {
walk_list!(visitor, visit_expr, optional_expression);
725 changes: 418 additions & 307 deletions src/librustc/hir/lowering.rs

Large diffs are not rendered by default.

46 changes: 29 additions & 17 deletions src/librustc/hir/map/collector.rs
Original file line number Diff line number Diff line change
@@ -124,23 +124,6 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
this.insert(struct_def.id(), NodeStructCtor(struct_def));
}
}
ItemTrait(.., ref bounds, _) => {
for b in bounds.iter() {
if let TraitTyParamBound(ref t, TraitBoundModifier::None) = *b {
this.insert(t.trait_ref.ref_id, NodeItem(i));
}
}
}
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);
@@ -217,6 +200,14 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
});
}

fn visit_trait_ref(&mut self, tr: &'ast TraitRef) {
self.insert(tr.ref_id, NodeTraitRef(tr));

self.with_parent(tr.ref_id, |this| {
intravisit::walk_trait_ref(this, tr);
});
}

fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl,
b: &'ast Expr, s: Span, id: NodeId) {
assert_eq!(self.parent_node, id);
@@ -234,7 +225,28 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
self.insert(lifetime.id, NodeLifetime(lifetime));
}

fn visit_vis(&mut self, visibility: &'ast Visibility) {
match *visibility {
Visibility::Public |
Visibility::Crate |
Visibility::Inherited => {}
Visibility::Restricted { id, .. } => {
self.insert(id, NodeVisibility(visibility));
self.with_parent(id, |this| {
intravisit::walk_vis(this, visibility);
});
}
}
}

fn visit_macro_def(&mut self, macro_def: &'ast MacroDef) {
self.insert_entry(macro_def.id, NotPresent);
}

fn visit_struct_field(&mut self, field: &'ast StructField) {
self.insert(field.id, NodeField(field));
self.with_parent(field.id, |this| {
intravisit::walk_struct_field(this, field);
});
}
}
17 changes: 15 additions & 2 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
@@ -155,7 +155,20 @@ impl<'a> visit::Visitor for DefCollector<'a> {
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);

@@ -423,7 +436,7 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
fn visit_pat(&mut self, pat: &'ast hir::Pat) {
let parent_def = self.parent_def;

if let hir::PatKind::Binding(_, name, _) = pat.node {
if let hir::PatKind::Binding(_, _, name, _) = pat.node {
let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str()));
self.parent_def = Some(def);
}
62 changes: 48 additions & 14 deletions src/librustc/hir/map/mod.rs
Original file line number Diff line number Diff line change
@@ -46,9 +46,11 @@ pub enum Node<'ast> {
NodeTraitItem(&'ast TraitItem),
NodeImplItem(&'ast ImplItem),
NodeVariant(&'ast Variant),
NodeField(&'ast StructField),
NodeExpr(&'ast Expr),
NodeStmt(&'ast Stmt),
NodeTy(&'ast Ty),
NodeTraitRef(&'ast TraitRef),
NodeLocal(&'ast Pat),
NodePat(&'ast Pat),
NodeBlock(&'ast Block),
@@ -57,7 +59,8 @@ pub enum Node<'ast> {
NodeStructCtor(&'ast VariantData),

NodeLifetime(&'ast Lifetime),
NodeTyParam(&'ast TyParam)
NodeTyParam(&'ast TyParam),
NodeVisibility(&'ast Visibility),
}

/// Represents an entry and its parent NodeID.
@@ -73,15 +76,18 @@ pub enum MapEntry<'ast> {
EntryTraitItem(NodeId, &'ast TraitItem),
EntryImplItem(NodeId, &'ast ImplItem),
EntryVariant(NodeId, &'ast Variant),
EntryField(NodeId, &'ast StructField),
EntryExpr(NodeId, &'ast Expr),
EntryStmt(NodeId, &'ast Stmt),
EntryTy(NodeId, &'ast Ty),
EntryTraitRef(NodeId, &'ast TraitRef),
EntryLocal(NodeId, &'ast Pat),
EntryPat(NodeId, &'ast Pat),
EntryBlock(NodeId, &'ast Block),
EntryStructCtor(NodeId, &'ast VariantData),
EntryLifetime(NodeId, &'ast Lifetime),
EntryTyParam(NodeId, &'ast TyParam),
EntryVisibility(NodeId, &'ast Visibility),

/// Roots for node trees.
RootCrate,
@@ -102,15 +108,18 @@ impl<'ast> MapEntry<'ast> {
NodeTraitItem(n) => EntryTraitItem(p, n),
NodeImplItem(n) => EntryImplItem(p, n),
NodeVariant(n) => EntryVariant(p, n),
NodeField(n) => EntryField(p, n),
NodeExpr(n) => EntryExpr(p, n),
NodeStmt(n) => EntryStmt(p, n),
NodeTy(n) => EntryTy(p, n),
NodeTraitRef(n) => EntryTraitRef(p, n),
NodeLocal(n) => EntryLocal(p, n),
NodePat(n) => EntryPat(p, n),
NodeBlock(n) => EntryBlock(p, n),
NodeStructCtor(n) => EntryStructCtor(p, n),
NodeLifetime(n) => EntryLifetime(p, n),
NodeTyParam(n) => EntryTyParam(p, n),
NodeVisibility(n) => EntryVisibility(p, n),
}
}

@@ -121,15 +130,18 @@ impl<'ast> MapEntry<'ast> {
EntryTraitItem(id, _) => id,
EntryImplItem(id, _) => id,
EntryVariant(id, _) => id,
EntryField(id, _) => id,
EntryExpr(id, _) => id,
EntryStmt(id, _) => id,
EntryTy(id, _) => id,
EntryTraitRef(id, _) => id,
EntryLocal(id, _) => id,
EntryPat(id, _) => id,
EntryBlock(id, _) => id,
EntryStructCtor(id, _) => id,
EntryLifetime(id, _) => id,
EntryTyParam(id, _) => id,
EntryVisibility(id, _) => id,

NotPresent |
RootCrate |
@@ -144,15 +156,18 @@ impl<'ast> MapEntry<'ast> {
EntryTraitItem(_, n) => NodeTraitItem(n),
EntryImplItem(_, n) => NodeImplItem(n),
EntryVariant(_, n) => NodeVariant(n),
EntryField(_, n) => NodeField(n),
EntryExpr(_, n) => NodeExpr(n),
EntryStmt(_, n) => NodeStmt(n),
EntryTy(_, n) => NodeTy(n),
EntryTraitRef(_, n) => NodeTraitRef(n),
EntryLocal(_, n) => NodeLocal(n),
EntryPat(_, n) => NodePat(n),
EntryBlock(_, n) => NodeBlock(n),
EntryStructCtor(_, n) => NodeStructCtor(n),
EntryLifetime(_, n) => NodeLifetime(n),
EntryTyParam(_, n) => NodeTyParam(n),
EntryVisibility(_, n) => NodeVisibility(n),
_ => return None
})
}
@@ -240,16 +255,8 @@ impl<'ast> Map<'ast> {
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);
}
@@ -263,15 +270,18 @@ impl<'ast> Map<'ast> {
EntryForeignItem(p, _) |
EntryTraitItem(p, _) |
EntryVariant(p, _) |
EntryField(p, _) |
EntryExpr(p, _) |
EntryStmt(p, _) |
EntryTy(p, _) |
EntryTraitRef(p, _) |
EntryLocal(p, _) |
EntryPat(p, _) |
EntryBlock(p, _) |
EntryStructCtor(p, _) |
EntryLifetime(p, _) |
EntryTyParam(p, _) =>
EntryTyParam(p, _) |
EntryVisibility(p, _) =>
id = p,

RootCrate =>
@@ -304,15 +314,18 @@ impl<'ast> Map<'ast> {
EntryTraitItem(p, _) |
EntryImplItem(p, _) |
EntryVariant(p, _) |
EntryField(p, _) |
EntryExpr(p, _) |
EntryStmt(p, _) |
EntryTy(p, _) |
EntryTraitRef(p, _) |
EntryLocal(p, _) |
EntryPat(p, _) |
EntryBlock(p, _) |
EntryStructCtor(p, _) |
EntryLifetime(p, _) |
EntryTyParam(p, _) =>
EntryTyParam(p, _) |
EntryVisibility(p, _) =>
id = p,

RootInlinedParent(parent) => match *parent {
@@ -650,9 +663,10 @@ impl<'ast> Map<'ast> {
NodeImplItem(ii) => ii.name,
NodeTraitItem(ti) => ti.name,
NodeVariant(v) => v.node.name,
NodeField(f) => f.name,
NodeLifetime(lt) => lt.name,
NodeTyParam(tp) => tp.name,
NodeLocal(&Pat { node: PatKind::Binding(_,l,_), .. }) => l.node,
NodeLocal(&Pat { node: PatKind::Binding(_,_,l,_), .. }) => l.node,
NodeStructCtor(_) => self.name(self.get_parent(id)),
_ => bug!("no name for {}", self.node_to_string(id))
}
@@ -668,6 +682,7 @@ impl<'ast> Map<'ast> {
Some(NodeTraitItem(ref ti)) => Some(&ti.attrs[..]),
Some(NodeImplItem(ref ii)) => Some(&ii.attrs[..]),
Some(NodeVariant(ref v)) => Some(&v.node.attrs[..]),
Some(NodeField(ref f)) => Some(&f.attrs[..]),
Some(NodeExpr(ref e)) => Some(&*e.attrs),
Some(NodeStmt(ref s)) => Some(s.node.attrs()),
// unit/tuple structs take the attributes straight from
@@ -704,14 +719,17 @@ impl<'ast> Map<'ast> {
Some(NodeTraitItem(trait_method)) => trait_method.span,
Some(NodeImplItem(ref impl_item)) => impl_item.span,
Some(NodeVariant(variant)) => variant.span,
Some(NodeField(field)) => field.span,
Some(NodeExpr(expr)) => expr.span,
Some(NodeStmt(stmt)) => stmt.span,
Some(NodeTy(ty)) => ty.span,
Some(NodeTraitRef(tr)) => tr.path.span,
Some(NodeLocal(pat)) => pat.span,
Some(NodePat(pat)) => pat.span,
Some(NodeBlock(block)) => block.span,
Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
Some(NodeTyParam(ty_param)) => ty_param.span,
Some(NodeVisibility(&Visibility::Restricted { ref path, .. })) => path.span,
_ => return None,
};
Some(sp)
@@ -823,6 +841,7 @@ impl<'a, 'ast> Iterator for NodesMatchingSuffix<'a, 'ast> {
Some(EntryTraitItem(_, n)) => n.name(),
Some(EntryImplItem(_, n)) => n.name(),
Some(EntryVariant(_, n)) => n.name(),
Some(EntryField(_, n)) => n.name(),
_ => continue,
};
if self.matches_names(self.map.get_parent(idx), name) {
@@ -841,6 +860,7 @@ impl<T:Named> Named for Spanned<T> { fn name(&self) -> Name { self.node.name() }
impl Named for Item { fn name(&self) -> Name { self.name } }
impl Named for ForeignItem { fn name(&self) -> Name { self.name } }
impl Named for Variant_ { fn name(&self) -> Name { self.name } }
impl Named for StructField { fn name(&self) -> Name { self.name } }
impl Named for TraitItem { fn name(&self) -> Name { self.name } }
impl Named for ImplItem { fn name(&self) -> Name { self.name } }

@@ -926,10 +946,13 @@ impl<'a> NodePrinter for pprust::State<'a> {
NodeExpr(a) => self.print_expr(&a),
NodeStmt(a) => self.print_stmt(&a),
NodeTy(a) => self.print_type(&a),
NodeTraitRef(a) => self.print_trait_ref(&a),
NodePat(a) => self.print_pat(&a),
NodeBlock(a) => self.print_block(&a),
NodeLifetime(a) => self.print_lifetime(&a),
NodeVisibility(a) => self.print_visibility(&a),
NodeTyParam(_) => bug!("cannot print TyParam"),
NodeField(_) => bug!("cannot print StructField"),
// these cases do not carry enough information in the
// ast_map to reconstruct their full structure for pretty
// printing.
@@ -1009,6 +1032,11 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
variant.node.name,
path_str(), id_str)
}
Some(NodeField(ref field)) => {
format!("field {} in {}{}",
field.name,
path_str(), id_str)
}
Some(NodeExpr(ref expr)) => {
format!("expr {}{}", pprust::expr_to_string(&expr), id_str)
}
@@ -1018,6 +1046,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
Some(NodeTy(ref ty)) => {
format!("type {}{}", pprust::ty_to_string(&ty), id_str)
}
Some(NodeTraitRef(ref tr)) => {
format!("trait_ref {}{}", pprust::path_to_string(&tr.path), id_str)
}
Some(NodeLocal(ref pat)) => {
format!("local {}{}", pprust::pat_to_string(&pat), id_str)
}
@@ -1037,6 +1068,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
Some(NodeTyParam(ref ty_param)) => {
format!("typaram {:?}{}", ty_param, id_str)
}
Some(NodeVisibility(ref vis)) => {
format!("visibility {:?}{}", vis, id_str)
}
None => {
format!("unknown node{}", id_str)
}
168 changes: 86 additions & 82 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
@@ -27,7 +27,6 @@ pub use self::Ty_::*;
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::*;

@@ -108,6 +107,8 @@ pub struct Path {
/// 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>,
}
@@ -124,21 +125,6 @@ impl fmt::Display for Path {
}
}

impl Path {
/// Convert a span and an identifier to the corresponding
/// 1-segment path.
pub fn from_name(s: Span, name: Name) -> Path {
Path {
span: s,
global: false,
segments: hir_vec![PathSegment {
name: name,
parameters: PathParameters::none()
}],
}
}
}

/// A segment of a path: an identifier, an optional lifetime, and a set of
/// types.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
@@ -154,6 +140,16 @@ pub struct PathSegment {
pub parameters: PathParameters,
}

impl PathSegment {
/// Convert an identifier to the corresponding segment.
pub fn from_name(name: Name) -> PathSegment {
PathSegment {
name: name,
parameters: PathParameters::none()
}
}
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum PathParameters {
/// The `<'a, A,B,C>` in `foo::bar::baz::<'a, A,B,C>`
@@ -167,6 +163,7 @@ impl PathParameters {
AngleBracketedParameters(AngleBracketedParameterData {
lifetimes: HirVec::new(),
types: HirVec::new(),
infer_types: true,
bindings: HirVec::new(),
})
}
@@ -241,6 +238,11 @@ pub struct AngleBracketedParameterData {
pub lifetimes: HirVec<Lifetime>,
/// The type parameters for this path segment, if present.
pub types: HirVec<P<Ty>>,
/// Whether to infer remaining type parameters, if any.
/// This only applies to expression and pattern paths, and
/// out of those only the segments with no type parameters
/// to begin with, e.g. `Vec::new` is `<Vec<..>>::new::<..>`.
pub infer_types: bool,
/// Bindings (equality constraints) on associated types, if present.
/// E.g., `Foo<A=Bar>`.
pub bindings: HirVec<TypeBinding>,
@@ -527,7 +529,7 @@ impl Pat {
PatKind::Lit(_) |
PatKind::Range(..) |
PatKind::Binding(..) |
PatKind::Path(..) => {
PatKind::Path(_) => {
true
}
}
@@ -566,20 +568,20 @@ pub enum PatKind {
Wild,

/// A fresh binding `ref mut binding @ OPT_SUBPATTERN`.
Binding(BindingMode, Spanned<Name>, Option<P<Pat>>),
/// The `DefId` is for the definition of the variable being bound.
Binding(BindingMode, DefId, Spanned<Name>, Option<P<Pat>>),

/// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
/// The `bool` is `true` in the presence of a `..`.
Struct(Path, HirVec<Spanned<FieldPat>>, bool),
Struct(QPath, HirVec<Spanned<FieldPat>>, bool),

/// A tuple struct/variant pattern `Variant(x, y, .., z)`.
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
/// 0 <= position <= subpats.len()
TupleStruct(Path, HirVec<P<Pat>>, Option<usize>),
TupleStruct(QPath, HirVec<P<Pat>>, Option<usize>),

/// A possibly qualified path pattern.
/// Such pattern can be resolved to a unit struct/variant or a constant.
Path(Option<QSelf>, Path),
/// A path pattern for an unit struct/variant or a (maybe-associated) constant.
Path(QPath),

/// A tuple pattern `(a, b)`.
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
@@ -836,9 +838,6 @@ pub enum BlockCheckMode {
UnsafeBlock(UnsafeSource),
PushUnsafeBlock(UnsafeSource),
PopUnsafeBlock(UnsafeSource),
// Within this block (but outside a PopUnstableBlock), we suspend checking of stability.
PushUnstableBlock,
PopUnstableBlock,
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -934,19 +933,15 @@ pub enum Expr_ {
/// An indexing operation (`foo[2]`)
ExprIndex(P<Expr>, P<Expr>),

/// Variable reference, possibly containing `::` and/or type
/// parameters, e.g. foo::bar::<baz>.
///
/// Optionally "qualified",
/// e.g. `<HirVec<T> as SomeTrait>::SomeType`.
ExprPath(Option<QSelf>, Path),
/// Path to a definition, possibly containing lifetime or type parameters.
ExprPath(QPath),

/// A referencing operation (`&a` or `&mut a`)
ExprAddrOf(Mutability, P<Expr>),
/// A `break`, with an optional label to break
ExprBreak(Option<Spanned<Name>>, Option<P<Expr>>),
ExprBreak(Option<Label>, Option<P<Expr>>),
/// A `continue`, with an optional label
ExprAgain(Option<Spanned<Name>>),
ExprAgain(Option<Label>),
/// A `return`, with an optional value to be returned
ExprRet(Option<P<Expr>>),

@@ -957,7 +952,7 @@ pub enum Expr_ {
///
/// For example, `Foo {x: 1, y: 2}`, or
/// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
ExprStruct(P<Path>, HirVec<Field>, Option<P<Expr>>),
ExprStruct(QPath, HirVec<Field>, Option<P<Expr>>),

/// An array literal constructed from one repeated element.
///
@@ -966,22 +961,30 @@ pub enum Expr_ {
ExprRepeat(P<Expr>, P<Expr>),
}

/// The explicit Self type in a "qualified path". The actual
/// path, including the trait and the associated item, is stored
/// separately. `position` represents the index of the associated
/// item qualified with this Self type.
///
/// <HirVec<T> as a::b::Trait>::AssociatedItem
/// ^~~~~ ~~~~~~~~~~~~~~^
/// ty position = 3
///
/// <HirVec<T>>::AssociatedItem
/// ^~~~~ ^
/// ty position = 0
/// Optionally `Self`-qualified value/type path or associated extension.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct QSelf {
pub ty: P<Ty>,
pub position: usize,
pub enum QPath {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, this is exactly what I wanted in eddyb@0a5d332#commitcomment-19533413

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll have to see how this structure works out -- it doesn't seem like what I would naively expect, which is probably something more like:

pub enum Path {
    Base(P<PathBase>),
    Project(P<Path>, P<PathProjection>),
}

pub enum PathBase {
    Module(P<Path>), // i.e., `::a` (or `a`, in a `use` statement)
    FullyQualified(P<Ty>, P<Path>), // i.e., `<Ty as Path>`
    Type(P<Ty>),
}

...

But I can see that the first two cases are kind of the same as QPath (also, the structure that I gave is less precise, in that it would permit associated modules etc). But anyway the point is some kind of recursive tree.

That said, I am also happy with this QPath structure -- I think mostly I just want some better documentation. Specifically, some examples showing different paths and how they wind up being represented to make it clearer.

/// Path to a definition, optionally "fully-qualified" with a `Self`
/// type, if the path points to an associated item in a trait.
///
/// E.g. an unqualified path like `Clone::clone` has `None` for `Self`,
/// while `<Vec<T> as Clone>::clone` has `Some(Vec<T>)` for `Self`,
/// even though they both have the same two-segment `Clone::clone` `Path`.
Resolved(Option<P<Ty>>, P<Path>),

/// Type-related paths, e.g. `<T>::default` or `<T>::Output`.
/// Will be resolved by type-checking to an associated item.
///
/// UFCS source paths can desugar into this, with `Vec::new` turning into
/// `<Vec>::new`, and `T::X::Y::method` into `<<<T>::X>::Y>::method`,
/// the `X` and `Y` nodes being each a `TyPath(QPath::TypeRelative(..))`.
TypeRelative(P<Ty>, P<PathSegment>)
}

impl fmt::Display for QPath {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", print::qpath_to_string(self))
}
}

/// Hints at the original code for a `match _ { .. }`
@@ -1014,6 +1017,13 @@ pub enum LoopSource {
}


#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub struct Label {
pub span: Span,
pub name: Name,
pub loop_id: NodeId
}

#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
pub enum CaptureClause {
CaptureByValue,
@@ -1155,11 +1165,12 @@ pub enum Ty_ {
TyNever,
/// A tuple (`(A, B, C, D,...)`)
TyTup(HirVec<P<Ty>>),
/// A path (`module::module::...::Type`), optionally
/// "qualified", e.g. `<HirVec<T> as SomeTrait>::SomeType`.
/// A path to a type definition (`module::module::...::Type`), or an
/// associated type, e.g. `<Vec<T> as Trait>::Type` or `<T>::Target`.
///
/// Type parameters are stored in the Path itself
TyPath(Option<QSelf>, Path),
/// Type parameters may be stored in each `PathSegment`.
TyPath(QPath),

/// Something like `A+B`. Note that `B` must always be a path.
TyObjectSum(P<Ty>, TyParamBounds),
/// A type like `for<'a> Foo<&'a Bar>`
@@ -1216,7 +1227,7 @@ pub type ExplicitSelf = Spanned<SelfKind>;

impl Arg {
pub fn to_self(&self) -> Option<ExplicitSelf> {
if let PatKind::Binding(BindByValue(mutbl), name, _) = self.pat.node {
if let PatKind::Binding(BindByValue(mutbl), _, name, _) = self.pat.node {
if name.node == keywords::SelfValue.name() {
return match self.ty.node {
TyInfer => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
@@ -1232,7 +1243,7 @@ impl Arg {
}

pub fn is_self(&self) -> bool {
if let PatKind::Binding(_, name, _) = self.pat.node {
if let PatKind::Binding(_, _, name, _) = self.pat.node {
name.node == keywords::SelfValue.name()
} else {
false
@@ -1375,32 +1386,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.
@@ -1534,8 +1533,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>),
240 changes: 122 additions & 118 deletions src/librustc/hir/pat_util.rs
Original file line number Diff line number Diff line change
@@ -8,13 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use hir::def::*;
use hir::def::Def;
use hir::def_id::DefId;
use hir::{self, PatKind};
use ty::TyCtxt;
use syntax::ast;
use syntax::codemap::Spanned;
use syntax_pos::{Span, DUMMY_SP};
use syntax_pos::Span;

use std::iter::{Enumerate, ExactSizeIterator};

@@ -51,139 +50,144 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
}
}

pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Lit(_) | PatKind::Range(..) | PatKind::Path(Some(..), _) => true,
PatKind::TupleStruct(..) |
PatKind::Path(..) |
PatKind::Struct(..) => {
match dm.get(&pat.id).map(|d| d.full_def()) {
Some(Def::Variant(..)) | Some(Def::VariantCtor(..)) => true,
_ => false
impl hir::Pat {
pub fn is_refutable(&self) -> bool {
match self.node {
PatKind::Lit(_) |
PatKind::Range(..) |
PatKind::Path(hir::QPath::Resolved(Some(..), _)) |
PatKind::Path(hir::QPath::TypeRelative(..)) => true,

PatKind::Path(hir::QPath::Resolved(_, ref path)) |
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
match path.def {
Def::Variant(..) | Def::VariantCtor(..) => true,
_ => false
}
}
PatKind::Slice(..) => true,
_ => false
}
PatKind::Slice(..) => true,
_ => false
}
}

pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Path(..) => {
match dm.get(&pat.id).map(|d| d.full_def()) {
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
_ => false
pub fn is_const(&self) -> bool {
match self.node {
PatKind::Path(hir::QPath::TypeRelative(..)) => true,
PatKind::Path(hir::QPath::Resolved(_, ref path)) => {
match path.def {
Def::Const(..) | Def::AssociatedConst(..) => true,
_ => false
}
}
_ => false
}
_ => false
}
}

/// Call `f` on every "binding" in a pattern, e.g., on `a` in
/// `match foo() { Some(a) => (), None => () }`
pub fn pat_bindings<F>(pat: &hir::Pat, mut f: F)
where F: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned<ast::Name>),
{
pat.walk(|p| {
if let PatKind::Binding(binding_mode, ref pth, _) = p.node {
f(binding_mode, p.id, p.span, pth);
}
true
});
}

/// Checks if the pattern contains any patterns that bind something to
/// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
pub fn pat_contains_bindings(pat: &hir::Pat) -> bool {
let mut contains_bindings = false;
pat.walk(|p| {
if let PatKind::Binding(..) = p.node {
contains_bindings = true;
false // there's at least one binding, can short circuit now.
} else {
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
/// `match foo() { Some(a) => (), None => () }`
pub fn each_binding<F>(&self, mut f: F)
where F: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned<ast::Name>),
{
self.walk(|p| {
if let PatKind::Binding(binding_mode, _, ref pth, _) = p.node {
f(binding_mode, p.id, p.span, pth);
}
true
}
});
contains_bindings
}
});
}

/// Checks if the pattern contains any `ref` or `ref mut` bindings,
/// and if yes whether its containing mutable ones or just immutables ones.
pub fn pat_contains_ref_binding(pat: &hir::Pat) -> Option<hir::Mutability> {
let mut result = None;
pat_bindings(pat, |mode, _, _, _| {
if let hir::BindingMode::BindByRef(m) = mode {
// Pick Mutable as maximum
match result {
None | Some(hir::MutImmutable) => result = Some(m),
_ => (),
/// Checks if the pattern contains any patterns that bind something to
/// an ident, e.g. `foo`, or `Foo(foo)` or `foo @ Bar(..)`.
pub fn contains_bindings(&self) -> bool {
let mut contains_bindings = false;
self.walk(|p| {
if let PatKind::Binding(..) = p.node {
contains_bindings = true;
false // there's at least one binding, can short circuit now.
} else {
true
}
}
});
result
}

/// Checks if the patterns for this arm contain any `ref` or `ref mut`
/// bindings, and if yes whether its containing mutable ones or just immutables ones.
pub fn arm_contains_ref_binding(arm: &hir::Arm) -> Option<hir::Mutability> {
arm.pats.iter()
.filter_map(|pat| pat_contains_ref_binding(pat))
.max_by_key(|m| match *m {
hir::MutMutable => 1,
hir::MutImmutable => 0,
})
}
});
contains_bindings
}

/// Checks if the pattern contains any patterns that bind something to
/// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`,
pub fn pat_contains_bindings_or_wild(pat: &hir::Pat) -> bool {
let mut contains_bindings = false;
pat.walk(|p| {
match p.node {
PatKind::Binding(..) | PatKind::Wild => {
contains_bindings = true;
false // there's at least one binding/wildcard, can short circuit now.
/// Checks if the pattern contains any patterns that bind something to
/// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`,
pub fn contains_bindings_or_wild(&self) -> bool {
let mut contains_bindings = false;
self.walk(|p| {
match p.node {
PatKind::Binding(..) | PatKind::Wild => {
contains_bindings = true;
false // there's at least one binding/wildcard, can short circuit now.
}
_ => true
}
_ => true
}
});
contains_bindings
}
});
contains_bindings
}

pub fn simple_name<'a>(pat: &'a hir::Pat) -> Option<ast::Name> {
match pat.node {
PatKind::Binding(hir::BindByValue(..), ref path1, None) => {
Some(path1.node)
}
_ => {
None
pub fn simple_name(&self) -> Option<ast::Name> {
match self.node {
PatKind::Binding(hir::BindByValue(..), _, ref path1, None) => {
Some(path1.node)
}
_ => {
None
}
}
}
}

pub fn def_to_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> hir::Path {
hir::Path::from_name(DUMMY_SP, tcx.item_name(id))
}
/// Return variants that are necessary to exist for the pattern to match.
pub fn necessary_variants(&self) -> Vec<DefId> {
let mut variants = vec![];
self.walk(|p| {
match p.node {
PatKind::Path(hir::QPath::Resolved(_, ref path)) |
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
match path.def {
Def::Variant(id) |
Def::VariantCtor(id, ..) => variants.push(id),
_ => ()
}
}
_ => ()
}
true
});
variants.sort();
variants.dedup();
variants
}

/// Return variants that are necessary to exist for the pattern to match.
pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
let mut variants = vec![];
pat.walk(|p| {
match p.node {
PatKind::TupleStruct(..) |
PatKind::Path(..) |
PatKind::Struct(..) => {
match dm.get(&p.id).map(|d| d.full_def()) {
Some(Def::Variant(id)) |
Some(Def::VariantCtor(id, ..)) => variants.push(id),
_ => ()
/// Checks if the pattern contains any `ref` or `ref mut` bindings,
/// and if yes whether its containing mutable ones or just immutables ones.
pub fn contains_ref_binding(&self) -> Option<hir::Mutability> {
let mut result = None;
self.each_binding(|mode, _, _, _| {
if let hir::BindingMode::BindByRef(m) = mode {
// Pick Mutable as maximum
match result {
None | Some(hir::MutImmutable) => result = Some(m),
_ => (),
}
}
_ => ()
}
true
});
variants.sort();
variants.dedup();
variants
});
result
}
}

impl hir::Arm {
/// Checks if the patterns for this arm contain any `ref` or `ref mut`
/// bindings, and if yes whether its containing mutable ones or just immutables ones.
pub fn contains_ref_binding(&self) -> Option<hir::Mutability> {
self.pats.iter()
.filter_map(|pat| pat.contains_ref_binding())
.max_by_key(|m| match *m {
hir::MutMutable => 1,
hir::MutImmutable => 0,
})
}
}
192 changes: 102 additions & 90 deletions src/librustc/hir/print.rs
Original file line number Diff line number Diff line change
@@ -272,7 +272,11 @@ pub fn fn_block_to_string(p: &hir::FnDecl) -> String {
}

pub fn path_to_string(p: &hir::Path) -> String {
to_string(|s| s.print_path(p, false, 0))
to_string(|s| s.print_path(p, false))
}

pub fn qpath_to_string(p: &hir::QPath) -> String {
to_string(|s| s.print_qpath(p, false))
}

pub fn name_to_string(name: ast::Name) -> String {
@@ -528,11 +532,8 @@ impl<'a> State<'a> {
};
self.print_ty_fn(f.abi, f.unsafety, &f.decl, None, &generics)?;
}
hir::TyPath(None, ref path) => {
self.print_path(path, false, 0)?;
}
hir::TyPath(Some(ref qself), ref path) => {
self.print_qpath(path, qself, false)?
hir::TyPath(ref qpath) => {
self.print_qpath(qpath, false)?
}
hir::TyObjectSum(ref ty, ref bounds) => {
self.print_type(&ty)?;
@@ -668,10 +669,22 @@ impl<'a> State<'a> {
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
}
@@ -844,8 +857,8 @@ impl<'a> State<'a> {
self.ann.post(self, NodeItem(item))
}

fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
self.print_path(&t.path, false, 0)
pub fn print_trait_ref(&mut self, t: &hir::TraitRef) -> io::Result<()> {
self.print_path(&t.path, false)
}

fn print_formal_lifetime_list(&mut self, lifetimes: &[hir::LifetimeDef]) -> io::Result<()> {
@@ -1115,8 +1128,6 @@ impl<'a> State<'a> {
hir::UnsafeBlock(..) => self.word_space("unsafe")?,
hir::PushUnsafeBlock(..) => self.word_space("push_unsafe")?,
hir::PopUnsafeBlock(..) => self.word_space("pop_unsafe")?,
hir::PushUnstableBlock => self.word_space("push_unstable")?,
hir::PopUnstableBlock => self.word_space("pop_unstable")?,
hir::DefaultBlock => (),
}
self.maybe_print_comment(blk.span.lo)?;
@@ -1237,11 +1248,11 @@ impl<'a> State<'a> {
}

fn print_expr_struct(&mut self,
path: &hir::Path,
qpath: &hir::QPath,
fields: &[hir::Field],
wth: &Option<P<hir::Expr>>)
-> io::Result<()> {
self.print_path(path, true, 0)?;
self.print_qpath(qpath, true)?;
word(&mut self.s, "{")?;
self.commasep_cmnt(Consistent,
&fields[..],
@@ -1345,8 +1356,8 @@ impl<'a> State<'a> {
hir::ExprRepeat(ref element, ref count) => {
self.print_expr_repeat(&element, &count)?;
}
hir::ExprStruct(ref path, ref fields, ref wth) => {
self.print_expr_struct(path, &fields[..], wth)?;
hir::ExprStruct(ref qpath, ref fields, ref wth) => {
self.print_expr_struct(qpath, &fields[..], wth)?;
}
hir::ExprTup(ref exprs) => {
self.print_expr_tup(exprs)?;
@@ -1465,29 +1476,26 @@ impl<'a> State<'a> {
self.print_expr(&index)?;
word(&mut self.s, "]")?;
}
hir::ExprPath(None, ref path) => {
self.print_path(path, true, 0)?
hir::ExprPath(ref qpath) => {
self.print_qpath(qpath, true)?
}
hir::ExprPath(Some(ref qself), ref path) => {
self.print_qpath(path, qself, true)?
}
hir::ExprBreak(opt_name, ref opt_expr) => {
hir::ExprBreak(opt_label, ref opt_expr) => {
word(&mut self.s, "break")?;
space(&mut self.s)?;
if let Some(name) = opt_name {
self.print_name(name.node)?;
if let Some(label) = opt_label {
self.print_name(label.name)?;
space(&mut self.s)?;
}
if let Some(ref expr) = *opt_expr {
self.print_expr(expr)?;
space(&mut self.s)?;
}
}
hir::ExprAgain(opt_name) => {
hir::ExprAgain(opt_label) => {
word(&mut self.s, "continue")?;
space(&mut self.s)?;
if let Some(name) = opt_name {
self.print_name(name.node)?;
if let Some(label) = opt_label {
self.print_name(label.name)?;
space(&mut self.s)?
}
}
@@ -1622,13 +1630,12 @@ impl<'a> State<'a> {

fn print_path(&mut self,
path: &hir::Path,
colons_before_params: bool,
depth: usize)
colons_before_params: bool)
-> io::Result<()> {
self.maybe_print_comment(path.span.lo)?;

let mut first = !path.global;
for segment in &path.segments[..path.segments.len() - depth] {
for segment in &path.segments {
if first {
first = false
} else {
@@ -1644,31 +1651,61 @@ impl<'a> State<'a> {
}

fn print_qpath(&mut self,
path: &hir::Path,
qself: &hir::QSelf,
qpath: &hir::QPath,
colons_before_params: bool)
-> io::Result<()> {
word(&mut self.s, "<")?;
self.print_type(&qself.ty)?;
if qself.position > 0 {
space(&mut self.s)?;
self.word_space("as")?;
let depth = path.segments.len() - qself.position;
self.print_path(&path, false, depth)?;
match *qpath {
hir::QPath::Resolved(None, ref path) => {
self.print_path(path, colons_before_params)
}
hir::QPath::Resolved(Some(ref qself), ref path) => {
word(&mut self.s, "<")?;
self.print_type(qself)?;
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 {
word(&mut self.s, "::")?
}
self.print_name(segment.name)?;
self.print_path_parameters(&segment.parameters, colons_before_params)?;
}

word(&mut self.s, ">")?;
word(&mut self.s, "::")?;
let item_segment = path.segments.last().unwrap();
self.print_name(item_segment.name)?;
self.print_path_parameters(&item_segment.parameters, colons_before_params)
}
hir::QPath::TypeRelative(ref qself, ref item_segment) => {
word(&mut self.s, "<")?;
self.print_type(qself)?;
word(&mut self.s, ">")?;
word(&mut self.s, "::")?;
self.print_name(item_segment.name)?;
self.print_path_parameters(&item_segment.parameters, colons_before_params)
}
}
word(&mut self.s, ">")?;
word(&mut self.s, "::")?;
let item_segment = path.segments.last().unwrap();
self.print_name(item_segment.name)?;
self.print_path_parameters(&item_segment.parameters, colons_before_params)
}

fn print_path_parameters(&mut self,
parameters: &hir::PathParameters,
colons_before_params: bool)
-> io::Result<()> {
if parameters.is_empty() {
return Ok(());
let infer_types = match *parameters {
hir::AngleBracketedParameters(ref data) => data.infer_types,
hir::ParenthesizedParameters(_) => false
};

// FIXME(eddyb) See the comment below about infer_types.
if !(infer_types && false) {
return Ok(());
}
}

if colons_before_params {
@@ -1696,6 +1733,16 @@ impl<'a> State<'a> {
comma = true;
}

// FIXME(eddyb) This would leak into error messages, e.g.:
// "non-exhaustive patterns: `Some::<..>(_)` not covered".
if data.infer_types && false {
if comma {
self.word_space(",")?
}
word(&mut self.s, "..")?;
comma = true;
}

for binding in data.bindings.iter() {
if comma {
self.word_space(",")?
@@ -1733,7 +1780,7 @@ impl<'a> State<'a> {
// is that it doesn't matter
match pat.node {
PatKind::Wild => word(&mut self.s, "_")?,
PatKind::Binding(binding_mode, ref path1, ref sub) => {
PatKind::Binding(binding_mode, _, ref path1, ref sub) => {
match binding_mode {
hir::BindByRef(mutbl) => {
self.word_nbsp("ref")?;
@@ -1750,8 +1797,8 @@ impl<'a> State<'a> {
self.print_pat(&p)?;
}
}
PatKind::TupleStruct(ref path, ref elts, ddpos) => {
self.print_path(path, true, 0)?;
PatKind::TupleStruct(ref qpath, ref elts, ddpos) => {
self.print_qpath(qpath, true)?;
self.popen()?;
if let Some(ddpos) = ddpos {
self.commasep(Inconsistent, &elts[..ddpos], |s, p| s.print_pat(&p))?;
@@ -1768,14 +1815,11 @@ impl<'a> State<'a> {
}
self.pclose()?;
}
PatKind::Path(None, ref path) => {
self.print_path(path, true, 0)?;
PatKind::Path(ref qpath) => {
self.print_qpath(qpath, true)?;
}
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)?;
PatKind::Struct(ref qpath, ref fields, etc) => {
self.print_qpath(qpath, true)?;
self.nbsp()?;
self.word_space("{")?;
self.commasep_cmnt(Consistent,
@@ -2108,7 +2152,7 @@ impl<'a> State<'a> {
}
}
&hir::WherePredicate::EqPredicate(hir::WhereEqPredicate{ref path, ref ty, ..}) => {
self.print_path(path, false, 0)?;
self.print_path(path, false)?;
space(&mut self.s)?;
self.word_space("=")?;
self.print_type(&ty)?;
@@ -2119,38 +2163,6 @@ impl<'a> State<'a> {
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, 0)?;

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, 0)?;
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, 0)?;
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"),
@@ -2171,7 +2183,7 @@ impl<'a> State<'a> {
if let Some(eself) = input.to_self() {
self.print_explicit_self(&eself)?;
} else {
let invalid = if let PatKind::Binding(_, name, _) = input.pat.node {
let invalid = if let PatKind::Binding(_, _, name, _) = input.pat.node {
name.node == keywords::Invalid.name()
} else {
false
15 changes: 7 additions & 8 deletions src/librustc/infer/error_reporting.rs
Original file line number Diff line number Diff line change
@@ -1440,8 +1440,8 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
}
ty_queue.push(&mut_ty.ty);
}
hir::TyPath(ref maybe_qself, ref path) => {
match self.tcx.expect_def(cur_ty.id) {
hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
match path.def {
Def::Enum(did) | Def::TyAlias(did) |
Def::Struct(did) | Def::Union(did) => {
let generics = self.tcx.item_generics(did);
@@ -1476,15 +1476,12 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
};
let new_path = self.rebuild_path(rebuild_info, lifetime);
let qself = maybe_qself.as_ref().map(|qself| {
hir::QSelf {
ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime,
anon_nums, region_names),
position: qself.position
}
self.rebuild_arg_ty_or_output(qself, lifetime,
anon_nums, region_names)
});
let to = hir::Ty {
id: cur_ty.id,
node: hir::TyPath(qself, new_path),
node: hir::TyPath(hir::QPath::Resolved(qself, P(new_path))),
span: cur_ty.span
};
new_ty = self.rebuild_ty(new_ty, P(to));
@@ -1609,6 +1606,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
lifetimes: new_lts.into(),
types: new_types,
infer_types: data.infer_types,
bindings: new_bindings,
})
}
@@ -1623,6 +1621,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
hir::Path {
span: path.span,
global: path.global,
def: path.def,
segments: new_segs.into()
}
}
9 changes: 8 additions & 1 deletion src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
@@ -211,6 +211,12 @@ declare_lint! {
not named `mod.rs`"
}

declare_lint! {
pub DEPRECATED,
Warn,
"detects use of deprecated items"
}

/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy, Clone)]
@@ -250,7 +256,8 @@ impl LintPass for HardwiredLints {
SAFE_EXTERN_STATICS,
PATTERNS_IN_FNS_WITHOUT_BODY,
EXTRA_REQUIREMENT_IN_IMPL,
LEGACY_DIRECTORY_OWNERSHIP
LEGACY_DIRECTORY_OWNERSHIP,
DEPRECATED
)
}
}
5 changes: 0 additions & 5 deletions src/librustc/lint/context.rs
Original file line number Diff line number Diff line change
@@ -948,11 +948,6 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
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);
1 change: 0 additions & 1 deletion src/librustc/lint/mod.rs
Original file line number Diff line number Diff line change
@@ -168,7 +168,6 @@ pub trait LateLintPass: LintPass {
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
26 changes: 13 additions & 13 deletions src/librustc/middle/astconv_util.rs
Original file line number Diff line number Diff line change
@@ -14,14 +14,14 @@
* Almost certainly this could (and should) be refactored out of existence.
*/

use hir;
use hir::def::Def;
use ty::{Ty, TyCtxt};

use syntax_pos::Span;
use hir as ast;

impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn prohibit_type_params(self, segments: &[ast::PathSegment]) {
pub fn prohibit_type_params(self, segments: &[hir::PathSegment]) {
for segment in segments {
for typ in segment.parameters.types() {
struct_span_err!(self.sess, typ.span, E0109,
@@ -53,25 +53,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
}

pub fn prim_ty_to_ty(self,
segments: &[ast::PathSegment],
nty: ast::PrimTy)
segments: &[hir::PathSegment],
nty: hir::PrimTy)
-> Ty<'tcx> {
self.prohibit_type_params(segments);
match nty {
ast::TyBool => self.types.bool,
ast::TyChar => self.types.char,
ast::TyInt(it) => self.mk_mach_int(it),
ast::TyUint(uit) => self.mk_mach_uint(uit),
ast::TyFloat(ft) => self.mk_mach_float(ft),
ast::TyStr => self.mk_str()
hir::TyBool => self.types.bool,
hir::TyChar => self.types.char,
hir::TyInt(it) => self.mk_mach_int(it),
hir::TyUint(uit) => self.mk_mach_uint(uit),
hir::TyFloat(ft) => self.mk_mach_float(ft),
hir::TyStr => self.mk_str()
}
}

/// If a type in the AST is a primitive type, return the ty::Ty corresponding
/// to it.
pub fn ast_ty_to_prim_ty(self, ast_ty: &ast::Ty) -> Option<Ty<'tcx>> {
if let ast::TyPath(None, ref path) = ast_ty.node {
if let Def::PrimTy(nty) = self.expect_def(ast_ty.id) {
pub fn ast_ty_to_prim_ty(self, ast_ty: &hir::Ty) -> Option<Ty<'tcx>> {
if let hir::TyPath(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
if let Def::PrimTy(nty) = path.def {
Some(self.prim_ty_to_ty(&path.segments, nty))
} else {
None
37 changes: 15 additions & 22 deletions src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@

use dep_graph::DepNode;
use hir::map as ast_map;
use hir::{self, pat_util, PatKind};
use hir::{self, PatKind};
use hir::intravisit::{self, Visitor};
use hir::itemlikevisit::ItemLikeVisitor;

@@ -86,9 +86,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
}
}

fn lookup_and_handle_definition(&mut self, id: ast::NodeId) {
let def = self.tcx.expect_def(id);

fn handle_definition(&mut self, id: ast::NodeId, def: Def) {
// If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar`
match def {
Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
@@ -147,12 +145,10 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
}
}

fn handle_field_pattern_match(&mut self, lhs: &hir::Pat,
fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, def: Def,
pats: &[codemap::Spanned<hir::FieldPat>]) {
let variant = match self.tcx.tables().node_id_to_type(lhs.id).sty {
ty::TyAdt(adt, _) => {
adt.variant_of_def(self.tcx.expect_def(lhs.id))
}
ty::TyAdt(adt, _) => adt.variant_of_def(def),
_ => span_bug!(lhs.span, "non-ADT in struct pattern")
};
for pat in pats {
@@ -240,6 +236,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {

fn visit_expr(&mut self, expr: &hir::Expr) {
match expr.node {
hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => {
let def = self.tcx.tables().qpath_def(qpath, expr.id);
self.handle_definition(expr.id, def);
}
hir::ExprMethodCall(..) => {
self.lookup_and_handle_method(expr.id);
}
@@ -257,8 +257,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {

fn visit_arm(&mut self, arm: &hir::Arm) {
if arm.pats.len() == 1 {
let pat = &*arm.pats[0];
let variants = pat_util::necessary_variants(&self.tcx.def_map.borrow(), pat);
let variants = arm.pats[0].necessary_variants();

// Inside the body, ignore constructions of variants
// necessary for the pattern to match. Those construction sites
@@ -273,14 +272,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
}

fn visit_pat(&mut self, pat: &hir::Pat) {
let def_map = &self.tcx.def_map;
match pat.node {
PatKind::Struct(_, ref fields, _) => {
self.handle_field_pattern_match(pat, fields);
PatKind::Struct(hir::QPath::Resolved(_, ref path), ref fields, _) => {
self.handle_field_pattern_match(pat, path.def, fields);
}
_ if pat_util::pat_is_const(&def_map.borrow(), pat) => {
// it might be the only use of a const
self.lookup_and_handle_definition(pat.id)
PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => {
let def = self.tcx.tables().qpath_def(qpath, pat.id);
self.handle_definition(pat.id, def);
}
_ => ()
}
@@ -291,14 +289,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
}

fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
self.lookup_and_handle_definition(id);
self.handle_definition(id, path.def);
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 {
6 changes: 3 additions & 3 deletions src/librustc/middle/effect.rs
Original file line number Diff line number Diff line change
@@ -147,7 +147,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
self.unsafe_context.push_unsafe_count =
self.unsafe_context.push_unsafe_count.checked_sub(1).unwrap();
}
hir::DefaultBlock | hir::PushUnstableBlock | hir:: PopUnstableBlock => {}
hir::DefaultBlock => {}
}

intravisit::walk_block(self, block);
@@ -186,8 +186,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
hir::ExprInlineAsm(..) => {
self.require_unsafe(expr.span, "use of inline assembly");
}
hir::ExprPath(..) => {
if let Def::Static(def_id, mutbl) = self.tcx.expect_def(expr.id) {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
if let Def::Static(def_id, mutbl) = path.def {
if mutbl {
self.require_unsafe(expr.span, "use of mutable static");
} else if match self.tcx.map.get_if_local(def_id) {
32 changes: 18 additions & 14 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
@@ -19,7 +19,6 @@ pub use self::MatchMode::*;
use self::TrackMatchMode::*;
use self::OverloadedCallType::*;

use hir::pat_util;
use hir::def::Def;
use hir::def_id::{DefId};
use infer::InferCtxt;
@@ -374,7 +373,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
self.walk_adjustment(expr);

match expr.node {
hir::ExprPath(..) => { }
hir::ExprPath(_) => { }

hir::ExprType(ref subexpr, _) => {
self.walk_expr(&subexpr)
@@ -622,7 +621,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
match local.init {
None => {
let delegate = &mut self.delegate;
pat_util::pat_bindings(&local.pat, |_, id, span, _| {
local.pat.each_binding(|_, id, span, _| {
delegate.decl_without_init(id, span);
})
}
@@ -957,16 +956,16 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
let infcx = self.mc.infcx;
let delegate = &mut self.delegate;
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
if let PatKind::Binding(bmode, ..) = pat.node {
if let PatKind::Binding(bmode, def_id, ..) = pat.node {
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);

// pat_ty: the type of the binding being produced.
let pat_ty = return_if_err!(infcx.node_ty(pat.id));

// Each match binding is effectively an assignment to the
// binding being produced.
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty,
tcx.expect_def(pat.id)) {
let def = Def::Local(def_id);
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) {
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
}

@@ -992,9 +991,16 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
// to the above loop's visit of than the bindings that form
// the leaves of the pattern tree structure.
return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
match tcx.expect_def_or_none(pat.id) {
Some(Def::Variant(variant_did)) |
Some(Def::VariantCtor(variant_did, ..)) => {
let qpath = match pat.node {
PatKind::Path(ref qpath) |
PatKind::TupleStruct(ref qpath, ..) |
PatKind::Struct(ref qpath, ..) => qpath,
_ => return
};
let def = tcx.tables().qpath_def(qpath, pat.id);
match def {
Def::Variant(variant_did) |
Def::VariantCtor(variant_did, ..) => {
let enum_did = tcx.parent_def_id(variant_did).unwrap();
let downcast_cmt = if tcx.lookup_adt_def(enum_did).is_univariant() {
cmt_pat
@@ -1006,14 +1012,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
delegate.matched_pat(pat, downcast_cmt, match_mode);
}
Some(Def::Struct(..)) | Some(Def::StructCtor(..)) | Some(Def::Union(..)) |
Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) | Some(Def::SelfTy(..)) => {
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
delegate.matched_pat(pat, cmt_pat, match_mode);
}
None | Some(Def::Local(..)) |
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {}
def => bug!("unexpected definition: {:?}", def)
_ => {}
}
}));
}
31 changes: 17 additions & 14 deletions src/librustc/middle/intrinsicck.rs
Original file line number Diff line number Diff line change
@@ -160,23 +160,26 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {

impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> {
fn visit_expr(&mut self, expr: &hir::Expr) {
if let hir::ExprPath(..) = expr.node {
match self.infcx.tcx.expect_def(expr.id) {
Def::Fn(did) if self.def_id_is_transmute(did) => {
let typ = self.infcx.tcx.tables().node_id_to_type(expr.id);
match typ.sty {
ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
let from = bare_fn_ty.sig.0.inputs[0];
let to = bare_fn_ty.sig.0.output;
self.check_transmute(expr.span, from, to, expr.id);
}
_ => {
span_bug!(expr.span, "transmute wasn't a bare fn?!");
}
let def = if let hir::ExprPath(ref qpath) = expr.node {
self.infcx.tcx.tables().qpath_def(qpath, expr.id)
} else {
Def::Err
};
match def {
Def::Fn(did) if self.def_id_is_transmute(did) => {
let typ = self.infcx.tcx.tables().node_id_to_type(expr.id);
match typ.sty {
ty::TyFnDef(.., ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
let from = bare_fn_ty.sig.0.inputs[0];
let to = bare_fn_ty.sig.0.output;
self.check_transmute(expr.span, from, to, expr.id);
}
_ => {
span_bug!(expr.span, "transmute wasn't a bare fn?!");
}
}
_ => {}
}
_ => {}
}

intravisit::walk_expr(self, expr);
67 changes: 28 additions & 39 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
@@ -111,7 +111,6 @@ use self::VarKind::*;

use dep_graph::DepNode;
use hir::def::*;
use hir::pat_util;
use ty::{self, TyCtxt, ParameterEnvironment};
use traits::{self, Reveal};
use ty::subst::Subst;
@@ -379,7 +378,7 @@ fn visit_fn(ir: &mut IrMaps,
debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps);

for arg in &decl.inputs {
pat_util::pat_bindings(&arg.pat, |_bm, arg_id, _x, path1| {
arg.pat.each_binding(|_bm, arg_id, _x, path1| {
debug!("adding argument {}", arg_id);
let name = path1.node;
fn_maps.add_variable(Arg(arg_id, name));
@@ -412,7 +411,7 @@ fn visit_fn(ir: &mut IrMaps,
}

fn visit_local(ir: &mut IrMaps, local: &hir::Local) {
pat_util::pat_bindings(&local.pat, |_, p_id, sp, path1| {
local.pat.each_binding(|_, p_id, sp, path1| {
debug!("adding local variable {}", p_id);
let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp));
@@ -426,7 +425,7 @@ fn visit_local(ir: &mut IrMaps, local: &hir::Local) {

fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) {
for pat in &arm.pats {
pat_util::pat_bindings(&pat, |bm, p_id, sp, path1| {
pat.each_binding(|bm, p_id, sp, path1| {
debug!("adding local variable {} from match with bm {:?}",
p_id, bm);
let name = path1.node;
@@ -443,10 +442,9 @@ fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) {
fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
match expr.node {
// live nodes required for uses or definitions of variables:
hir::ExprPath(..) => {
let def = ir.tcx.expect_def(expr.id);
debug!("expr {}: path that leads to {:?}", expr.id, def);
if let Def::Local(..) = def {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
debug!("expr {}: path that leads to {:?}", expr.id, path.def);
if let Def::Local(..) = path.def {
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
}
intravisit::walk_expr(ir, expr);
@@ -495,7 +493,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) |
hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprInlineAsm(..) | hir::ExprBox(..) |
hir::ExprType(..) => {
hir::ExprType(..) | hir::ExprPath(hir::QPath::TypeRelative(..)) => {
intravisit::walk_expr(ir, expr);
}
}
@@ -587,7 +585,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn pat_bindings<F>(&mut self, pat: &hir::Pat, mut f: F) where
F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId),
{
pat_util::pat_bindings(pat, |_bm, p_id, sp, _n| {
pat.each_binding(|_bm, p_id, sp, _n| {
let ln = self.live_node(p_id, sp);
let var = self.variable(p_id, sp);
f(self, ln, var, sp, p_id);
@@ -684,22 +682,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}

fn find_loop_scope(&self,
opt_label: Option<ast::Name>,
id: NodeId,
opt_label: Option<hir::Label>,
sp: Span)
-> NodeId {
match opt_label {
Some(_) => {
// Refers to a labeled loop. Use the results of resolve
// to find with one
match self.ir.tcx.expect_def(id) {
Def::Label(loop_id) => loop_id,
_ => span_bug!(sp, "label on break/loop \
doesn't refer to a loop")
}
}
Some(label) => label.loop_id,
None => {
// Vanilla 'break' or 'loop', so use the enclosing
// Vanilla 'break' or 'continue', so use the enclosing
// loop scope
if self.loop_scope.is_empty() {
span_bug!(sp, "break outside loop");
@@ -922,8 +911,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
match expr.node {
// Interesting cases with control flow or which gen/kill

hir::ExprPath(..) => {
self.access_path(expr, succ, ACC_READ | ACC_USE)
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
self.access_path(expr.id, path, succ, ACC_READ | ACC_USE)
}

hir::ExprField(ref e, _) => {
@@ -1037,7 +1026,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {

hir::ExprBreak(opt_label, ref opt_expr) => {
// Find which label this break jumps to
let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span);
let sc = self.find_loop_scope(opt_label, expr.span);

// Now that we know the label we're going to,
// look it up in the break loop nodes table
@@ -1050,7 +1039,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {

hir::ExprAgain(opt_label) => {
// Find which label this expr continues to
let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span);
let sc = self.find_loop_scope(opt_label, expr.span);

// Now that we know the label we're going to,
// look it up in the continue loop nodes table
@@ -1171,7 +1160,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
self.propagate_through_exprs(inputs, succ)
}

hir::ExprLit(..) => {
hir::ExprLit(..) | hir::ExprPath(hir::QPath::TypeRelative(..)) => {
succ
}

@@ -1235,7 +1224,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// just ignore such cases and treat them as reads.

match expr.node {
hir::ExprPath(..) => succ,
hir::ExprPath(_) => succ,
hir::ExprField(ref e, _) => self.propagate_through_expr(&e, succ),
hir::ExprTupField(ref e, _) => self.propagate_through_expr(&e, succ),
_ => self.propagate_through_expr(expr, succ)
@@ -1246,8 +1235,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
-> LiveNode {
match expr.node {
hir::ExprPath(..) => {
self.access_path(expr, succ, acc)
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
self.access_path(expr.id, path, succ, acc)
}

// We do not track other lvalues, so just propagate through
@@ -1258,15 +1247,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
}
}

fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
fn access_path(&mut self, id: NodeId, path: &hir::Path, succ: LiveNode, acc: u32)
-> LiveNode {
match self.ir.tcx.expect_def(expr.id) {
match path.def {
Def::Local(def_id) => {
let nid = self.ir.tcx.map.as_local_node_id(def_id).unwrap();
let ln = self.live_node(expr.id, expr.span);
let ln = self.live_node(id, path.span);
if acc != 0 {
self.init_from_succ(ln, succ);
let var = self.variable(nid, expr.span);
let var = self.variable(nid, path.span);
self.acc(ln, var, acc);
}
ln
@@ -1431,8 +1420,8 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
hir::ExprBreak(..) | hir::ExprAgain(..) | hir::ExprLit(_) |
hir::ExprBlock(..) | hir::ExprAddrOf(..) |
hir::ExprStruct(..) | hir::ExprRepeat(..) |
hir::ExprClosure(..) | hir::ExprPath(..) | hir::ExprBox(..) |
hir::ExprType(..) => {
hir::ExprClosure(..) | hir::ExprPath(_) |
hir::ExprBox(..) | hir::ExprType(..) => {
intravisit::walk_expr(this, expr);
}
}
@@ -1482,8 +1471,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {

fn check_lvalue(&mut self, expr: &Expr) {
match expr.node {
hir::ExprPath(..) => {
if let Def::Local(def_id) = self.ir.tcx.expect_def(expr.id) {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
if let Def::Local(def_id) = path.def {
// Assignment to an immutable variable or argument: only legal
// if there is no later assignment. If this local is actually
// mutable, then check for a reassignment to flag the mutability
@@ -1513,7 +1502,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {

fn warn_about_unused_args(&self, decl: &hir::FnDecl, entry_ln: LiveNode) {
for arg in &decl.inputs {
pat_util::pat_bindings(&arg.pat, |_bm, p_id, sp, path1| {
arg.pat.each_binding(|_bm, p_id, sp, path1| {
let var = self.variable(p_id, sp);
// Ignore unused self.
let name = path1.node;
39 changes: 24 additions & 15 deletions src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
@@ -488,8 +488,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
}

hir::ExprPath(..) => {
self.cat_def(expr.id, expr.span, expr_ty, self.tcx().expect_def(expr.id))
hir::ExprPath(ref qpath) => {
let def = self.infcx.tables.borrow().qpath_def(qpath, expr.id);
self.cat_def(expr.id, expr.span, expr_ty, def)
}

hir::ExprType(ref e, _) => {
@@ -1062,24 +1063,32 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {

// Note: This goes up here (rather than within the PatKind::TupleStruct arm
// alone) because PatKind::Struct can also refer to variants.
let cmt = match self.tcx().expect_def_or_none(pat.id) {
Some(Def::Err) => return Err(()),
Some(Def::Variant(variant_did)) |
Some(Def::VariantCtor(variant_did, ..)) => {
// univariant enums do not need downcasts
let enum_did = self.tcx().parent_def_id(variant_did).unwrap();
if !self.tcx().lookup_adt_def(enum_did).is_univariant() {
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
} else {
cmt
let cmt = match pat.node {
PatKind::Path(hir::QPath::Resolved(_, ref path)) |
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
match path.def {
Def::Err => return Err(()),
Def::Variant(variant_did) |
Def::VariantCtor(variant_did, ..) => {
// univariant enums do not need downcasts
let enum_did = self.tcx().parent_def_id(variant_did).unwrap();
if !self.tcx().lookup_adt_def(enum_did).is_univariant() {
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
} else {
cmt
}
}
_ => cmt
}
}
_ => cmt
};

match pat.node {
PatKind::TupleStruct(_, ref subpats, ddpos) => {
let expected_len = match self.tcx().expect_def(pat.id) {
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
let def = self.infcx.tables.borrow().qpath_def(qpath, pat.id);
let expected_len = match def {
Def::VariantCtor(def_id, CtorKind::Fn) => {
let enum_def = self.tcx().parent_def_id(def_id).unwrap();
self.tcx().lookup_adt_def(enum_def).variant_with_id(def_id).fields.len()
@@ -1157,7 +1166,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
}
}

PatKind::Path(..) | PatKind::Binding(.., None) |
PatKind::Path(_) | PatKind::Binding(.., None) |
PatKind::Lit(..) | PatKind::Range(..) | PatKind::Wild => {
// always ok
}
65 changes: 31 additions & 34 deletions src/librustc/middle/reachable.rs
Original file line number Diff line number Diff line change
@@ -90,45 +90,40 @@ struct ReachableContext<'a, 'tcx: 'a> {

impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
fn visit_expr(&mut self, expr: &hir::Expr) {
match expr.node {
hir::ExprPath(..) => {
let def = self.tcx.expect_def(expr.id);
let def_id = def.def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
if self.def_id_represents_local_inlined_item(def_id) {
self.worklist.push(node_id);
} else {
match def {
// If this path leads to a constant, then we need to
// recurse into the constant to continue finding
// items that are reachable.
Def::Const(..) | Def::AssociatedConst(..) => {
self.worklist.push(node_id);
}

// If this wasn't a static, then the destination is
// surely reachable.
_ => {
self.reachable_symbols.insert(node_id);
}
}
}
}
let def = match expr.node {
hir::ExprPath(ref qpath) => {
Some(self.tcx.tables().qpath_def(qpath, expr.id))
}
hir::ExprMethodCall(..) => {
let method_call = ty::MethodCall::expr(expr.id);
let def_id = self.tcx.tables().method_map[&method_call].def_id;
let def_id = self.tcx.tables.borrow().method_map[&method_call].def_id;
Some(Def::Method(def_id))
}
_ => None
};

if let Some(def) = def {
let def_id = def.def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
if self.def_id_represents_local_inlined_item(def_id) {
self.worklist.push(node_id);
} else {
match def {
// If this path leads to a constant, then we need to
// recurse into the constant to continue finding
// items that are reachable.
Def::Const(..) | Def::AssociatedConst(..) => {
self.worklist.push(node_id);
}

// Mark the trait item (and, possibly, its default impl) as reachable
// Or mark inherent impl item as reachable
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
if self.def_id_represents_local_inlined_item(def_id) {
self.worklist.push(node_id)
// If this wasn't a static, then the destination is
// surely reachable.
_ => {
self.reachable_symbols.insert(node_id);
}
}
self.reachable_symbols.insert(node_id);
}
}
_ => {}
}

intravisit::walk_expr(self, expr)
@@ -265,7 +260,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
// 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(..) |
@@ -303,7 +298,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
// Nothing to recurse on for these
ast_map::NodeForeignItem(_) |
ast_map::NodeVariant(_) |
ast_map::NodeStructCtor(_) => {}
ast_map::NodeStructCtor(_) |
ast_map::NodeField(_) |
ast_map::NodeTy(_) => {}
_ => {
bug!("found unexpected thingy in worklist: {}",
self.tcx.map.node_to_string(search_item))
21 changes: 9 additions & 12 deletions src/librustc/middle/resolve_lifetime.rs
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@ use self::ScopeChain::*;
use dep_graph::DepNode;
use hir::map::Map;
use session::Session;
use hir::def::{Def, DefMap};
use hir::def::Def;
use hir::def_id::DefId;
use middle::region;
use ty;
@@ -65,7 +65,6 @@ struct LifetimeContext<'a, 'tcx: 'a> {
hir_map: &'a Map<'tcx>,
map: &'a mut NamedRegionMap,
scope: Scope<'a>,
def_map: &'a DefMap,
// Deep breath. Our representation for poly trait refs contains a single
// binder and thus we only allow a single level of quantification. However,
// the syntax of Rust permits quantification in two places, e.g., `T: for <'a> Foo<'a>`
@@ -109,8 +108,7 @@ type Scope<'a> = &'a ScopeChain<'a>;
static ROOT_SCOPE: ScopeChain<'static> = RootScope;

pub fn krate(sess: &Session,
hir_map: &Map,
def_map: &DefMap)
hir_map: &Map)
-> Result<NamedRegionMap, usize> {
let _task = hir_map.dep_graph.in_task(DepNode::ResolveLifetimes);
let krate = hir_map.krate();
@@ -124,7 +122,6 @@ pub fn krate(sess: &Session,
hir_map: hir_map,
map: &mut map,
scope: &ROOT_SCOPE,
def_map: def_map,
trait_ref_hack: false,
labels_in_fn: vec![],
}, krate);
@@ -151,7 +148,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::walk_item(this, item);
}
hir::ItemExternCrate(_) |
hir::ItemUse(_) |
hir::ItemUse(..) |
hir::ItemMod(..) |
hir::ItemDefaultImpl(..) |
hir::ItemForeignMod(..) |
@@ -244,11 +241,11 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
intravisit::walk_ty(this, ty);
});
}
hir::TyPath(None, ref path) => {
hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
// if this path references a trait, then this will resolve to
// a trait ref, which introduces a binding scope.
match self.def_map.get(&ty.id).map(|d| (d.base_def, d.depth)) {
Some((Def::Trait(..), 0)) => {
match path.def {
Def::Trait(..) => {
self.with(LateScope(&[], self.scope), |_, this| {
this.visit_path(path, ty.id);
});
@@ -541,7 +538,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
hir_map: hir_map,
map: *map,
scope: &wrap_scope,
def_map: self.def_map,
trait_ref_hack: self.trait_ref_hack,
labels_in_fn: self.labels_in_fn.clone(),
};
@@ -944,13 +940,14 @@ fn insert_late_bound_lifetimes(map: &mut NamedRegionMap,
impl<'v> Visitor<'v> for ConstrainedCollector {
fn visit_ty(&mut self, ty: &'v hir::Ty) {
match ty.node {
hir::TyPath(Some(_), _) => {
hir::TyPath(hir::QPath::Resolved(Some(_), _)) |
hir::TyPath(hir::QPath::TypeRelative(..)) => {
// ignore lifetimes appearing in associated type
// projections, as they are not *constrained*
// (defined above)
}

hir::TyPath(None, ref path) => {
hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
// consider only the lifetimes on the final
// segment; I am not sure it's even currently
// valid to have them elsewhere, but even if it
Loading