rustc: embed path resolutions into the HIR instead of keeping DefMap.

This commit is contained in:
Eduard-Mihai Burtescu 2016-11-25 13:21:19 +02:00
parent bc096549e8
commit 962633cdbb
55 changed files with 951 additions and 949 deletions

View file

@ -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;
@ -284,7 +282,7 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
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);
@ -292,7 +290,7 @@ fn expr(&mut self, expr: &hir::Expr, pred: CFGIndex) -> CFGIndex {
}
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);
@ -457,7 +455,7 @@ fn match_(&mut self, id: ast::NodeId, discr: &hir::Expr,
// 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 @@ fn add_returning_edge(&mut self,
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);
}
}
}

View file

@ -83,14 +83,6 @@ pub fn new(def: Def) -> 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"

View file

@ -38,6 +38,7 @@
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 @@ fn as_deep_visitor<'s>(&'s mut self) -> DeepVisitor<'s, Self> {
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.
}
@ -507,6 +511,7 @@ pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V, qpath: &'v QPath, id: Nod
}
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);
}
@ -566,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);
}
@ -907,12 +913,18 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
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);

View file

@ -77,7 +77,7 @@ pub struct LoweringContext<'a> {
pub trait Resolver {
// Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def;
fn resolve_generated_global_path(&mut self, path: &mut hir::Path, is_value: bool);
// Obtain the resolution for a node id
fn get_resolution(&mut self, id: NodeId) -> Option<PathResolution>;
@ -154,6 +154,15 @@ fn next_id(&self) -> NodeId {
self.sess.next_node_id()
}
fn expect_full_def(&mut self, id: NodeId) -> Def {
self.resolver.get_resolution(id).map_or(Def::Err, |pr| {
if pr.depth != 0 {
bug!("path not fully resolved: {:?}", pr);
}
pr.base_def
})
}
fn diagnostic(&self) -> &errors::Handler {
self.sess.diagnostic()
}
@ -181,6 +190,19 @@ fn lower_opt_sp_ident(&mut self, o_id: Option<Spanned<Ident>>) -> Option<Spanned
o_id.map(|sp_ident| respan(sp_ident.span, sp_ident.node.name))
}
fn lower_label(&mut self, id: NodeId, label: Option<Spanned<Ident>>) -> Option<hir::Label> {
label.map(|sp_ident| {
hir::Label {
span: sp_ident.span,
name: sp_ident.node.name,
loop_id: match self.expect_full_def(id) {
Def::Label(loop_id) => loop_id,
_ => DUMMY_NODE_ID
}
}
})
}
fn lower_attrs(&mut self, attrs: &Vec<Attribute>) -> hir::HirVec<Attribute> {
attrs.clone().into()
}
@ -286,6 +308,7 @@ fn lower_qpath(&mut self,
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) {
(Some(j), ParamMode::Optional) if i < j => {
@ -353,12 +376,14 @@ fn lower_qpath(&mut self,
}
fn lower_path_extra(&mut self,
id: NodeId,
p: &Path,
name: Option<Name>,
param_mode: ParamMode)
-> hir::Path {
hir::Path {
global: p.global,
def: self.expect_full_def(id),
segments: p.segments.iter().map(|segment| {
self.lower_path_segment(segment, param_mode)
}).chain(name.map(|name| {
@ -372,10 +397,11 @@ fn lower_path_extra(&mut self,
}
fn lower_path(&mut self,
id: NodeId,
p: &Path,
param_mode: ParamMode)
-> hir::Path {
self.lower_path_extra(p, None, param_mode)
self.lower_path_extra(id, p, None, param_mode)
}
fn lower_path_segment(&mut self,
@ -569,7 +595,7 @@ fn lower_where_predicate(&mut self, pred: &WherePredicate) -> hir::WherePredicat
span}) => {
hir::WherePredicate::EqPredicate(hir::WhereEqPredicate {
id: id,
path: self.lower_path(path, ParamMode::Explicit),
path: self.lower_path(id, path, ParamMode::Explicit),
ty: self.lower_ty(ty),
span: span,
})
@ -599,7 +625,7 @@ fn lower_variant_data(&mut self, vdata: &VariantData) -> hir::VariantData {
fn lower_trait_ref(&mut self, p: &TraitRef) -> hir::TraitRef {
hir::TraitRef {
path: self.lower_path(&p.path, ParamMode::Explicit),
path: self.lower_path(p.ref_id, &p.path, ParamMode::Explicit),
ref_id: p.ref_id,
}
}
@ -665,6 +691,7 @@ fn lower_block(&mut self, b: &Block) -> P<hir::Block> {
}
fn lower_item_kind(&mut self,
id: NodeId,
name: &mut Name,
attrs: &hir::HirVec<Attribute>,
vis: &mut hir::Visibility,
@ -690,7 +717,7 @@ fn lower_item_kind(&mut self,
Some(ident.name)
};
let mut path = self.lower_path_extra(path, suffix,
let mut path = self.lower_path_extra(import.id, path, suffix,
ParamMode::Explicit);
path.span = span;
self.items.insert(import.id, hir::Item {
@ -705,7 +732,7 @@ fn lower_item_kind(&mut self,
path
}
};
let path = P(self.lower_path(path, ParamMode::Explicit));
let path = P(self.lower_path(id, path, ParamMode::Explicit));
let kind = match view_path.node {
ViewPathSimple(ident, _) => {
*name = ident.name;
@ -901,7 +928,7 @@ pub fn lower_item(&mut self, i: &Item) -> hir::Item {
let attrs = self.lower_attrs(&i.attrs);
let mut vis = self.lower_visibility(&i.vis);
let node = self.with_parent_def(i.id, |this| {
this.lower_item_kind(&mut name, &attrs, &mut vis, &i.node)
this.lower_item_kind(i.id, &mut name, &attrs, &mut vis, &i.node)
});
hir::Item {
@ -1012,14 +1039,24 @@ fn lower_pat(&mut self, p: &Pat) -> P<hir::Pat> {
self.with_parent_def(p.id, |this| {
match this.resolver.get_resolution(p.id).map(|d| d.base_def) {
// `None` can occur in body-less function signatures
None | Some(Def::Local(..)) => {
def @ None | def @ Some(Def::Local(_)) => {
let def_id = def.map(|d| d.def_id()).unwrap_or_else(|| {
this.resolver.definitions().local_def_id(p.id)
});
hir::PatKind::Binding(this.lower_binding_mode(binding_mode),
def_id,
respan(pth1.span, pth1.node.name),
sub.as_ref().map(|x| this.lower_pat(x)))
}
_ => {
let path = hir::Path::from_name(pth1.span, pth1.node.name);
hir::PatKind::Path(hir::QPath::Resolved(None, P(path)))
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)
],
})))
}
}
})
@ -1120,8 +1157,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
let inplace_finalize = ["ops", "InPlace", "finalize"];
let make_call = |this: &mut LoweringContext, p, args| {
let path = this.std_path(e.span, p);
let path = this.expr_path(path, ThinVec::new());
let path = this.expr_std_path(e.span, p, ThinVec::new());
P(this.expr_call(e.span, path, args))
};
@ -1315,13 +1351,12 @@ fn make_struct(this: &mut LoweringContext,
ast_expr: &Expr,
path: &[&str],
fields: &[(&str, &P<Expr>)]) -> hir::Expr {
let struct_path = this.std_path(ast_expr.span,
&iter::once(&"ops").chain(path)
.map(|s| *s)
.collect::<Vec<_>>());
let struct_path = &iter::once(&"ops").chain(path).map(|s| *s)
.collect::<Vec<_>>();
let hir_expr = if fields.len() == 0 {
this.expr_path(struct_path, ast_expr.attrs.clone())
this.expr_std_path(ast_expr.span, struct_path,
ast_expr.attrs.clone())
} else {
let fields = fields.into_iter().map(|&(s, e)| {
let expr = P(this.lower_expr(&e));
@ -1334,7 +1369,7 @@ fn make_struct(this: &mut LoweringContext,
}).collect();
let attrs = ast_expr.attrs.clone();
this.expr_struct(ast_expr.span, struct_path, fields, None, attrs)
this.expr_std_struct(ast_expr.span, struct_path, fields, None, attrs)
};
this.signal_block_expr(hir_vec![],
@ -1378,10 +1413,10 @@ fn make_struct(this: &mut LoweringContext,
hir::ExprPath(self.lower_qpath(e.id, qself, path, ParamMode::Optional))
}
ExprKind::Break(opt_ident, ref opt_expr) => {
hir::ExprBreak(self.lower_opt_sp_ident(opt_ident),
hir::ExprBreak(self.lower_label(e.id, opt_ident),
opt_expr.as_ref().map(|x| P(self.lower_expr(x))))
}
ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_opt_sp_ident(opt_ident)),
ExprKind::Continue(opt_ident) => hir::ExprAgain(self.lower_label(e.id, opt_ident)),
ExprKind::Ret(ref e) => hir::ExprRet(e.as_ref().map(|x| P(self.lower_expr(x)))),
ExprKind::InlineAsm(ref asm) => {
let hir_asm = hir::InlineAsm {
@ -1608,10 +1643,10 @@ fn make_struct(this: &mut LoweringContext,
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let match_expr = {
let next_path = self.std_path(e.span, &["iter", "Iterator", "next"]);
let iter = P(self.expr_ident(e.span, iter, iter_pat.id));
let ref_mut_iter = self.expr_mut_addr_of(e.span, iter);
let next_path = self.expr_path(next_path, ThinVec::new());
let next_path = &["iter", "Iterator", "next"];
let next_path = self.expr_std_path(e.span, next_path, ThinVec::new());
let next_expr = P(self.expr_call(e.span, next_path,
hir_vec![ref_mut_iter]));
let arms = hir_vec![pat_arm, break_arm];
@ -1638,10 +1673,8 @@ fn make_struct(this: &mut LoweringContext,
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = {
let into_iter_path = self.std_path(e.span,
&["iter", "IntoIterator", "into_iter"]);
let into_iter = self.expr_path(into_iter_path, ThinVec::new());
let into_iter_path = &["iter", "IntoIterator", "into_iter"];
let into_iter = self.expr_std_path(e.span, into_iter_path, ThinVec::new());
P(self.expr_call(e.span, into_iter, hir_vec![head]))
};
@ -1684,8 +1717,8 @@ fn make_struct(this: &mut LoweringContext,
hir::PopUnstableBlock,
ThinVec::new());
let path = self.std_path(e.span, &["ops", "Carrier", "translate"]);
let path = self.expr_path(path, ThinVec::new());
let path = &["ops", "Carrier", "translate"];
let path = self.expr_std_path(e.span,path, ThinVec::new());
let call = P(self.expr_call(e.span, path, hir_vec![sub_expr]));
P(self.signal_block_expr(hir_vec![],
@ -1710,15 +1743,15 @@ fn make_struct(this: &mut LoweringContext,
let err_ident = self.str_to_ident("err");
let err_local = self.pat_ident(e.span, err_ident);
let from_expr = {
let path = self.std_path(e.span, &["convert", "From", "from"]);
let from = self.expr_path(path, ThinVec::new());
let path = &["convert", "From", "from"];
let from = self.expr_std_path(e.span, path, ThinVec::new());
let err_expr = self.expr_ident(e.span, err_ident, err_local.id);
self.expr_call(e.span, from, hir_vec![err_expr])
};
let from_err_expr = {
let path = self.std_path(e.span, &["ops", "Carrier", "from_error"]);
let from_err = self.expr_path(path, ThinVec::new());
let path = &["ops", "Carrier", "from_error"];
let from_err = self.expr_std_path(e.span, path, ThinVec::new());
P(self.expr_call(e.span, from_err, hir_vec![from_expr]))
};
@ -1794,7 +1827,7 @@ fn lower_visibility(&mut self, v: &Visibility) -> hir::Visibility {
Visibility::Crate(_) => hir::Visibility::Crate,
Visibility::Restricted { ref path, id } => {
hir::Visibility::Restricted {
path: P(self.lower_path(path, ParamMode::Explicit)),
path: P(self.lower_path(id, path, ParamMode::Explicit)),
id: id
}
}
@ -1880,14 +1913,18 @@ fn expr_call(&mut self, span: Span, e: P<hir::Expr>, args: hir::HirVec<hir::Expr
}
fn expr_ident(&mut self, span: Span, id: Name, binding: NodeId) -> hir::Expr {
let path = self.path_ident(span, id);
let expr_path = hir::ExprPath(hir::QPath::Resolved(None, P(path)));
let expr = self.expr(span, expr_path, ThinVec::new());
let def = {
let defs = self.resolver.definitions();
Def::Local(defs.local_def_id(binding))
};
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)],
})));
let expr = self.expr(span, expr_path, ThinVec::new());
self.resolver.record_resolution(expr.id, def);
expr
@ -1897,9 +1934,14 @@ fn expr_mut_addr_of(&mut self, span: Span, e: P<hir::Expr>) -> hir::Expr {
self.expr(span, hir::ExprAddrOf(hir::MutMutable, e), ThinVec::new())
}
fn expr_path(&mut self, path: hir::Path, attrs: ThinVec<Attribute>) -> P<hir::Expr> {
let def = self.resolver.resolve_generated_global_path(&path, true);
let expr = self.expr(path.span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs);
fn expr_std_path(&mut self,
span: Span,
components: &[&str],
attrs: ThinVec<Attribute>)
-> P<hir::Expr> {
let path = self.std_path(span, components, true);
let def = path.def;
let expr = self.expr(span, hir::ExprPath(hir::QPath::Resolved(None, P(path))), attrs);
self.resolver.record_resolution(expr.id, def);
P(expr)
}
@ -1921,15 +1963,16 @@ fn expr_tuple(&mut self, sp: Span, exprs: hir::HirVec<hir::Expr>) -> P<hir::Expr
P(self.expr(sp, hir::ExprTup(exprs), ThinVec::new()))
}
fn expr_struct(&mut self,
sp: Span,
path: hir::Path,
fields: hir::HirVec<hir::Field>,
e: Option<P<hir::Expr>>,
attrs: ThinVec<Attribute>) -> P<hir::Expr> {
let def = self.resolver.resolve_generated_global_path(&path, false);
fn expr_std_struct(&mut self,
span: Span,
components: &[&str],
fields: hir::HirVec<hir::Field>,
e: Option<P<hir::Expr>>,
attrs: ThinVec<Attribute>) -> P<hir::Expr> {
let path = self.std_path(span, components, false);
let def = path.def;
let qpath = hir::QPath::Resolved(None, P(path));
let expr = self.expr(sp, hir::ExprStruct(qpath, fields, e), attrs);
let expr = self.expr(span, hir::ExprStruct(qpath, fields, e), attrs);
self.resolver.record_resolution(expr.id, def);
P(expr)
}
@ -1988,28 +2031,28 @@ fn block_all(&mut self, span: Span, stmts: hir::HirVec<hir::Stmt>, expr: Option<
}
fn pat_ok(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
let path = self.std_path(span, &["result", "Result", "Ok"]);
self.pat_enum(span, path, hir_vec![pat])
self.pat_std_enum(span, &["result", "Result", "Ok"], hir_vec![pat])
}
fn pat_err(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
let path = self.std_path(span, &["result", "Result", "Err"]);
self.pat_enum(span, path, hir_vec![pat])
self.pat_std_enum(span, &["result", "Result", "Err"], hir_vec![pat])
}
fn pat_some(&mut self, span: Span, pat: P<hir::Pat>) -> P<hir::Pat> {
let path = self.std_path(span, &["option", "Option", "Some"]);
self.pat_enum(span, path, hir_vec![pat])
self.pat_std_enum(span, &["option", "Option", "Some"], hir_vec![pat])
}
fn pat_none(&mut self, span: Span) -> P<hir::Pat> {
let path = self.std_path(span, &["option", "Option", "None"]);
self.pat_enum(span, path, hir_vec![])
self.pat_std_enum(span, &["option", "Option", "None"], hir_vec![])
}
fn pat_enum(&mut self, span: Span, path: hir::Path, subpats: hir::HirVec<P<hir::Pat>>)
-> P<hir::Pat> {
let def = self.resolver.resolve_generated_global_path(&path, true);
fn pat_std_enum(&mut self,
span: Span,
components: &[&str],
subpats: hir::HirVec<P<hir::Pat>>)
-> P<hir::Pat> {
let path = self.std_path(span, components, true);
let def = path.def;
let qpath = hir::QPath::Resolved(None, P(path));
let pt = if subpats.is_empty() {
hir::PatKind::Path(qpath)
@ -2027,25 +2070,27 @@ fn pat_ident(&mut self, span: Span, name: Name) -> P<hir::Pat> {
fn pat_ident_binding_mode(&mut self, span: Span, name: Name, bm: hir::BindingMode)
-> P<hir::Pat> {
let pat_ident = hir::PatKind::Binding(bm,
Spanned {
span: span,
node: name,
},
None);
let pat = self.pat(span, pat_ident);
let id = self.next_id();
let parent_def = self.parent_def;
let def = {
let def_id = {
let defs = self.resolver.definitions();
let def_path_data = DefPathData::Binding(name.as_str());
let def_index = defs.create_def_with_parent(parent_def, pat.id, def_path_data);
Def::Local(DefId::local(def_index))
let def_index = defs.create_def_with_parent(parent_def, id, def_path_data);
DefId::local(def_index)
};
self.resolver.record_resolution(pat.id, def);
self.resolver.record_resolution(id, Def::Local(def_id));
pat
P(hir::Pat {
id: id,
node: hir::PatKind::Binding(bm,
def_id,
Spanned {
span: span,
node: name,
},
None),
span: span,
})
}
fn pat_wild(&mut self, span: Span) -> P<hir::Pat> {
@ -2060,64 +2105,25 @@ fn pat(&mut self, span: Span, pat: hir::PatKind) -> P<hir::Pat> {
})
}
fn path_ident(&mut self, span: Span, id: Name) -> hir::Path {
self.path(span, vec![id])
}
/// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
/// `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);
fn path(&mut self, span: Span, strs: Vec<Name>) -> hir::Path {
self.path_all(span, false, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new())
}
fn path_global(&mut self, span: Span, strs: Vec<Name>) -> hir::Path {
self.path_all(span, true, strs, hir::HirVec::new(), hir::HirVec::new(), hir::HirVec::new())
}
fn path_all(&mut self,
sp: Span,
global: bool,
mut names: Vec<Name>,
lifetimes: hir::HirVec<hir::Lifetime>,
types: hir::HirVec<P<hir::Ty>>,
bindings: hir::HirVec<hir::TypeBinding>)
-> hir::Path {
let last_identifier = names.pop().unwrap();
let mut segments: Vec<hir::PathSegment> = names.into_iter().map(|name| {
hir::PathSegment {
name: name,
parameters: hir::PathParameters::none(),
}
let segments: Vec<_> = idents.map(|name| {
hir::PathSegment::from_name(Symbol::intern(name))
}).collect();
segments.push(hir::PathSegment {
name: last_identifier,
parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
lifetimes: lifetimes,
types: types,
infer_types: true,
bindings: bindings,
}),
});
hir::Path {
span: sp,
global: global,
let mut path = hir::Path {
span: span,
global: true,
def: Def::Err,
segments: segments.into(),
}
}
};
fn std_path_components(&mut self, components: &[&str]) -> Vec<Name> {
let mut v = Vec::new();
if let Some(s) = self.crate_root {
v.push(Symbol::intern(s));
}
v.extend(components.iter().map(|s| Symbol::intern(s)));
return v;
}
// Given suffix ["b","c","d"], returns path `::std::b::c::d` when
// `fld.cx.use_std`, and `::core::b::c::d` otherwise.
fn std_path(&mut self, span: Span, components: &[&str]) -> hir::Path {
let idents = self.std_path_components(components);
self.path_global(span, idents)
self.resolver.resolve_generated_global_path(&mut path, is_value);
path
}
fn signal_block_expr(&mut self,

View file

@ -436,7 +436,7 @@ fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
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);
}

View file

@ -658,7 +658,7 @@ pub fn name(&self, id: NodeId) -> Name {
NodeVariant(v) => v.node.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))
}

View file

@ -107,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>,
}
@ -123,21 +125,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
}
}
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)]
@ -153,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>`
@ -571,7 +568,8 @@ 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 `..`.
@ -944,9 +942,9 @@ pub enum Expr_ {
/// 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>>),
@ -1022,6 +1020,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,
@ -1225,7 +1230,7 @@ pub enum 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))),
@ -1241,7 +1246,7 @@ pub fn to_self(&self) -> Option<ExplicitSelf> {
}
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

View file

@ -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,144 +50,144 @@ fn enumerate_and_adjust(self, expected_len: usize, gap_pos: Option<usize>)
}
}
pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Lit(_) |
PatKind::Range(..) |
PatKind::Path(hir::QPath::Resolved(Some(..), _)) |
PatKind::Path(hir::QPath::TypeRelative(..)) => true,
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::TupleStruct(..) |
PatKind::Path(hir::QPath::Resolved(..)) |
PatKind::Struct(..) => {
match dm.get(&pat.id).map(|d| d.full_def()) {
Some(Def::Variant(..)) | Some(Def::VariantCtor(..)) => true,
_ => false
}
}
PatKind::Slice(..) => true,
_ => false
}
}
pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Path(hir::QPath::TypeRelative(..)) => true,
PatKind::Path(hir::QPath::Resolved(..)) => {
match dm.get(&pat.id).map(|d| d.full_def()) {
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
_ => 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 {
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),
_ => (),
}
}
});
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,
})
}
/// 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.
}
_ => true
}
});
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 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(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
let mut variants = vec![];
pat.walk(|p| {
match p.node {
PatKind::TupleStruct(..) |
PatKind::Path(hir::QPath::Resolved(..)) |
PatKind::Struct(..) => {
match dm.get(&p.id).map(|d| d.full_def()) {
Some(Def::Variant(id)) |
Some(Def::VariantCtor(id, ..)) => variants.push(id),
_ => ()
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
}
true
});
variants.sort();
variants.dedup();
variants
}
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
}
}
/// 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
});
}
/// 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
}
});
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 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
}
});
contains_bindings
}
pub fn simple_name(&self) -> Option<ast::Name> {
match self.node {
PatKind::Binding(hir::BindByValue(..), _, ref path1, None) => {
Some(path1.node)
}
_ => {
None
}
}
}
/// 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
}
/// 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),
_ => (),
}
}
});
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,
})
}
}

View file

@ -1481,11 +1481,11 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
hir::ExprPath(ref qpath) => {
self.print_qpath(qpath, 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 {
@ -1493,11 +1493,11 @@ pub fn print_expr(&mut self, expr: &hir::Expr) -> io::Result<()> {
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)?
}
}
@ -1782,7 +1782,7 @@ pub fn print_pat(&mut self, pat: &hir::Pat) -> io::Result<()> {
// 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")?;
@ -2185,7 +2185,7 @@ pub fn print_arg(&mut self, input: &hir::Arg, is_closure: bool) -> io::Result<()
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

View file

@ -1441,7 +1441,7 @@ fn rebuild_arg_ty_or_output(&self,
ty_queue.push(&mut_ty.ty);
}
hir::TyPath(hir::QPath::Resolved(ref maybe_qself, ref path)) => {
match self.tcx.expect_def(cur_ty.id) {
match path.def {
Def::Enum(did) | Def::TyAlias(did) |
Def::Struct(did) | Def::Union(did) => {
let generics = self.tcx.item_generics(did);
@ -1621,6 +1621,7 @@ fn rebuild_path(&self,
hir::Path {
span: path.span,
global: path.global,
def: path.def,
segments: new_segs.into()
}
}

View file

@ -71,7 +71,7 @@ pub fn prim_ty_to_ty(self,
/// to it.
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) = self.expect_def(ast_ty.id) {
if let Def::PrimTy(nty) = path.def {
Some(self.prim_ty_to_ty(&path.segments, nty))
} else {
None

View file

@ -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 @@ fn insert_def_id(&mut self, def_id: DefId) {
}
}
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 @@ fn handle_tup_field_access(&mut self, lhs: &hir::Expr, idx: usize) {
}
}
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,8 +236,9 @@ fn visit_variant_data(&mut self, def: &hir::VariantData, _: ast::Name,
fn visit_expr(&mut self, expr: &hir::Expr) {
match expr.node {
hir::ExprPath(hir::QPath::TypeRelative(..)) => {
self.lookup_and_handle_definition(expr.id);
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);
@ -260,8 +257,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
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
@ -276,14 +272,13 @@ fn visit_arm(&mut self, arm: &hir::Arm) {
}
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);
}
_ => ()
}
@ -294,7 +289,7 @@ fn visit_pat(&mut self, pat: &hir::Pat) {
}
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);
}
}

View file

@ -186,8 +186,8 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
hir::ExprInlineAsm(..) => {
self.require_unsafe(expr.span, "use of inline assembly");
}
hir::ExprPath(hir::QPath::Resolved(..)) => {
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) {

View file

@ -19,7 +19,6 @@
use self::TrackMatchMode::*;
use self::OverloadedCallType::*;
use hir::pat_util;
use hir::def::Def;
use hir::def_id::{DefId};
use infer::InferCtxt;
@ -622,7 +621,7 @@ fn walk_local(&mut self, local: &hir::Local) {
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,7 +956,7 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat
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.
@ -965,8 +964,8 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat
// 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 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat
// 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 @@ fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: Mat
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)
_ => {}
}
}));
}

View file

@ -160,11 +160,10 @@ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl,
impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> {
fn visit_expr(&mut self, expr: &hir::Expr) {
let def = match expr.node {
hir::ExprPath(_) => {
self.infcx.tcx.expect_def(expr.id)
}
_ => Def::Err
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) => {

View file

@ -111,7 +111,6 @@
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 @@ fn variable(&self, node_id: NodeId, span: Span) -> Variable {
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 @@ fn write_vars<F>(&self,
}
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 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
match expr.node {
// Interesting cases with control flow or which gen/kill
hir::ExprPath(hir::QPath::Resolved(..)) => {
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 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
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 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
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
@ -1246,8 +1235,8 @@ fn propagate_through_lvalue_components(&mut self,
fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
-> LiveNode {
match expr.node {
hir::ExprPath(hir::QPath::Resolved(..)) => {
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 @@ fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
}
}
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
@ -1482,8 +1471,8 @@ fn check_ret(&self,
fn check_lvalue(&mut self, expr: &Expr) {
match expr.node {
hir::ExprPath(hir::QPath::Resolved(..)) => {
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 @@ fn should_warn(&self, var: Variable) -> Option<String> {
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;

View file

@ -488,8 +488,9 @@ pub fn cat_expr_unadjusted(&self, expr: &hir::Expr) -> McResult<cmt<'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.tcx().tables().qpath_def(qpath, expr.id);
self.cat_def(expr.id, expr.span, expr_ty, def)
}
hir::ExprType(ref e, _) => {
@ -1062,24 +1063,32 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F) -> McResul
// 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.tcx().tables().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()

View file

@ -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);
}
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.borrow().method_map[&method_call].def_id;
Some(Def::Method(def_id))
}
_ => None
};
// If this wasn't a static, then the destination is
// surely reachable.
_ => {
self.reachable_symbols.insert(node_id);
}
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);
}
// If this wasn't a static, then the destination is
// surely reachable.
_ => {
self.reachable_symbols.insert(node_id);
}
}
}
}
hir::ExprMethodCall(..) => {
let method_call = ty::MethodCall::expr(expr.id);
let def_id = self.tcx.tables().method_map[&method_call].def_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)
}
self.reachable_symbols.insert(node_id);
}
}
_ => {}
}
intravisit::walk_expr(self, expr)

View file

@ -21,7 +21,7 @@
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 @@ enum 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);
@ -247,8 +244,8 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
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 @@ fn with<F>(&mut self, wrap_scope: ScopeChain, f: F) where
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(),
};

View file

@ -468,8 +468,8 @@ fn visit_expr(&mut self, ex: &'tcx hir::Expr) {
intravisit::walk_expr(self, ex);
}
fn visit_path(&mut self, path: &'tcx hir::Path, id: ast::NodeId) {
check_path(self.tcx, path, id,
fn visit_path(&mut self, path: &'tcx hir::Path, _: ast::NodeId) {
check_path(self.tcx, path,
&mut |id, sp, stab, depr| self.check(id, sp, stab, depr));
intravisit::walk_path(self, path)
}
@ -526,7 +526,7 @@ pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// individually as it's possible to have a stable trait with unstable
// items.
hir::ItemImpl(.., Some(ref t), _, ref impl_item_refs) => {
let trait_did = tcx.expect_def(t.ref_id).def_id();
let trait_did = t.path.def.def_id();
for impl_item_ref in impl_item_refs {
let impl_item = tcx.map.impl_item(impl_item_ref.id);
let item = tcx.associated_items(trait_did)
@ -553,9 +553,9 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
let method_call = ty::MethodCall::expr(e.id);
tcx.tables().method_map[&method_call].def_id
}
hir::ExprPath(hir::QPath::TypeRelative(..)) => {
hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => {
span = e.span;
tcx.expect_def(e.id).def_id()
tcx.tables().qpath_def(qpath, e.id).def_id()
}
hir::ExprField(ref base_e, ref field) => {
span = field.span;
@ -611,14 +611,13 @@ pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
}
pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
path: &hir::Path, id: ast::NodeId,
path: &hir::Path,
cb: &mut FnMut(DefId, Span,
&Option<&Stability>,
&Option<DeprecationEntry>)) {
// Paths in import prefixes may have no resolution.
match tcx.expect_def_or_none(id) {
None | Some(Def::PrimTy(..)) | Some(Def::SelfTy(..)) => {}
Some(def) => maybe_do_stability_check(tcx, def.def_id(), path.span, cb)
match path.def {
Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => {}
_ => maybe_do_stability_check(tcx, path.def.def_id(), path.span, cb)
}
}
@ -629,8 +628,8 @@ pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
debug!("check_pat(pat = {:?})", pat);
if is_internal(tcx, pat.span) { return; }
if let PatKind::Path(hir::QPath::TypeRelative(..)) = pat.node {
let def_id = tcx.expect_def(pat.id).def_id();
if let PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) = pat.node {
let def_id = tcx.tables().qpath_def(qpath, pat.id).def_id();
maybe_do_stability_check(tcx, def_id, pat.span, cb)
}
@ -665,7 +664,7 @@ pub fn check_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: &hir::Ty,
if is_internal(tcx, ty.span) { return; }
if let hir::TyPath(hir::QPath::TypeRelative(..)) = ty.node {
let def_id = tcx.expect_def(ty.id).def_id();
let def_id = tcx.tables().type_relative_path_defs[&ty.id].def_id();
maybe_do_stability_check(tcx, def_id, ty.span, cb);
}
}

View file

@ -14,7 +14,7 @@
use session::Session;
use middle;
use hir::TraitMap;
use hir::def::DefMap;
use hir::def::Def;
use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use hir::map as ast_map;
use hir::map::{DefKey, DefPathData, DisambiguatedDefPathData};
@ -201,6 +201,9 @@ pub struct CommonTypes<'tcx> {
}
pub struct Tables<'tcx> {
/// Resolved definitions for `<T>::X` associated paths.
pub type_relative_path_defs: NodeMap<Def>,
/// Stores the types for various nodes in the AST. Note that this table
/// is not guaranteed to be populated until after typeck. See
/// typeck::check::fn_ctxt for details.
@ -244,6 +247,7 @@ pub struct Tables<'tcx> {
impl<'a, 'gcx, 'tcx> Tables<'tcx> {
pub fn empty() -> Tables<'tcx> {
Tables {
type_relative_path_defs: NodeMap(),
node_types: FxHashMap(),
item_substs: NodeMap(),
adjustments: NodeMap(),
@ -256,6 +260,16 @@ pub fn empty() -> Tables<'tcx> {
}
}
/// Returns the final resolution of a `QPath` in an `Expr` or `Pat` node.
pub fn qpath_def(&self, qpath: &hir::QPath, id: NodeId) -> Def {
match *qpath {
hir::QPath::Resolved(_, ref path) => path.def,
hir::QPath::TypeRelative(..) => {
self.type_relative_path_defs.get(&id).cloned().unwrap_or(Def::Err)
}
}
}
pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> {
match self.node_id_to_type_opt(id) {
Some(ty) => ty,
@ -379,11 +393,6 @@ pub struct GlobalCtxt<'tcx> {
pub sess: &'tcx Session,
/// Map from path id to the results from resolve; generated
/// initially by resolve and updated during typeck in some cases
/// (e.g., UFCS paths)
pub def_map: RefCell<DefMap>,
/// Map indicating what traits are in scope for places where this
/// is relevant; generated by resolve.
pub trait_map: TraitMap,
@ -768,7 +777,6 @@ fn is_global(self) -> bool {
/// reference to the context, to allow formatting values that need it.
pub fn create_and_enter<F, R>(s: &'tcx Session,
arenas: &'tcx CtxtArenas<'tcx>,
def_map: DefMap,
trait_map: TraitMap,
named_region_map: resolve_lifetime::NamedRegionMap,
map: ast_map::Map<'tcx>,
@ -797,7 +805,6 @@ pub fn create_and_enter<F, R>(s: &'tcx Session,
item_variance_map: RefCell::new(DepTrackingMap::new(dep_graph.clone())),
variance_computed: Cell::new(false),
sess: s,
def_map: RefCell::new(def_map),
trait_map: trait_map,
tables: RefCell::new(Tables::empty()),
impl_trait_refs: RefCell::new(DepTrackingMap::new(dep_graph.clone())),

View file

@ -19,7 +19,7 @@
use dep_graph::{self, DepNode};
use hir::map as ast_map;
use middle;
use hir::def::{Def, CtorKind, PathResolution, ExportMap};
use hir::def::{Def, CtorKind, ExportMap};
use hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
use middle::region::{CodeExtent, ROOT_CODE_EXTENT};
@ -247,7 +247,7 @@ pub fn from_hir(visibility: &hir::Visibility, id: NodeId, tcx: TyCtxt) -> Self {
match *visibility {
hir::Public => Visibility::Public,
hir::Visibility::Crate => Visibility::Restricted(ast::CRATE_NODE_ID),
hir::Visibility::Restricted { id, .. } => match tcx.expect_def(id) {
hir::Visibility::Restricted { ref path, .. } => match path.def {
// If there is no resolution, `resolve` will have already reported an error, so
// assume that the visibility is public to avoid reporting more privacy errors.
Def::Err => Visibility::Public,
@ -2047,7 +2047,7 @@ pub fn local_var_name_str(self, id: NodeId) -> InternedString {
match self.map.find(id) {
Some(ast_map::NodeLocal(pat)) => {
match pat.node {
hir::PatKind::Binding(_, ref path1, _) => path1.node.as_str(),
hir::PatKind::Binding(_, _, ref path1, _) => path1.node.as_str(),
_ => {
bug!("Variable id {} maps to {:?}, not local", id, pat);
},
@ -2059,8 +2059,8 @@ pub fn local_var_name_str(self, id: NodeId) -> InternedString {
pub fn expr_is_lval(self, expr: &hir::Expr) -> bool {
match expr.node {
hir::ExprPath(hir::QPath::Resolved(..)) => {
match self.expect_def(expr.id) {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
match path.def {
Def::Local(..) | Def::Upvar(..) | Def::Static(..) | Def::Err => true,
_ => false,
}
@ -2298,22 +2298,6 @@ pub fn impl_trait_ref(self, id: DefId) -> Option<TraitRef<'gcx>> {
|| self.sess.cstore.impl_trait_ref(self.global_tcx(), id))
}
/// Returns a path resolution for node id if it exists, panics otherwise.
pub fn expect_resolution(self, id: NodeId) -> PathResolution {
*self.def_map.borrow().get(&id).expect("no def-map entry for node id")
}
/// Returns a fully resolved definition for node id if it exists, panics otherwise.
pub fn expect_def(self, id: NodeId) -> Def {
self.expect_resolution(id).full_def()
}
/// Returns a fully resolved definition for node id if it exists, or none if no
/// definition exists, panics on partial resolutions to catch errors.
pub fn expect_def_or_none(self, id: NodeId) -> Option<Def> {
self.def_map.borrow().get(&id).map(|resolution| resolution.full_def())
}
// Returns `ty::VariantDef` if `def` refers to a struct,
// or variant or their constructors, panics otherwise.
pub fn expect_variant_def(self, def: Def) -> VariantDef<'tcx> {

View file

@ -14,7 +14,6 @@
use hir::map::DefPathData;
use infer::InferCtxt;
use hir::map as ast_map;
use hir::pat_util;
use traits::{self, Reveal};
use ty::{self, Ty, AdtKind, TyCtxt, TypeAndMut, TypeFlags, TypeFoldable};
use ty::{Disr, ParameterEnvironment};
@ -180,14 +179,6 @@ pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn pat_contains_ref_binding(self, pat: &hir::Pat) -> Option<hir::Mutability> {
pat_util::pat_contains_ref_binding(pat)
}
pub fn arm_contains_ref_binding(self, arm: &hir::Arm) -> Option<hir::Mutability> {
pat_util::arm_contains_ref_binding(arm)
}
pub fn has_error_field(self, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::TyAdt(def, substs) => {

View file

@ -98,7 +98,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
move_pat: &hir::Pat,
cmt: mc::cmt<'tcx>) {
let pat_span_path_opt = match move_pat.node {
PatKind::Binding(_, ref path1, _) => {
PatKind::Binding(_, _, ref path1, _) => {
Some(MoveSpanAndPath{span: move_pat.span,
name: path1.node})
},

View file

@ -23,8 +23,8 @@
use pattern::{FieldPattern, Pattern, PatternKind};
use pattern::{PatternFoldable, PatternFolder};
use rustc::hir::def_id::{DefId};
use rustc::hir::pat_util::def_to_path;
use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc::hir;
@ -324,7 +324,12 @@ fn apply_constructor<'a, 'tcx>(
ty::TyAdt(adt, _) => {
let v = ctor.variant_for_adt(adt);
let qpath = hir::QPath::Resolved(None, P(def_to_path(cx.tcx, v.did)));
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(),
}));
match v.ctor_kind {
CtorKind::Fictive => {
let field_pats: hir::HirVec<_> = v.fields.iter()

View file

@ -19,8 +19,6 @@
use rustc::dep_graph::DepNode;
use rustc::hir::pat_util::{pat_bindings, pat_contains_bindings};
use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
use rustc::middle::expr_use_visitor::{LoanCause, MutateMode};
use rustc::middle::expr_use_visitor as euv;
@ -262,26 +260,22 @@ fn check_irrefutable(&self, pat: &Pat, is_fn_arg: bool) {
fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) {
pat.walk(|p| {
if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), name, None) = p.node {
if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), _, name, None) = p.node {
let pat_ty = cx.tcx.tables().pat_ty(p);
if let ty::TyAdt(edef, _) = pat_ty.sty {
if edef.is_enum() {
if let Def::Local(..) = cx.tcx.expect_def(p.id) {
if edef.variants.iter().any(|variant| {
variant.name == name.node && variant.ctor_kind == CtorKind::Const
}) {
let ty_path = cx.tcx.item_path_str(edef.did);
let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
"pattern binding `{}` is named the same as one \
of the variants of the type `{}`",
name.node, ty_path);
help!(err,
"if you meant to match on a variant, \
consider making the path in the pattern qualified: `{}::{}`",
ty_path, name.node);
err.emit();
}
}
if edef.is_enum() && edef.variants.iter().any(|variant| {
variant.name == name.node && variant.ctor_kind == CtorKind::Const
}) {
let ty_path = cx.tcx.item_path_str(edef.did);
let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
"pattern binding `{}` is named the same as one \
of the variants of the type `{}`",
name.node, ty_path);
help!(err,
"if you meant to match on a variant, \
consider making the path in the pattern qualified: `{}::{}`",
ty_path, name.node);
err.emit();
}
}
}
@ -290,13 +284,13 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchVisitor, pat: &Pat) {
}
/// Checks for common cases of "catchall" patterns that may not be intended as such.
fn pat_is_catchall(dm: &DefMap, pat: &Pat) -> bool {
fn pat_is_catchall(pat: &Pat) -> bool {
match pat.node {
PatKind::Binding(.., None) => true,
PatKind::Binding(.., Some(ref s)) => pat_is_catchall(dm, s),
PatKind::Ref(ref s, _) => pat_is_catchall(dm, s),
PatKind::Binding(.., Some(ref s)) => pat_is_catchall(s),
PatKind::Ref(ref s, _) => pat_is_catchall(s),
PatKind::Tuple(ref v, _) => v.iter().all(|p| {
pat_is_catchall(dm, &p)
pat_is_catchall(&p)
}),
_ => false
}
@ -374,7 +368,7 @@ fn check_arms<'a, 'tcx>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
}
if guard.is_none() {
seen.push(v);
if catchall.is_none() && pat_is_catchall(&cx.tcx.def_map.borrow(), hir_pat) {
if catchall.is_none() && pat_is_catchall(hir_pat) {
catchall = Some(pat.span);
}
}
@ -454,7 +448,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
pats: &[P<Pat>]) {
let mut by_ref_span = None;
for pat in pats {
pat_bindings(&pat, |bm, _, span, _path| {
pat.each_binding(|bm, _, span, _path| {
if let hir::BindByRef(..) = bm {
by_ref_span = Some(span);
}
@ -465,7 +459,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
// check legality of moving out of the enum
// x @ Foo(..) is legal, but x @ Foo(y) isn't.
if sub.map_or(false, |p| pat_contains_bindings(&p)) {
if sub.map_or(false, |p| p.contains_bindings()) {
struct_span_err!(cx.tcx.sess, p.span, E0007,
"cannot bind by-move with sub-bindings")
.span_label(p.span, &format!("binds an already bound by-move value by moving it"))
@ -486,7 +480,7 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor,
for pat in pats {
pat.walk(|p| {
if let PatKind::Binding(hir::BindByValue(..), _, ref sub) = p.node {
if let PatKind::Binding(hir::BindByValue(..), _, _, ref sub) = p.node {
let pat_ty = cx.tcx.tables().node_id_to_type(p.id);
if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) {
check_move(p, sub.as_ref().map(|p| &**p));

View file

@ -19,9 +19,8 @@
use rustc::hir::map::blocks::FnLikeNode;
use rustc::middle::cstore::InlinedItem;
use rustc::traits;
use rustc::hir::def::{Def, CtorKind, PathResolution};
use rustc::hir::def::{Def, CtorKind};
use rustc::hir::def_id::DefId;
use rustc::hir::pat_util::def_to_path;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::util::IntTypeExt;
use rustc::ty::subst::Substs;
@ -42,7 +41,6 @@
use std::borrow::Cow;
use std::cmp::Ordering;
use std::collections::hash_map::Entry::Vacant;
use rustc_const_math::*;
use rustc_errors::DiagnosticBuilder;
@ -282,26 +280,34 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
.collect::<Result<_, _>>()?, None),
hir::ExprCall(ref callee, ref args) => {
let def = tcx.expect_def(callee.id);
if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
entry.insert(PathResolution::new(def));
}
let qpath = match def {
Def::StructCtor(def_id, CtorKind::Fn) |
Def::VariantCtor(def_id, CtorKind::Fn) => {
hir::QPath::Resolved(None, P(def_to_path(tcx, def_id)))
}
Def::Fn(..) | Def::Method(..) => return Ok(P(hir::Pat {
id: expr.id,
node: PatKind::Lit(P(expr.clone())),
span: span,
})),
let qpath = match callee.node {
hir::ExprPath(ref qpath) => qpath,
_ => bug!()
};
let pats = args.iter()
.map(|expr| const_expr_to_pat(tcx, &*expr, pat_id, span))
.collect::<Result<_, _>>()?;
PatKind::TupleStruct(qpath, pats, None)
let def = tcx.tables().qpath_def(qpath, callee.id);
let ctor_path = if let hir::QPath::Resolved(_, ref path) = *qpath {
match def {
Def::StructCtor(_, CtorKind::Fn) |
Def::VariantCtor(_, CtorKind::Fn) => {
Some(path.clone())
}
_ => None
}
} else {
None
};
match (def, ctor_path) {
(Def::Fn(..), None) | (Def::Method(..), None) => {
PatKind::Lit(P(expr.clone()))
}
(_, Some(ctor_path)) => {
let pats = args.iter()
.map(|expr| const_expr_to_pat(tcx, expr, pat_id, span))
.collect::<Result<_, _>>()?;
PatKind::TupleStruct(hir::QPath::Resolved(None, ctor_path), pats, None)
}
_ => bug!()
}
}
hir::ExprStruct(ref qpath, ref fields, None) => {
@ -326,8 +332,9 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
PatKind::Slice(pats, None, hir::HirVec::new())
}
hir::ExprPath(_) => {
match tcx.expect_def(expr.id) {
hir::ExprPath(ref qpath) => {
let def = tcx.tables().qpath_def(qpath, expr.id);
match def {
Def::StructCtor(_, CtorKind::Const) |
Def::VariantCtor(_, CtorKind::Const) => {
match expr.node {
@ -797,13 +804,8 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
Err(kind) => return Err(ConstEvalErr { span: e.span, kind: kind }),
}
}
hir::ExprPath(_) => {
// This function can be used before type checking when not all paths are fully resolved.
// FIXME: There's probably a better way to make sure we don't panic here.
let def = match tcx.expect_def_or_none(e.id) {
Some(def) => def,
None => signal!(e, UnresolvedPath)
};
hir::ExprPath(ref qpath) => {
let def = tcx.tables().qpath_def(qpath, e.id);
match def {
Def::Const(def_id) |
Def::AssociatedConst(def_id) => {
@ -854,6 +856,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
}
},
Def::Method(id) | Def::Fn(id) => Function(id),
Def::Err => signal!(e, UnresolvedPath),
_ => signal!(e, NonConstPath),
}
}
@ -882,8 +885,9 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
fn_args
)?;
debug!("const call arg: {:?}", arg);
let old = call_args.insert(tcx.expect_def(arg.pat.id).def_id(), arg_val);
assert!(old.is_none());
if let PatKind::Binding(_, def_id, _, _) = arg.pat.node {
assert!(call_args.insert(def_id, arg_val).is_none());
}
}
debug!("const call({:?})", call_args);
eval_const_expr_partial(tcx, &result, ty_hint, Some(&call_args))?
@ -1368,10 +1372,8 @@ pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
tcx, &err, count_expr.span, reason);
if let hir::ExprPath(hir::QPath::Resolved(None, ref path)) = count_expr.node {
if !path.global && path.segments.len() == 1 {
if let Some(Def::Local(..)) = tcx.expect_def_or_none(count_expr.id) {
diag.note(&format!("`{}` is a variable", path.segments[0].name));
}
if let Def::Local(..) = path.def {
diag.note(&format!("`{}` is a variable", path));
}
}

View file

@ -163,8 +163,9 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
}
}
PatKind::Path(..) => {
match self.tcx.expect_def(pat.id) {
PatKind::Path(ref qpath) => {
let def = self.tcx.tables().qpath_def(qpath, pat.id);
match def {
Def::Const(def_id) | Def::AssociatedConst(def_id) => {
let tcx = self.tcx.global_tcx();
let substs = tcx.tables().node_id_item_substs(pat.id)
@ -188,7 +189,7 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
}
}
}
_ => self.lower_variant_or_leaf(pat, vec![])
_ => self.lower_variant_or_leaf(def, vec![])
}
}
@ -242,8 +243,7 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
}
}
PatKind::Binding(bm, ref ident, ref sub) => {
let def_id = self.tcx.expect_def(pat.id).def_id();
PatKind::Binding(bm, def_id, ref ident, ref sub) => {
let id = self.tcx.map.as_local_node_id(def_id).unwrap();
let var_ty = self.tcx.tables().node_id_to_type(pat.id);
let region = match var_ty.sty {
@ -281,13 +281,14 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
}
}
PatKind::TupleStruct(_, ref subpatterns, ddpos) => {
PatKind::TupleStruct(ref qpath, ref subpatterns, ddpos) => {
let def = self.tcx.tables().qpath_def(qpath, pat.id);
let pat_ty = self.tcx.tables().node_id_to_type(pat.id);
let adt_def = match pat_ty.sty {
ty::TyAdt(adt_def, _) => adt_def,
_ => span_bug!(pat.span, "tuple struct pattern not applied to an ADT"),
};
let variant_def = adt_def.variant_of_def(self.tcx.expect_def(pat.id));
let variant_def = adt_def.variant_of_def(def);
let subpatterns =
subpatterns.iter()
@ -297,10 +298,11 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
pattern: self.lower_pattern(field),
})
.collect();
self.lower_variant_or_leaf(pat, subpatterns)
self.lower_variant_or_leaf(def, subpatterns)
}
PatKind::Struct(_, ref fields, _) => {
PatKind::Struct(ref qpath, ref fields, _) => {
let def = self.tcx.tables().qpath_def(qpath, pat.id);
let pat_ty = self.tcx.tables().node_id_to_type(pat.id);
let adt_def = match pat_ty.sty {
ty::TyAdt(adt_def, _) => adt_def,
@ -310,7 +312,7 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
"struct pattern not applied to an ADT");
}
};
let variant_def = adt_def.variant_of_def(self.tcx.expect_def(pat.id));
let variant_def = adt_def.variant_of_def(def);
let subpatterns =
fields.iter()
@ -329,7 +331,7 @@ pub fn lower_pattern(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
})
.collect();
self.lower_variant_or_leaf(pat, subpatterns)
self.lower_variant_or_leaf(def, subpatterns)
}
};
@ -418,11 +420,11 @@ fn slice_or_array_pattern(
fn lower_variant_or_leaf(
&mut self,
pat: &hir::Pat,
def: Def,
subpatterns: Vec<FieldPattern<'tcx>>)
-> PatternKind<'tcx>
{
match self.tcx.expect_def(pat.id) {
match def {
Def::Variant(variant_id) | Def::VariantCtor(variant_id, ..) => {
let enum_id = self.tcx.parent_def_id(variant_id).unwrap();
let adt_def = self.tcx.lookup_adt_def(enum_id);
@ -442,9 +444,7 @@ fn lower_variant_or_leaf(
PatternKind::Leaf { subpatterns: subpatterns }
}
def => {
span_bug!(pat.span, "inappropriate def for pattern: {:?}", def);
}
_ => bug!()
}
}
}

View file

@ -840,9 +840,7 @@ macro_rules! try_with_f {
let named_region_map = time(time_passes,
"lifetime resolution",
|| middle::resolve_lifetime::krate(sess,
&hir_map,
&resolutions.def_map))?;
|| middle::resolve_lifetime::krate(sess, &hir_map))?;
time(time_passes,
"looking for entry point",
@ -859,17 +857,16 @@ macro_rules! try_with_f {
time(time_passes,
"loop checking",
|| loops::check_crate(sess, &resolutions.def_map, &hir_map));
|| loops::check_crate(sess, &hir_map));
time(time_passes,
"static item recursion checking",
|| static_recursion::check_crate(sess, &resolutions.def_map, &hir_map))?;
|| static_recursion::check_crate(sess, &hir_map))?;
let index = stability::Index::new(&hir_map);
TyCtxt::create_and_enter(sess,
arenas,
resolutions.def_map,
resolutions.trait_map,
named_region_map,
hir_map,

View file

@ -131,12 +131,11 @@ fn test_env<F>(source_string: &str,
// run just enough stuff to build a tcx:
let lang_items = lang_items::collect_language_items(&sess, &ast_map);
let named_region_map = resolve_lifetime::krate(&sess, &ast_map, &resolutions.def_map);
let named_region_map = resolve_lifetime::krate(&sess, &ast_map);
let region_map = region::resolve_crate(&sess, &ast_map);
let index = stability::Index::new(&ast_map);
TyCtxt::create_and_enter(&sess,
&arenas,
resolutions.def_map,
resolutions.trait_map,
named_region_map.unwrap(),
ast_map,

View file

@ -23,7 +23,7 @@
use syntax::tokenstream;
use rustc::hir;
use rustc::hir::*;
use rustc::hir::def::{Def, PathResolution};
use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
use rustc::hir::intravisit as visit;
use rustc::ty::TyCtxt;
@ -335,8 +335,8 @@ fn saw_expr<'a>(node: &'a Expr_,
ExprIndex(..) => (SawExprIndex, true),
ExprPath(_) => (SawExprPath, false),
ExprAddrOf(m, _) => (SawExprAddrOf(m), false),
ExprBreak(id, _) => (SawExprBreak(id.map(|id| id.node.as_str())), false),
ExprAgain(id) => (SawExprAgain(id.map(|id| id.node.as_str())), false),
ExprBreak(label, _) => (SawExprBreak(label.map(|l| l.name.as_str())), false),
ExprAgain(label) => (SawExprAgain(label.map(|l| l.name.as_str())), false),
ExprRet(..) => (SawExprRet, false),
ExprInlineAsm(ref a,..) => (SawExprInlineAsm(a), false),
ExprStruct(..) => (SawExprStruct, false),
@ -669,6 +669,10 @@ fn visit_path(&mut self, path: &'tcx Path, _: ast::NodeId) {
visit::walk_path(self, path)
}
fn visit_def_mention(&mut self, def: Def) {
self.hash_def(def);
}
fn visit_block(&mut self, b: &'tcx Block) {
debug!("visit_block: st={:?}", self.st);
SawBlock.hash(self.st);
@ -799,11 +803,6 @@ fn hash_resolve(&mut self, id: ast::NodeId) {
// or not an entry was present (we are already hashing what
// variant it is above when we visit the HIR).
if let Some(def) = self.tcx.def_map.borrow().get(&id) {
debug!("hash_resolve: id={:?} def={:?} st={:?}", id, def, self.st);
self.hash_partial_def(def);
}
if let Some(traits) = self.tcx.trait_map.get(&id) {
debug!("hash_resolve: id={:?} traits={:?} st={:?}", id, traits, self.st);
traits.len().hash(self.st);
@ -825,11 +824,6 @@ fn hash_def_id(&mut self, def_id: DefId) {
self.compute_def_id_hash(def_id).hash(self.st);
}
fn hash_partial_def(&mut self, def: &PathResolution) {
self.hash_def(def.base_def);
def.depth.hash(self.st);
}
fn hash_def(&mut self, def: Def) {
match def {
// Crucial point: for all of these variants, the variant +

View file

@ -288,12 +288,17 @@ fn check_lifetime_def(&mut self, cx: &LateContext, t: &hir::LifetimeDef) {
}
fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
if let &PatKind::Binding(_, ref path1, _) = &p.node {
// Exclude parameter names from foreign functions (they have no `Def`)
if cx.tcx.expect_def_or_none(p.id).is_some() {
self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span));
// Exclude parameter names from foreign functions
let parent_node = cx.tcx.map.get_parent_node(p.id);
if let hir::map::NodeForeignItem(item) = cx.tcx.map.get(parent_node) {
if let hir::ForeignItemFn(..) = item.node {
return;
}
}
if let &PatKind::Binding(_, _, ref path1, _) = &p.node {
self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span));
}
}
fn check_struct_def(&mut self,
@ -378,7 +383,7 @@ 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 let Def::Const(..) = cx.tcx.expect_def(p.id) {
if let Def::Const(..) = path.def {
NonUpperCaseGlobals::check_upper_case(cx,
"constant in pattern",
path.segments[0].name,

View file

@ -167,7 +167,7 @@ fn check_pat(&mut self, cx: &LateContext, pat: &hir::Pat) {
if fieldpat.node.is_shorthand {
continue;
}
if let PatKind::Binding(_, ident, None) = fieldpat.node.pat.node {
if let PatKind::Binding(_, _, ident, None) = fieldpat.node.pat.node {
if ident.node == fieldpat.node.name {
cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS,
fieldpat.span,
@ -391,7 +391,7 @@ fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
hir::ItemImpl(.., Some(ref trait_ref), _, ref impl_item_refs) => {
// If the trait is private, add the impl items to private_traits so they don't get
// reported for missing docs.
let real_trait = cx.tcx.expect_def(trait_ref.ref_id).def_id();
let real_trait = trait_ref.path.def.def_id();
if let Some(node_id) = cx.tcx.map.as_local_node_id(real_trait) {
match cx.tcx.map.find(node_id) {
Some(hir_map::NodeItem(item)) => {
@ -697,10 +697,9 @@ fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
&mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr));
}
fn check_path(&mut self, cx: &LateContext, path: &hir::Path, id: ast::NodeId) {
fn check_path(&mut self, cx: &LateContext, path: &hir::Path, _: ast::NodeId) {
stability::check_path(cx.tcx,
path,
id,
&mut |id, sp, stab, depr| self.lint(cx, id, sp, &stab, &depr));
}
@ -926,8 +925,12 @@ fn check_fn(&mut self,
fn expr_refers_to_this_fn(tcx: TyCtxt, fn_id: ast::NodeId, id: ast::NodeId) -> bool {
match tcx.map.get(id) {
hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
tcx.expect_def_or_none(callee.id)
.map_or(false, |def| def.def_id() == tcx.map.local_def_id(fn_id))
let def = if let hir::ExprPath(ref qpath) = callee.node {
tcx.tables().qpath_def(qpath, callee.id)
} else {
return false;
};
def.def_id() == tcx.map.local_def_id(fn_id)
}
_ => false,
}
@ -965,10 +968,13 @@ fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
// Check for calls to methods via explicit paths (e.g. `T::method()`).
match tcx.map.get(id) {
hir_map::NodeExpr(&hir::Expr { node: hir::ExprCall(ref callee, _), .. }) => {
// The callee is an arbitrary expression,
// it doesn't necessarily have a definition.
match tcx.expect_def_or_none(callee.id) {
Some(Def::Method(def_id)) => {
let def = if let hir::ExprPath(ref qpath) = callee.node {
tcx.tables().qpath_def(qpath, callee.id)
} else {
return false;
};
match def {
Def::Method(def_id) => {
let substs = tcx.tables().node_id_item_substs(callee.id)
.unwrap_or_else(|| tcx.intern_substs(&[]));
method_call_refers_to_method(
@ -1201,11 +1207,12 @@ fn get_transmute_from_to<'a, 'tcx>
(cx: &LateContext<'a, 'tcx>,
expr: &hir::Expr)
-> Option<(&'tcx ty::TypeVariants<'tcx>, &'tcx ty::TypeVariants<'tcx>)> {
match expr.node {
hir::ExprPath(_) => (),
_ => return None,
}
if let Def::Fn(did) = cx.tcx.expect_def(expr.id) {
let def = if let hir::ExprPath(ref qpath) = expr.node {
cx.tcx.tables().qpath_def(qpath, expr.id)
} else {
return None;
};
if let Def::Fn(did) = def {
if !def_id_is_transmute(cx, did) {
return None;
}

View file

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use rustc::hir::pat_util;
use rustc::ty;
use rustc::ty::adjustment;
use util::nodemap::FxHashMap;
@ -44,7 +43,7 @@ fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) {
let mut mutables = FxHashMap();
for p in pats {
pat_util::pat_bindings(p, |mode, id, _, path1| {
p.each_binding(|mode, id, _, path1| {
let name = path1.node;
if let hir::BindByValue(hir::MutMutable) = mode {
if !name.as_str().starts_with("_") {

View file

@ -18,7 +18,7 @@
use rustc::middle::cstore::{InlinedItem, InlinedItemRef};
use rustc::middle::const_qualif::ConstQualif;
use rustc::hir::def::{self, Def};
use rustc::hir::def::Def;
use rustc::hir::def_id::DefId;
use rustc::ty::{self, TyCtxt, Ty};
@ -35,7 +35,7 @@ pub struct Ast<'tcx> {
#[derive(RustcEncodable, RustcDecodable)]
enum TableEntry<'tcx> {
Def(Def),
TypeRelativeDef(Def),
NodeType(Ty<'tcx>),
ItemSubsts(ty::ItemSubsts<'tcx>),
Adjustment(ty::adjustment::Adjustment<'tcx>),
@ -93,7 +93,8 @@ fn visit_id(&mut self, id: ast::NodeId) {
}
};
encode(tcx.expect_def_or_none(id).map(TableEntry::Def));
encode(tcx.tables().type_relative_path_defs.get(&id).cloned()
.map(TableEntry::TypeRelativeDef));
encode(tcx.tables().node_types.get(&id).cloned().map(TableEntry::NodeType));
encode(tcx.tables().item_substs.get(&id).cloned().map(TableEntry::ItemSubsts));
encode(tcx.tables().adjustments.get(&id).cloned().map(TableEntry::Adjustment));
@ -140,8 +141,8 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata,
for (id, entry) in ast.side_tables.decode((cdata, tcx, id_ranges)) {
match entry {
TableEntry::Def(def) => {
tcx.def_map.borrow_mut().insert(id, def::PathResolution::new(def));
TableEntry::TypeRelativeDef(def) => {
tcx.tables.borrow_mut().type_relative_path_defs.insert(id, def);
}
TableEntry::NodeType(ty) => {
tcx.tables.borrow_mut().node_types.insert(id, ty);

View file

@ -597,7 +597,7 @@ fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> {
fn encode_fn_arg_names(&mut self, decl: &hir::FnDecl) -> LazySeq<ast::Name> {
self.lazy_seq(decl.inputs.iter().map(|arg| {
if let PatKind::Binding(_, ref path1, _) = arg.pat.node {
if let PatKind::Binding(_, _, ref path1, _) = arg.pat.node {
path1.node
} else {
Symbol::intern("")

View file

@ -182,7 +182,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
by_ref: by_ref
};
if let Some(hir::map::NodeLocal(pat)) = tcx.map.find(var_id) {
if let hir::PatKind::Binding(_, ref ident, _) = pat.node {
if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node {
decl.debug_name = ident.node;
}
}
@ -286,7 +286,7 @@ fn args_and_body(&mut self,
// If this is a simple binding pattern, give the local a nice name for debuginfo.
let mut name = None;
if let Some(pat) = pattern {
if let hir::PatKind::Binding(_, ref ident, _) = pat.node {
if let hir::PatKind::Binding(_, _, ref ident, _) = pat.node {
name = Some(ident.node);
}
}

View file

@ -18,7 +18,6 @@
use rustc::hir::def::{Def, CtorKind};
use rustc::middle::const_val::ConstVal;
use rustc_const_eval as const_eval;
use rustc::middle::region::CodeExtent;
use rustc::ty::{self, AdtKind, VariantDef, Ty};
use rustc::ty::cast::CastKind as TyCastKind;
use rustc::hir;
@ -265,10 +264,10 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
args: vec![fun.to_ref(), tupled_args.to_ref()]
}
} else {
let adt_data = if let hir::ExprPath(hir::QPath::Resolved(..)) = fun.node {
let adt_data = if let hir::ExprPath(hir::QPath::Resolved(_, ref path)) = fun.node {
// Tuple-like ADTs are represented as ExprCall. We convert them here.
expr_ty.ty_adt_def().and_then(|adt_def|{
match cx.tcx.expect_def(fun.id) {
match path.def {
Def::VariantCtor(variant_id, CtorKind::Fn) => {
Some((adt_def, adt_def.variant_index_with_id(variant_id)))
},
@ -456,7 +455,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
}
hir::ExprStruct(_, ref fields, ref base) => {
hir::ExprStruct(ref qpath, ref fields, ref base) => {
match expr_ty.sty {
ty::TyAdt(adt, substs) => match adt.adt_kind() {
AdtKind::Struct | AdtKind::Union => {
@ -476,7 +475,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
}
AdtKind::Enum => {
match cx.tcx.expect_def(expr.id) {
let def = match *qpath {
hir::QPath::Resolved(_, ref path) => path.def,
hir::QPath::TypeRelative(..) => Def::Err
};
match def {
Def::Variant(variant_id) => {
assert!(base.is_none());
@ -490,7 +493,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
base: None
}
}
ref def => {
_ => {
span_bug!(
expr.span,
"unexpected def: {:?}",
@ -531,8 +534,9 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
}
hir::ExprPath(_) => {
convert_path_expr(cx, expr)
hir::ExprPath(ref qpath) => {
let def = cx.tcx.tables().qpath_def(qpath, expr.id);
convert_path_expr(cx, expr, def)
}
hir::ExprInlineAsm(ref asm, ref outputs, ref inputs) => {
@ -559,10 +563,18 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
hir::ExprRet(ref v) =>
ExprKind::Return { value: v.to_ref() },
hir::ExprBreak(label, ref value) =>
ExprKind::Break { label: label.map(|_| loop_label(cx, expr)),
value: value.to_ref() },
ExprKind::Break {
label: label.map(|label| {
cx.tcx.region_maps.node_extent(label.loop_id)
}),
value: value.to_ref()
},
hir::ExprAgain(label) =>
ExprKind::Continue { label: label.map(|_| loop_label(cx, expr)) },
ExprKind::Continue {
label: label.map(|label| {
cx.tcx.region_maps.node_extent(label.loop_id)
})
},
hir::ExprMatch(ref discr, ref arms, _) =>
ExprKind::Match { discriminant: discr.to_ref(),
arms: arms.iter().map(|a| convert_arm(cx, a)).collect() },
@ -661,11 +673,11 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
fn convert_path_expr<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr)
expr: &'tcx hir::Expr,
def: Def)
-> ExprKind<'tcx> {
let substs = cx.tcx.tables().node_id_item_substs(expr.id)
.unwrap_or_else(|| cx.tcx.intern_substs(&[]));
let def = cx.tcx.expect_def(expr.id);
let def_id = match def {
// A regular function, constructor function or a constant.
Def::Fn(def_id) | Def::Method(def_id) |
@ -990,14 +1002,6 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
}
}
fn loop_label<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
expr: &'tcx hir::Expr) -> CodeExtent {
match cx.tcx.expect_def(expr.id) {
Def::Label(loop_id) => cx.tcx.region_maps.node_extent(loop_id),
d => span_bug!(expr.span, "loop scope resolved to {:?}", d),
}
}
/// Converts a list of named fields (i.e. for struct-like struct/enum ADTs) into FieldExprRef.
fn field_refs<'tcx>(variant: VariantDef<'tcx>,
fields: &'tcx [hir::Field])

View file

@ -487,8 +487,9 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
_ => {}
}
}
hir::ExprPath(_) => {
match v.tcx.expect_def(e.id) {
hir::ExprPath(ref qpath) => {
let def = v.tcx.tables().qpath_def(qpath, e.id);
match def {
Def::VariantCtor(_, CtorKind::Const) => {
// Size is determined by the whole enum, may be non-zero.
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
@ -531,17 +532,22 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Expr, node
};
}
// The callee is an arbitrary expression, it doesn't necessarily have a definition.
let is_const = match v.tcx.expect_def_or_none(callee.id) {
Some(Def::StructCtor(_, CtorKind::Fn)) |
Some(Def::VariantCtor(_, CtorKind::Fn)) => {
let def = if let hir::ExprPath(ref qpath) = callee.node {
v.tcx.tables().qpath_def(qpath, callee.id)
} else {
Def::Err
};
let is_const = match def {
Def::StructCtor(_, CtorKind::Fn) |
Def::VariantCtor(_, CtorKind::Fn) => {
// `NON_ZERO_SIZED` is about the call result, not about the ctor itself.
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
true
}
Some(Def::Fn(did)) => {
Def::Fn(did) => {
v.handle_const_fn_call(e, did, node_ty)
}
Some(Def::Method(did)) => {
Def::Method(did) => {
match v.tcx.associated_item(did).container {
ty::ImplContainer(_) => {
v.handle_const_fn_call(e, did, node_ty)

View file

@ -12,10 +12,10 @@
use rustc::session::Session;
use rustc::dep_graph::DepNode;
use rustc::hir::def::{Def, DefMap};
use rustc::hir::map::Map;
use rustc::hir::intravisit::{self, Visitor};
use rustc::hir;
use syntax::ast;
use syntax_pos::Span;
#[derive(Clone, Copy, PartialEq)]
@ -45,17 +45,15 @@ enum Context {
#[derive(Copy, Clone)]
struct CheckLoopVisitor<'a, 'ast: 'a> {
sess: &'a Session,
def_map: &'a DefMap,
hir_map: &'a Map<'ast>,
cx: Context,
}
pub fn check_crate(sess: &Session, def_map: &DefMap, map: &Map) {
pub fn check_crate(sess: &Session, map: &Map) {
let _task = map.dep_graph.in_task(DepNode::CheckLoops);
let krate = map.krate();
krate.visit_all_item_likes(&mut CheckLoopVisitor {
sess: sess,
def_map: def_map,
hir_map: map,
cx: Normal,
}.as_deep_visitor());
@ -84,21 +82,18 @@ fn visit_expr(&mut self, e: &hir::Expr) {
hir::ExprClosure(.., ref b, _) => {
self.with_context(Closure, |v| v.visit_expr(&b));
}
hir::ExprBreak(ref opt_label, ref opt_expr) => {
hir::ExprBreak(label, ref opt_expr) => {
if opt_expr.is_some() {
let loop_kind = if opt_label.is_some() {
let loop_def = self.def_map.get(&e.id).unwrap().full_def();
if loop_def == Def::Err {
let loop_kind = if let Some(label) = label {
if label.loop_id == ast::DUMMY_NODE_ID {
None
} else if let Def::Label(loop_id) = loop_def {
Some(match self.hir_map.expect_expr(loop_id).node {
} else {
Some(match self.hir_map.expect_expr(label.loop_id).node {
hir::ExprWhile(..) => LoopKind::WhileLoop,
hir::ExprLoop(_, _, source) => LoopKind::Loop(source),
ref r => span_bug!(e.span,
"break label resolved to a non-loop: {:?}", r),
})
} else {
span_bug!(e.span, "break resolved to a non-label")
}
} else if let Loop(kind) = self.cx {
Some(kind)

View file

@ -14,7 +14,7 @@
use rustc::dep_graph::DepNode;
use rustc::hir::map as ast_map;
use rustc::session::{CompileResult, Session};
use rustc::hir::def::{Def, CtorKind, DefMap};
use rustc::hir::def::{Def, CtorKind};
use rustc::util::nodemap::NodeMap;
use syntax::ast;
@ -27,7 +27,6 @@
struct CheckCrateVisitor<'a, 'ast: 'a> {
sess: &'a Session,
def_map: &'a DefMap,
ast_map: &'a ast_map::Map<'ast>,
// `discriminant_map` is a cache that associates the `NodeId`s of local
// variant definitions with the discriminant expression that applies to
@ -88,14 +87,12 @@ fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
}
pub fn check_crate<'ast>(sess: &Session,
def_map: &DefMap,
ast_map: &ast_map::Map<'ast>)
-> CompileResult {
let _task = ast_map.dep_graph.in_task(DepNode::CheckStaticRecursion);
let mut visitor = CheckCrateVisitor {
sess: sess,
def_map: def_map,
ast_map: ast_map,
discriminant_map: RefCell::new(NodeMap()),
};
@ -109,7 +106,6 @@ struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
root_span: &'a Span,
sess: &'a Session,
ast_map: &'a ast_map::Map<'ast>,
def_map: &'a DefMap,
discriminant_map: &'a RefCell<NodeMap<Option<&'ast hir::Expr>>>,
idstack: Vec<ast::NodeId>,
}
@ -122,7 +118,6 @@ fn new(v: &'a CheckCrateVisitor<'a, 'ast>,
root_span: span,
sess: v.sess,
ast_map: v.ast_map,
def_map: v.def_map,
discriminant_map: &v.discriminant_map,
idstack: Vec::new(),
}
@ -250,11 +245,11 @@ fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) {
fn visit_expr(&mut self, e: &'ast hir::Expr) {
match e.node {
hir::ExprPath(_) => {
match self.def_map.get(&e.id).map(|d| d.base_def) {
Some(Def::Static(def_id, _)) |
Some(Def::AssociatedConst(def_id)) |
Some(Def::Const(def_id)) => {
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
match path.def {
Def::Static(def_id, _) |
Def::AssociatedConst(def_id) |
Def::Const(def_id) => {
if let Some(node_id) = self.ast_map.as_local_node_id(def_id) {
match self.ast_map.get(node_id) {
ast_map::NodeItem(item) => self.visit_item(item),
@ -273,7 +268,7 @@ fn visit_expr(&mut self, e: &'ast hir::Expr) {
// affect the specific variant used, but we need to check
// the whole enum definition to see what expression that
// might be (if any).
Some(Def::VariantCtor(variant_id, CtorKind::Const)) => {
Def::VariantCtor(variant_id, CtorKind::Const) => {
if let Some(variant_id) = self.ast_map.as_local_node_id(variant_id) {
let variant = self.ast_map.expect_variant(variant_id);
let enum_id = self.ast_map.get_parent(variant_id);

View file

@ -67,8 +67,12 @@ struct ReachEverythingInTheInterfaceVisitor<'b, 'a: 'b, 'tcx: 'a> {
impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
if let hir::TyPath(_) = ty.node {
match self.tcx.expect_def(ty.id) {
if let hir::TyPath(ref qpath) = ty.node {
let def = match *qpath {
hir::QPath::Resolved(_, ref path) => path.def,
hir::QPath::TypeRelative(..) => self.tcx.tables().type_relative_path_defs[&ty.id]
};
match def {
Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
Some(AccessLevel::Public)
}
@ -86,7 +90,7 @@ fn ty_level(&self, ty: &hir::Ty) -> Option<AccessLevel> {
}
fn trait_level(&self, trait_ref: &hir::TraitRef) -> Option<AccessLevel> {
let did = self.tcx.expect_def(trait_ref.ref_id).def_id();
let did = trait_ref.path.def.def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
self.get(node_id)
} else {
@ -328,13 +332,16 @@ fn visit_nested_impl_item(&mut self, item_id: hir::ImplItemId) {
}
fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
let path_segment = match ty.node {
hir::TyPath(hir::QPath::Resolved(_, ref path)) => path.segments.last(),
hir::TyPath(hir::QPath::TypeRelative(_, ref segment)) => Some(&**segment),
let def_and_segment = match ty.node {
hir::TyPath(hir::QPath::Resolved(_, ref path)) => {
Some((path.def, path.segments.last().unwrap()))
}
hir::TyPath(hir::QPath::TypeRelative(_, ref segment)) => {
Some((self.ev.tcx.tables().type_relative_path_defs[&ty.id], &**segment))
}
_ => None
};
if let Some(segment) = path_segment {
let def = self.ev.tcx.expect_def(ty.id);
if let Some((def, segment)) = def_and_segment {
match def {
Def::Struct(def_id) | Def::Union(def_id) | Def::Enum(def_id) |
Def::TyAlias(def_id) | Def::Trait(def_id) | Def::AssociatedTy(def_id) => {
@ -365,7 +372,7 @@ fn visit_ty(&mut self, ty: &'tcx hir::Ty) {
}
fn visit_trait_ref(&mut self, trait_ref: &'tcx hir::TraitRef) {
let def_id = self.ev.tcx.expect_def(trait_ref.ref_id).def_id();
let def_id = trait_ref.path.def.def_id();
if let Some(node_id) = self.ev.tcx.map.as_local_node_id(def_id) {
let item = self.ev.tcx.map.expect_item(node_id);
self.ev.update(item.id, Some(AccessLevel::Reachable));
@ -446,9 +453,10 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
let method = self.tcx.tables().method_map[&method_call];
self.check_method(expr.span, method.def_id);
}
hir::ExprStruct(_, ref expr_fields, _) => {
hir::ExprStruct(ref qpath, ref expr_fields, _) => {
let def = self.tcx.tables().qpath_def(qpath, expr.id);
let adt = self.tcx.tables().expr_ty(expr).ty_adt_def().unwrap();
let variant = adt.variant_of_def(self.tcx.expect_def(expr.id));
let variant = adt.variant_of_def(def);
// RFC 736: ensure all unmentioned fields are visible.
// Rather than computing the set of unmentioned fields
// (i.e. `all_fields - fields`), just check them all,
@ -466,9 +474,9 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
}
}
}
hir::ExprPath(hir::QPath::Resolved(..)) => {
if let def @ Def::StructCtor(_, CtorKind::Fn) = self.tcx.expect_def(expr.id) {
let adt_def = self.tcx.expect_variant_def(def);
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
if let Def::StructCtor(_, CtorKind::Fn) = path.def {
let adt_def = self.tcx.expect_variant_def(path.def);
let private_indexes = adt_def.fields.iter().enumerate().filter(|&(_, field)| {
!field.vis.is_accessible_from(self.curitem, &self.tcx.map)
}).map(|(i, _)| i).collect::<Vec<_>>();
@ -507,9 +515,10 @@ fn visit_pat(&mut self, pattern: &'tcx hir::Pat) {
if self.in_foreign { return }
match pattern.node {
PatKind::Struct(_, ref fields, _) => {
PatKind::Struct(ref qpath, ref fields, _) => {
let def = self.tcx.tables().qpath_def(qpath, pattern.id);
let adt = self.tcx.tables().pat_ty(pattern).ty_adt_def().unwrap();
let variant = adt.variant_of_def(self.tcx.expect_def(pattern.id));
let variant = adt.variant_of_def(def);
for field in fields {
self.check_field(field.span, adt, variant.field_named(field.node.name));
}
@ -569,8 +578,8 @@ struct ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
}
impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
let did = match self.tcx.expect_def(path_id) {
fn path_is_private_type(&self, path: &hir::Path) -> bool {
let did = match path.def {
Def::PrimTy(..) | Def::SelfTy(..) => return false,
def => def.def_id(),
};
@ -598,7 +607,7 @@ fn trait_is_public(&self, trait_id: ast::NodeId) -> bool {
fn check_ty_param_bound(&mut self,
ty_param_bound: &hir::TyParamBound) {
if let hir::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
if self.path_is_private_type(trait_ref.trait_ref.ref_id) {
if self.path_is_private_type(&trait_ref.trait_ref.path) {
self.old_error_set.insert(trait_ref.trait_ref.ref_id);
}
}
@ -611,13 +620,16 @@ fn item_is_public(&self, id: &ast::NodeId, vis: &hir::Visibility) -> bool {
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for ObsoleteCheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
fn visit_ty(&mut self, ty: &hir::Ty) {
if let hir::TyPath(_) = ty.node {
if self.inner.path_is_private_type(ty.id) {
if let hir::TyPath(hir::QPath::Resolved(_, ref path)) = ty.node {
if self.inner.path_is_private_type(path) {
self.contains_private = true;
// found what we're looking for so let's stop
// working.
return
} else if self.at_outer_type {
}
}
if let hir::TyPath(_) = ty.node {
if self.at_outer_type {
self.outer_type_is_public_path = true;
}
}
@ -687,7 +699,7 @@ fn visit_item(&mut self, item: &'tcx hir::Item) {
let not_private_trait =
trait_ref.as_ref().map_or(true, // no trait counts as public trait
|tr| {
let did = self.tcx.expect_def(tr.ref_id).def_id();
let did = tr.path.def.def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(did) {
self.trait_is_public(node_id)
@ -849,8 +861,8 @@ fn visit_foreign_item(&mut self, item: &'tcx hir::ForeignItem) {
}
fn visit_ty(&mut self, t: &'tcx hir::Ty) {
if let hir::TyPath(_) = t.node {
if self.path_is_private_type(t.id) {
if let hir::TyPath(hir::QPath::Resolved(_, ref path)) = t.node {
if self.path_is_private_type(path) {
self.old_error_set.insert(t.id);
}
}
@ -941,13 +953,17 @@ fn substituted_alias_visibility(&self, item: &hir::Item, segment: &hir::PathSegm
impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
fn visit_ty(&mut self, ty: &hir::Ty) {
let path_segment = match ty.node {
hir::TyPath(hir::QPath::Resolved(_, ref path)) => path.segments.last(),
hir::TyPath(hir::QPath::TypeRelative(_, ref segment)) => Some(&**segment),
let def_and_segment = match ty.node {
hir::TyPath(hir::QPath::Resolved(_, ref path)) => {
Some((path.def, path.segments.last().unwrap()))
}
hir::TyPath(hir::QPath::TypeRelative(_, ref segment)) => {
Some((self.tcx.tables().type_relative_path_defs[&ty.id], &**segment))
}
_ => None
};
if let Some(segment) = path_segment {
match self.tcx.expect_def(ty.id) {
if let Some((def, segment)) = def_and_segment {
match def {
Def::PrimTy(..) | Def::SelfTy(..) | Def::TyParam(..) => {
// Public
}
@ -1005,7 +1021,7 @@ fn visit_ty(&mut self, ty: &hir::Ty) {
fn visit_trait_ref(&mut self, trait_ref: &hir::TraitRef) {
// Non-local means public (private items can't leave their crate, modulo bugs)
let def_id = self.tcx.expect_def(trait_ref.ref_id).def_id();
let def_id = trait_ref.path.def.def_id();
if let Some(node_id) = self.tcx.map.as_local_node_id(def_id) {
let item = self.tcx.map.expect_item(node_id);
let vis = ty::Visibility::from_hir(&item.vis, node_id, self.tcx);

View file

@ -1201,11 +1201,11 @@ fn is_descendant_of(&self, mut node: NodeId, ancestor: NodeId) -> bool {
}
impl<'a> hir::lowering::Resolver for Resolver<'a> {
fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def {
fn resolve_generated_global_path(&mut self, path: &mut hir::Path, is_value: bool) {
let namespace = if is_value { ValueNS } else { TypeNS };
match self.resolve_crate_relative_path(path.span, &path.segments, namespace) {
Ok(binding) => binding.def(),
Err(true) => Def::Err,
Ok(binding) => path.def = binding.def(),
Err(true) => {}
Err(false) => {
let path_name = &format!("{}", path);
let error =
@ -1218,7 +1218,6 @@ fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) ->
def: Def::Err,
};
resolve_error(self, path.span, error);
Def::Err
}
}
}

View file

@ -274,12 +274,10 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) {
}
fn lookup_def_id(&self, ref_id: NodeId) -> Option<DefId> {
self.tcx.expect_def_or_none(ref_id).and_then(|def| {
match def {
Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None,
def => Some(def.def_id()),
}
})
match self.save_ctxt.get_path_def(ref_id) {
Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None,
def => Some(def.def_id()),
}
}
fn process_def_kind(&mut self,
@ -292,7 +290,7 @@ fn process_def_kind(&mut self,
return;
}
let def = self.tcx.expect_def(ref_id);
let def = self.save_ctxt.get_path_def(ref_id);
match def {
Def::Mod(_) => {
self.dumper.mod_ref(ModRefData {
@ -919,7 +917,7 @@ fn process_path(&mut self, id: NodeId, path: &ast::Path, ref_kind: Option<record
}
// Modules or types in the path prefix.
match self.tcx.expect_def(id) {
match self.save_ctxt.get_path_def(id) {
Def::Method(did) => {
let ti = self.tcx.associated_item(did);
if ti.kind == ty::AssociatedKind::Method && ti.method_has_self_argument {
@ -998,7 +996,7 @@ fn process_pat(&mut self, p: &ast::Pat) {
return;
}
};
let variant = adt.variant_of_def(self.tcx.expect_def(p.id));
let variant = adt.variant_of_def(self.save_ctxt.get_path_def(p.id));
for &Spanned { node: ref field, span } in fields {
let sub_span = self.span.span_for_first_ident(span);
@ -1370,7 +1368,7 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
return;
}
};
let def = self.tcx.expect_def(hir_expr.id);
let def = self.save_ctxt.get_path_def(hir_expr.id);
self.process_struct_lit(ex, path, fields, adt.variant_of_def(def), base)
}
ast::ExprKind::MethodCall(.., ref args) => self.process_method_call(ex, args),
@ -1480,7 +1478,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
// process collected paths
for &(id, ref p, immut, ref_kind) in &collector.collected_paths {
match self.tcx.expect_def(id) {
match self.save_ctxt.get_path_def(id) {
Def::Local(def_id) => {
let id = self.tcx.map.as_local_node_id(def_id).unwrap();
let mut value = if immut == ast::Mutability::Immutable {

View file

@ -42,8 +42,8 @@
pub mod span_utils;
use rustc::hir;
use rustc::hir::map::{Node, NodeItem};
use rustc::hir::def::Def;
use rustc::hir::map::Node;
use rustc::hir::def_id::DefId;
use rustc::session::config::CrateType::CrateTypeExecutable;
use rustc::ty::{self, TyCtxt};
@ -318,7 +318,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
let (qualname, parent_scope, decl_id, vis, docs) =
match self.tcx.impl_of_method(self.tcx.map.local_def_id(id)) {
Some(impl_id) => match self.tcx.map.get_if_local(impl_id) {
Some(NodeItem(item)) => {
Some(Node::NodeItem(item)) => {
match item.node {
hir::ItemImpl(.., ref ty, _) => {
let mut result = String::from("<");
@ -358,7 +358,7 @@ pub fn get_method_data(&self, id: ast::NodeId,
None => match self.tcx.trait_of_item(self.tcx.map.local_def_id(id)) {
Some(def_id) => {
match self.tcx.map.get_if_local(def_id) {
Some(NodeItem(item)) => {
Some(Node::NodeItem(item)) => {
(format!("::{}", self.tcx.item_path_str(def_id)),
Some(def_id), None,
From::from(&item.vis),
@ -497,13 +497,41 @@ pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
}
}
pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
let resolution = self.tcx.expect_resolution(id);
if resolution.depth != 0 {
return None;
}
let def = resolution.base_def;
pub fn get_path_def(&self, id: NodeId) -> Def {
match self.tcx.map.get(id) {
Node::NodeTraitRef(tr) => tr.path.def,
Node::NodeItem(&hir::Item { node: hir::ItemUse(ref path, _), .. }) |
Node::NodeVisibility(&hir::Visibility::Restricted { ref path, .. }) => path.def,
Node::NodeExpr(&hir::Expr { node: hir::ExprPath(ref qpath), .. }) |
Node::NodeExpr(&hir::Expr { node: hir::ExprStruct(ref qpath, ..), .. }) |
Node::NodePat(&hir::Pat { node: hir::PatKind::Path(ref qpath), .. }) |
Node::NodePat(&hir::Pat { node: hir::PatKind::Struct(ref qpath, ..), .. }) |
Node::NodePat(&hir::Pat { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => {
self.tcx.tables().qpath_def(qpath, id)
}
Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => {
Def::Local(def_id)
}
Node::NodeTy(&hir::Ty { node: hir::TyPath(ref qpath), .. }) => {
match *qpath {
hir::QPath::Resolved(_, ref path) => path.def,
hir::QPath::TypeRelative(..) => {
// FIXME(eddyb) Avoid keeping associated type resolutions.
self.tcx.tables().type_relative_path_defs[&id]
}
}
}
_ => Def::Err
}
}
pub fn get_path_data(&self, id: NodeId, path: &ast::Path) -> Option<Data> {
let def = self.get_path_def(id);
let sub_span = self.span_utils.span_for_last_ident(path.span);
filter!(self.span_utils, sub_span, path.span, None);
match def {
@ -647,8 +675,8 @@ pub fn get_data_for_id(&self, _id: &NodeId) -> Data {
}
fn lookup_ref_id(&self, ref_id: NodeId) -> Option<DefId> {
match self.tcx.expect_def(ref_id) {
Def::PrimTy(_) | Def::SelfTy(..) => None,
match self.get_path_def(ref_id) {
Def::PrimTy(_) | Def::SelfTy(..) | Def::Err => None,
def => Some(def.def_id()),
}
}

View file

@ -50,7 +50,7 @@
use rustc_const_eval::eval_length;
use hir::{self, SelfKind};
use hir::def::{Def, PathResolution};
use hir::def::Def;
use hir::def_id::DefId;
use hir::print as pprust;
use middle::resolve_lifetime as rl;
@ -678,7 +678,7 @@ pub fn instantiate_mono_trait_ref(&self,
fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
let path = &trait_ref.path;
match self.tcx().expect_def(trait_ref.ref_id) {
match path.def {
Def::Trait(trait_def_id) => trait_def_id,
Def::Err => {
self.tcx().sess.fatal("cannot continue compilation due to previous error");
@ -953,24 +953,20 @@ fn ast_ty_to_object_trait_ref(&self,
let tcx = self.tcx();
match ty.node {
hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
let resolution = tcx.expect_resolution(ty.id);
match resolution.base_def {
Def::Trait(trait_def_id) if resolution.depth == 0 => {
self.trait_path_to_object_type(rscope,
path.span,
trait_def_id,
ty.id,
path.segments.last().unwrap(),
span,
partition_bounds(tcx, span, bounds))
}
_ => {
struct_span_err!(tcx.sess, ty.span, E0172,
"expected a reference to a trait")
.span_label(ty.span, &format!("expected a trait"))
.emit();
tcx.types.err
}
if let Def::Trait(trait_def_id) = path.def {
self.trait_path_to_object_type(rscope,
path.span,
trait_def_id,
ty.id,
path.segments.last().unwrap(),
span,
partition_bounds(tcx, span, bounds))
} else {
struct_span_err!(tcx.sess, ty.span, E0172,
"expected a reference to a trait")
.span_label(ty.span, &format!("expected a trait"))
.emit();
tcx.types.err
}
}
_ => {
@ -1412,55 +1408,54 @@ fn ast_ty_arg_to_ty(&self,
}
}
// Check a type Def and convert it to a Ty.
// Check a type Path and convert it to a Ty.
pub fn def_to_ty(&self,
rscope: &RegionScope,
span: Span,
def: Def,
opt_self_ty: Option<Ty<'tcx>>,
path: &hir::Path,
path_id: ast::NodeId,
path_segments: &[hir::PathSegment],
permit_variants: bool)
-> Ty<'tcx> {
let tcx = self.tcx();
debug!("base_def_to_ty(def={:?}, opt_self_ty={:?}, path_segments={:?})",
def, opt_self_ty, path_segments);
path.def, opt_self_ty, path.segments);
match def {
let span = path.span;
match path.def {
Def::Trait(trait_def_id) => {
// N.B. this case overlaps somewhat with
// TyObjectSum, see that fn for details
assert_eq!(opt_self_ty, None);
tcx.prohibit_type_params(path_segments.split_last().unwrap().1);
tcx.prohibit_type_params(path.segments.split_last().unwrap().1);
self.trait_path_to_object_type(rscope,
span,
trait_def_id,
path_id,
path_segments.last().unwrap(),
path.segments.last().unwrap(),
span,
partition_bounds(tcx, span, &[]))
}
Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => {
assert_eq!(opt_self_ty, None);
tcx.prohibit_type_params(path_segments.split_last().unwrap().1);
self.ast_path_to_ty(rscope, span, did, path_segments.last().unwrap())
tcx.prohibit_type_params(path.segments.split_last().unwrap().1);
self.ast_path_to_ty(rscope, span, did, path.segments.last().unwrap())
}
Def::Variant(did) if permit_variants => {
// Convert "variant type" as if it were a real type.
// The resulting `Ty` is type of the variant's enum for now.
assert_eq!(opt_self_ty, None);
tcx.prohibit_type_params(path_segments.split_last().unwrap().1);
tcx.prohibit_type_params(path.segments.split_last().unwrap().1);
self.ast_path_to_ty(rscope,
span,
tcx.parent_def_id(did).unwrap(),
path_segments.last().unwrap())
path.segments.last().unwrap())
}
Def::TyParam(did) => {
assert_eq!(opt_self_ty, None);
tcx.prohibit_type_params(path_segments);
tcx.prohibit_type_params(&path.segments);
let node_id = tcx.map.as_local_node_id(did).unwrap();
let param = tcx.ty_param_defs.borrow().get(&node_id)
@ -1483,7 +1478,7 @@ pub fn def_to_ty(&self,
// Self in impl (we know the concrete type).
assert_eq!(opt_self_ty, None);
tcx.prohibit_type_params(path_segments);
tcx.prohibit_type_params(&path.segments);
let ty = tcx.item_type(def_id);
if let Some(free_substs) = self.get_free_substs() {
ty.subst(tcx, free_substs)
@ -1494,22 +1489,22 @@ pub fn def_to_ty(&self,
Def::SelfTy(Some(_), None) => {
// Self in trait.
assert_eq!(opt_self_ty, None);
tcx.prohibit_type_params(path_segments);
tcx.prohibit_type_params(&path.segments);
tcx.mk_self_type()
}
Def::AssociatedTy(def_id) => {
tcx.prohibit_type_params(&path_segments[..path_segments.len()-2]);
tcx.prohibit_type_params(&path.segments[..path.segments.len()-2]);
let trait_did = tcx.parent_def_id(def_id).unwrap();
self.qpath_to_ty(rscope,
span,
opt_self_ty,
trait_did,
&path_segments[path_segments.len()-2],
path_segments.last().unwrap())
&path.segments[path.segments.len()-2],
path.segments.last().unwrap())
}
Def::PrimTy(prim_ty) => {
assert_eq!(opt_self_ty, None);
tcx.prim_ty_to_ty(path_segments, prim_ty)
tcx.prim_ty_to_ty(&path.segments, prim_ty)
}
Def::Err => {
self.set_tainted_by_errors();
@ -1518,7 +1513,7 @@ pub fn def_to_ty(&self,
_ => {
struct_span_err!(tcx.sess, span, E0248,
"found value `{}` used as a type",
tcx.item_path_str(def.def_id()))
tcx.item_path_str(path.def.def_id()))
.span_label(span, &format!("value used as a type"))
.emit();
return self.tcx().types.err;
@ -1653,23 +1648,21 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
let opt_self_ty = maybe_qself.as_ref().map(|qself| {
self.ast_ty_to_ty(rscope, qself)
});
self.def_to_ty(rscope,
ast_ty.span,
tcx.expect_def(ast_ty.id),
opt_self_ty,
ast_ty.id,
&path.segments,
false)
self.def_to_ty(rscope, opt_self_ty, path, ast_ty.id, false)
}
hir::TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => {
debug!("ast_ty_to_ty: qself={:?} segment={:?}", qself, segment);
let ty = self.ast_ty_to_ty(rscope, qself);
let def = tcx.expect_def_or_none(qself.id).unwrap_or(Def::Err);
let def = if let hir::TyPath(hir::QPath::Resolved(_, ref path)) = qself.node {
path.def
} else {
Def::Err
};
let (ty, def) = self.associated_path_def_to_ty(ast_ty.span, ty, def, segment);
// Write back the new resolution.
tcx.def_map.borrow_mut().insert(ast_ty.id, PathResolution::new(def));
tcx.tables.borrow_mut().type_relative_path_defs.insert(ast_ty.id, def);
ty
}
@ -2007,7 +2000,7 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
for ast_bound in ast_bounds {
match *ast_bound {
hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => {
match tcx.expect_def(b.trait_ref.ref_id) {
match b.trait_ref.path.def {
Def::Trait(trait_did) => {
if tcx.try_add_builtin_trait(trait_did,
&mut builtin_bounds) {

View file

@ -103,7 +103,7 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
self.demand_eqtype(pat.span, expected, rhs_ty);
common_type
}
PatKind::Binding(bm, _, ref sub) => {
PatKind::Binding(bm, def_id, _, ref sub) => {
let typ = self.local_ty(pat.span, pat.id);
match bm {
hir::BindByRef(mutbl) => {
@ -130,16 +130,10 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
// if there are multiple arms, make sure they all agree on
// what the type of the binding `x` ought to be
match tcx.expect_def(pat.id) {
Def::Err => {}
Def::Local(def_id) => {
let var_id = tcx.map.as_local_node_id(def_id).unwrap();
if var_id != pat.id {
let vt = self.local_ty(pat.span, var_id);
self.demand_eqtype(pat.span, vt, typ);
}
}
d => bug!("bad def for pattern binding `{:?}`", d)
let var_id = tcx.map.as_local_node_id(def_id).unwrap();
if var_id != pat.id {
let vt = self.local_ty(pat.span, var_id);
self.demand_eqtype(pat.span, vt, typ);
}
if let Some(ref p) = *sub {
@ -373,7 +367,7 @@ pub fn check_match(&self,
// want to use the *precise* type of the discriminant, *not* some
// supertype, as the "discriminant type" (issue #23116).
let contains_ref_bindings = arms.iter()
.filter_map(|a| tcx.arm_contains_ref_binding(a))
.filter_map(|a| a.contains_ref_binding())
.max_by_key(|m| match *m {
hir::MutMutable => 1,
hir::MutImmutable => 0,

View file

@ -218,12 +218,14 @@ fn confirm_builtin_call(&self,
};
if let hir::ExprCall(ref expr, _) = call_expr.node {
let tcx = self.tcx;
if let Some(pr) = tcx.def_map.borrow().get(&expr.id) {
if pr.depth == 0 && pr.base_def != Def::Err {
if let Some(span) = tcx.map.span_if_local(pr.base_def.def_id()) {
err.span_note(span, "defined here");
}
let def = if let hir::ExprPath(ref qpath) = expr.node {
self.tcx.tables().qpath_def(qpath, expr.id)
} else {
Def::Err
};
if def != Def::Err {
if let Some(span) = self.tcx.map.span_if_local(def.def_id()) {
err.span_note(span, "defined here");
}
}
}

View file

@ -83,9 +83,8 @@
use astconv::{AstConv, ast_region_to_region};
use dep_graph::DepNode;
use fmt_macros::{Parser, Piece, Position};
use hir::def::{Def, CtorKind, PathResolution};
use hir::def::{Def, CtorKind};
use hir::def_id::{DefId, LOCAL_CRATE};
use hir::pat_util;
use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin,
TypeTrace, type_variable};
use rustc::ty::subst::{Kind, Subst, Substs};
@ -711,7 +710,7 @@ fn visit_local(&mut self, local: &'gcx hir::Local) {
// Add pattern bindings.
fn visit_pat(&mut self, p: &'gcx hir::Pat) {
if let PatKind::Binding(_, ref path1, _) = p.node {
if let PatKind::Binding(_, _, ref path1, _) = p.node {
let var_ty = self.assign(p.span, p.id, None);
self.fcx.require_type_is_sized(var_ty, p.span,
@ -796,7 +795,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
fcx.register_old_wf_obligation(arg_ty, input.ty.span, traits::MiscObligation);
// Create type variables for each argument.
pat_util::pat_bindings(&input.pat, |_bm, pat_id, sp, _path| {
input.pat.each_binding(|_bm, pat_id, sp, _path| {
let var_ty = visit.assign(sp, pat_id, None);
fcx.require_type_is_sized(var_ty, sp, traits::VariableType(pat_id));
});
@ -3627,72 +3626,58 @@ fn check_expr_kind(&self,
}
tcx.mk_nil()
}
hir::ExprBreak(ref label_opt, ref expr_opt) => {
let loop_id = if label_opt.is_some() {
let loop_def = tcx.expect_def(expr.id);
if let Def::Label(loop_id) = loop_def {
Some(Some(loop_id))
} else if loop_def == Def::Err {
// an error was already printed, so just ignore it
None
} else {
span_bug!(expr.span, "break label resolved to a non-label");
}
} else {
Some(None)
hir::ExprBreak(label, ref expr_opt) => {
let loop_id = label.map(|l| l.loop_id);
let coerce_to = {
let mut enclosing_loops = self.enclosing_loops.borrow_mut();
enclosing_loops.find_loop(loop_id).map(|ctxt| ctxt.coerce_to)
};
if let Some(loop_id) = loop_id {
let coerce_to = {
let mut enclosing_loops = self.enclosing_loops.borrow_mut();
enclosing_loops.find_loop(loop_id).map(|ctxt| ctxt.coerce_to)
};
if let Some(coerce_to) = coerce_to {
let e_ty;
let cause;
if let Some(ref e) = *expr_opt {
// Recurse without `enclosing_loops` borrowed.
e_ty = self.check_expr_with_hint(e, coerce_to);
cause = self.misc(e.span);
// Notably, the recursive call may alter coerce_to - must not keep using it!
} else {
// `break` without argument acts like `break ()`.
e_ty = tcx.mk_nil();
cause = self.misc(expr.span);
}
let mut enclosing_loops = self.enclosing_loops.borrow_mut();
let ctxt = enclosing_loops.find_loop(loop_id).unwrap();
let result = if let Some(ref e) = *expr_opt {
// Special-case the first element, as it has no "previous expressions".
let result = if !ctxt.may_break {
self.try_coerce(e, e_ty, ctxt.coerce_to)
} else {
self.try_find_coercion_lub(&cause, || ctxt.break_exprs.iter().cloned(),
ctxt.unified, e, e_ty)
};
ctxt.break_exprs.push(e);
result
} else {
self.eq_types(true, &cause, e_ty, ctxt.unified)
.map(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
e_ty
})
};
match result {
Ok(ty) => ctxt.unified = ty,
Err(err) => {
self.report_mismatched_types(&cause, ctxt.unified, e_ty, err);
}
}
ctxt.may_break = true;
if let Some(coerce_to) = coerce_to {
let e_ty;
let cause;
if let Some(ref e) = *expr_opt {
// Recurse without `enclosing_loops` borrowed.
e_ty = self.check_expr_with_hint(e, coerce_to);
cause = self.misc(e.span);
// Notably, the recursive call may alter coerce_to - must not keep using it!
} else {
// `break` without argument acts like `break ()`.
e_ty = tcx.mk_nil();
cause = self.misc(expr.span);
}
// Otherwise, we failed to find the enclosing loop; this can only happen if the
// `break` was not inside a loop at all, which is caught by the loop-checking pass.
let mut enclosing_loops = self.enclosing_loops.borrow_mut();
let ctxt = enclosing_loops.find_loop(loop_id).unwrap();
let result = if let Some(ref e) = *expr_opt {
// Special-case the first element, as it has no "previous expressions".
let result = if !ctxt.may_break {
self.try_coerce(e, e_ty, ctxt.coerce_to)
} else {
self.try_find_coercion_lub(&cause, || ctxt.break_exprs.iter().cloned(),
ctxt.unified, e, e_ty)
};
ctxt.break_exprs.push(e);
result
} else {
self.eq_types(true, &cause, e_ty, ctxt.unified)
.map(|InferOk { obligations, .. }| {
// FIXME(#32730) propagate obligations
assert!(obligations.is_empty());
e_ty
})
};
match result {
Ok(ty) => ctxt.unified = ty,
Err(err) => {
self.report_mismatched_types(&cause, ctxt.unified, e_ty, err);
}
}
ctxt.may_break = true;
}
// Otherwise, we failed to find the enclosing loop; this can only happen if the
// `break` was not inside a loop at all, which is caught by the loop-checking pass.
tcx.types.never
}
hir::ExprAgain(_) => { tcx.types.never }
@ -4006,7 +3991,7 @@ fn check_expr_kind(&self,
}
// Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
// The newly resolved definition is written into `def_map`.
// The newly resolved definition is written into `type_relative_path_defs`.
fn finish_resolving_struct_path(&self,
qpath: &hir::QPath,
path_span: Span,
@ -4016,25 +4001,22 @@ fn finish_resolving_struct_path(&self,
match *qpath {
hir::QPath::Resolved(ref maybe_qself, ref path) => {
let opt_self_ty = maybe_qself.as_ref().map(|qself| self.to_ty(qself));
let def = self.tcx.expect_def(node_id);
let ty = AstConv::def_to_ty(self, self,
path.span,
def,
opt_self_ty,
node_id,
&path.segments,
true);
(def, ty)
let ty = AstConv::def_to_ty(self, self, opt_self_ty, path, node_id, true);
(path.def, ty)
}
hir::QPath::TypeRelative(ref qself, ref segment) => {
let ty = self.to_ty(qself);
let def = self.tcx.expect_def_or_none(qself.id).unwrap_or(Def::Err);
let def = if let hir::TyPath(hir::QPath::Resolved(_, ref path)) = qself.node {
path.def
} else {
Def::Err
};
let (ty, def) = AstConv::associated_path_def_to_ty(self, path_span,
ty, def, segment);
// Write back the new resolution.
self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
self.tcx.tables.borrow_mut().type_relative_path_defs.insert(node_id, def);
(def, ty)
}
@ -4042,7 +4024,7 @@ fn finish_resolving_struct_path(&self,
}
// Resolve associated value path into a base type and associated constant or method definition.
// The newly resolved definition is written into `def_map`.
// The newly resolved definition is written into `type_relative_path_defs`.
pub fn resolve_ty_and_def_ufcs<'b>(&self,
qpath: &'b hir::QPath,
node_id: ast::NodeId,
@ -4051,7 +4033,7 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
{
let (ty, item_segment) = match *qpath {
hir::QPath::Resolved(ref opt_qself, ref path) => {
return (self.tcx.expect_def(node_id),
return (path.def,
opt_qself.as_ref().map(|qself| self.to_ty(qself)),
&path.segments[..]);
}
@ -4075,7 +4057,7 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
};
// Write back the new resolution.
self.tcx.def_map.borrow_mut().insert(node_id, PathResolution::new(def));
self.tcx.tables.borrow_mut().type_relative_path_defs.insert(node_id, def);
(def, Some(ty), slice::ref_slice(&**item_segment))
}
@ -4083,7 +4065,7 @@ pub fn check_decl_initializer(&self,
local: &'gcx hir::Local,
init: &'gcx hir::Expr) -> Ty<'tcx>
{
let ref_bindings = self.tcx.pat_contains_ref_binding(&local.pat);
let ref_bindings = local.pat.contains_ref_binding();
let local_ty = self.local_ty(init.span, local.id);
if let Some(m) = ref_bindings {

View file

@ -92,7 +92,6 @@
use rustc::traits;
use rustc::ty::{self, Ty, MethodCall, TypeFoldable};
use rustc::infer::{self, GenericKind, SubregionOrigin, VerifyBound};
use hir::pat_util;
use rustc::ty::adjustment;
use rustc::ty::wf::ImpliedBound;
@ -434,7 +433,7 @@ fn resolve_regions_and_report_errors(&self) {
fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
let tcx = self.tcx;
debug!("regionck::visit_pat(pat={:?})", pat);
pat_util::pat_bindings(pat, |_, id, span, _| {
pat.each_binding(|_, id, span, _| {
// If we have a variable that contains region'd data, that
// data will be accessible from anywhere that the variable is
// accessed. We must be wary of loops like this:

View file

@ -542,11 +542,10 @@ fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_id: ast::NodeId)
-> bool
{
if let hir::TyPath(hir::QPath::Resolved(None, _)) = ast_ty.node {
let path_res = tcx.expect_resolution(ast_ty.id);
match path_res.base_def {
if let hir::TyPath(hir::QPath::Resolved(None, ref path)) = ast_ty.node {
match path.def {
Def::SelfTy(Some(def_id), None) |
Def::TyParam(def_id) if path_res.depth == 0 => {
Def::TyParam(def_id) => {
def_id == tcx.map.local_def_id(param_id)
}
_ => false
@ -1625,8 +1624,7 @@ fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>,
Some(ref tpb) => {
// FIXME(#8559) currently requires the unbound to be built-in.
if let Ok(kind_id) = kind_id {
let trait_def = tcx.expect_def(tpb.ref_id);
if trait_def != Def::Trait(kind_id) {
if tpb.path.def != Def::Trait(kind_id) {
tcx.sess.span_warn(span,
"default bound relaxed for a type parameter, but \
this does nothing because the given bound is not \

View file

@ -29,24 +29,21 @@
use super::Clean;
/// Attempt to inline the definition of a local node id into this AST.
/// Attempt to inline a definition into this AST.
///
/// This function will fetch the definition of the id specified, and if it is
/// from another crate it will attempt to inline the documentation from the
/// other crate into this crate.
/// This function will fetch the definition specified, and if it is
/// from another crate it will attempt to inline the documentation
/// from the other crate into this crate.
///
/// This is primarily used for `pub use` statements which are, in general,
/// implementation details. Inlining the documentation should help provide a
/// better experience when reading the documentation in this use case.
///
/// The returned value is `None` if the `id` could not be inlined, and `Some`
/// of a vector of items if it was successfully expanded.
pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Name>)
/// The returned value is `None` if the definition could not be inlined,
/// and `Some` of a vector of items if it was successfully expanded.
pub fn try_inline(cx: &DocContext, def: Def, into: Option<ast::Name>)
-> Option<Vec<clean::Item>> {
let def = match cx.tcx.expect_def_or_none(id) {
Some(def) => def,
None => return None,
};
if def == Def::Err { return None }
let did = def.def_id();
if did.is_local() { return None }
try_inline_def(cx, def).map(|vec| {

View file

@ -667,6 +667,7 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self
bindings: Vec<TypeBinding>, substs: &Substs) -> Path {
Path {
global: false,
def: Def::Err,
segments: vec![PathSegment {
name: name.to_string(),
params: external_path_params(cx, trait_did, has_self, bindings, substs)
@ -1728,13 +1729,12 @@ fn clean(&self, cx: &DocContext) -> Type {
},
TyTup(ref tys) => Tuple(tys.clean(cx)),
TyPath(hir::QPath::Resolved(None, ref path)) => {
let def = cx.tcx.expect_def(self.id);
if let Some(new_ty) = cx.ty_substs.borrow().get(&def).cloned() {
if let Some(new_ty) = cx.ty_substs.borrow().get(&path.def).cloned() {
return new_ty;
}
let mut alias = None;
if let Def::TyAlias(def_id) = def {
if let Def::TyAlias(def_id) = path.def {
// Substitute private type aliases
if let Some(node_id) = cx.tcx.map.as_local_node_id(def_id) {
if !cx.access_levels.borrow().is_exported(def_id) {
@ -1748,7 +1748,7 @@ fn clean(&self, cx: &DocContext) -> Type {
let mut ty_substs = FxHashMap();
let mut lt_substs = FxHashMap();
for (i, ty_param) in generics.ty_params.iter().enumerate() {
let ty_param_def = cx.tcx.expect_def(ty_param.id);
let ty_param_def = Def::TyParam(cx.tcx.map.local_def_id(ty_param.id));
if let Some(ty) = provided_params.types().get(i).cloned()
.cloned() {
ty_substs.insert(ty_param_def, ty.unwrap().clean(cx));
@ -1772,6 +1772,7 @@ fn clean(&self, cx: &DocContext) -> Type {
let trait_path = hir::Path {
span: p.span,
global: p.global,
def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()),
segments: segments.into(),
};
Type::QPath {
@ -1784,6 +1785,10 @@ fn clean(&self, cx: &DocContext) -> Type {
let trait_path = hir::Path {
span: self.span,
global: false,
def: cx.tcx_opt().map_or(Def::Err, |tcx| {
let def_id = tcx.tables().type_relative_path_defs[&self.id].def_id();
Def::Trait(tcx.associated_item(def_id).container.id())
}),
segments: vec![].into(),
};
Type::QPath {
@ -2194,6 +2199,7 @@ fn clean(&self, cx: &DocContext) -> Span {
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
pub struct Path {
pub global: bool,
pub def: Def,
pub segments: Vec<PathSegment>,
}
@ -2201,6 +2207,7 @@ impl Path {
pub fn singleton(name: String) -> Path {
Path {
global: false,
def: Def::Err,
segments: vec![PathSegment {
name: name,
params: PathParameters::AngleBracketed {
@ -2221,6 +2228,7 @@ impl Clean<Path> for hir::Path {
fn clean(&self, cx: &DocContext) -> Path {
Path {
global: self.global,
def: self.def,
segments: self.segments.clean(cx),
}
}
@ -2591,15 +2599,15 @@ fn clean(&self, cx: &DocContext) -> Vec<Item> {
});
let path = self.path.clean(cx);
let inner = if self.glob {
Import::Glob(resolve_use_source(cx, path, self.id))
Import::Glob(resolve_use_source(cx, path))
} else {
let name = self.name;
if !denied {
if let Some(items) = inline::try_inline(cx, self.id, Some(name)) {
if let Some(items) = inline::try_inline(cx, path.def, Some(name)) {
return items;
}
}
Import::Simple(name.clean(cx), resolve_use_source(cx, path, self.id))
Import::Simple(name.clean(cx), resolve_use_source(cx, path))
};
vec![Item {
name: None,
@ -2697,7 +2705,7 @@ fn name_from_pat(p: &hir::Pat) -> String {
match p.node {
PatKind::Wild => "_".to_string(),
PatKind::Binding(_, ref p, _) => p.node.to_string(),
PatKind::Binding(_, _, ref p, _) => p.node.to_string(),
PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p),
PatKind::Struct(ref name, ref fields, etc) => {
format!("{} {{ {}{} }}", qpath_to_string(name),
@ -2727,15 +2735,13 @@ fn name_from_pat(p: &hir::Pat) -> String {
}
}
/// Given a Type, resolve it using the def_map
/// Given a type Path, resolve it to a Type using the TyCtxt
fn resolve_type(cx: &DocContext,
path: Path,
id: ast::NodeId) -> Type {
debug!("resolve_type({:?},{:?})", path, id);
let def = cx.tcx.expect_def(id);
debug!("resolve_type: def={:?}", def);
let is_generic = match def {
let is_generic = match path.def {
Def::PrimTy(p) => match p {
hir::TyStr => return Primitive(PrimitiveType::Str),
hir::TyBool => return Primitive(PrimitiveType::Bool),
@ -2750,7 +2756,7 @@ fn resolve_type(cx: &DocContext,
Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true,
_ => false,
};
let did = register_def(&*cx, def);
let did = register_def(&*cx, path.def);
ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
}
@ -2782,17 +2788,17 @@ fn register_def(cx: &DocContext, def: Def) -> DefId {
did
}
fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSource {
fn resolve_use_source(cx: &DocContext, path: Path) -> ImportSource {
ImportSource {
did: if path.def == Def::Err {
None
} else {
Some(register_def(cx, path.def))
},
path: path,
did: resolve_def(cx, id),
}
}
fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<DefId> {
cx.tcx.expect_def_or_none(id).map(|def| register_def(cx, def))
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Macro {
pub source: String,
@ -2896,6 +2902,7 @@ fn lang_struct(cx: &DocContext, did: Option<DefId>,
did: did,
path: Path {
global: false,
def: Def::Err,
segments: vec![PathSegment {
name: name.to_string(),
params: PathParameters::AngleBracketed {

View file

@ -234,8 +234,13 @@ pub fn visit_mod_contents(&mut self, span: Span, attrs: hir::HirVec<ast::Attribu
/// and follows different rules.
///
/// Returns true if the target has been inlined.
fn maybe_inline_local(&mut self, id: ast::NodeId, renamed: Option<ast::Name>,
glob: bool, om: &mut Module, please_inline: bool) -> bool {
fn maybe_inline_local(&mut self,
id: ast::NodeId,
def: Def,
renamed: Option<ast::Name>,
glob: bool,
om: &mut Module,
please_inline: bool) -> bool {
fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
while let Some(id) = cx.tcx.map.get_enclosing_scope(node) {
@ -251,7 +256,9 @@ fn inherits_doc_hidden(cx: &core::DocContext, mut node: ast::NodeId) -> bool {
}
let tcx = self.cx.tcx;
let def = tcx.expect_def(id);
if def == Def::Err {
return false;
}
let def_did = def.def_id();
let use_attrs = tcx.map.attrs(id);
@ -368,13 +375,18 @@ pub fn visit_item(&mut self, item: &hir::Item,
}
});
let name = if is_glob { None } else { Some(name) };
if self.maybe_inline_local(item.id, name, is_glob, om, please_inline) {
if self.maybe_inline_local(item.id,
path.def,
name,
is_glob,
om,
please_inline) {
return;
}
}
om.imports.push(Import {
name: item.name,
name: name,
id: item.id,
vis: item.vis.clone(),
attrs: item.attrs.clone(),

View file

@ -16,7 +16,7 @@ enum Stuff {
Bar = foo
//~^ ERROR attempt to use a non-constant value in a constant
//~^^ ERROR constant evaluation error
//~| non-constant path in constant expression
//~| unresolved path in constant expression
}
println!("{}", Stuff::Bar);