rustc: embed path resolutions into the HIR instead of keeping DefMap.
This commit is contained in:
parent
bc096549e8
commit
962633cdbb
@ -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 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
|
||||
hir::ExprBreak(label, ref opt_expr) => {
|
||||
let v = self.opt_expr(opt_expr, pred);
|
||||
let loop_scope = self.find_scope(expr, label.map(|l| l.node));
|
||||
let loop_scope = self.find_scope(expr, label);
|
||||
let b = self.add_ast_node(expr.id, &[v]);
|
||||
self.add_exiting_edge(expr, b,
|
||||
loop_scope, loop_scope.break_index);
|
||||
@ -292,7 +290,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
// Visit the guard expression
|
||||
let guard_exit = self.expr(&guard, guard_start);
|
||||
|
||||
let this_has_bindings = pat_util::pat_contains_bindings_or_wild(&pat);
|
||||
let this_has_bindings = pat.contains_bindings_or_wild();
|
||||
|
||||
// If both this pattern and the previous pattern
|
||||
// were free of bindings, they must consist only
|
||||
@ -570,23 +568,16 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
|
||||
fn find_scope(&self,
|
||||
expr: &hir::Expr,
|
||||
label: Option<ast::Name>) -> LoopScope {
|
||||
if label.is_none() {
|
||||
return *self.loop_scopes.last().unwrap();
|
||||
}
|
||||
|
||||
match self.tcx.expect_def(expr.id) {
|
||||
Def::Label(loop_id) => {
|
||||
label: Option<hir::Label>) -> LoopScope {
|
||||
match label {
|
||||
None => *self.loop_scopes.last().unwrap(),
|
||||
Some(label) => {
|
||||
for l in &self.loop_scopes {
|
||||
if l.loop_id == loop_id {
|
||||
if l.loop_id == label.loop_id {
|
||||
return *l;
|
||||
}
|
||||
}
|
||||
span_bug!(expr.span, "no loop scope for id {}", loop_id);
|
||||
}
|
||||
|
||||
r => {
|
||||
span_bug!(expr.span, "bad entry `{:?}` in def_map for label", r);
|
||||
span_bug!(expr.span, "no loop scope for id {}", label.loop_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,14 +83,6 @@ impl PathResolution {
|
||||
PathResolution { base_def: def, depth: 0 }
|
||||
}
|
||||
|
||||
/// Get the definition, if fully resolved, otherwise panic.
|
||||
pub fn full_def(&self) -> Def {
|
||||
if self.depth != 0 {
|
||||
bug!("path not fully resolved: {:?}", self);
|
||||
}
|
||||
self.base_def
|
||||
}
|
||||
|
||||
pub fn kind_name(&self) -> &'static str {
|
||||
if self.depth != 0 {
|
||||
"associated item"
|
||||
|
@ -38,6 +38,7 @@ use syntax::ast::{NodeId, CRATE_NODE_ID, Name, Attribute};
|
||||
use syntax::codemap::Spanned;
|
||||
use syntax_pos::Span;
|
||||
use hir::*;
|
||||
use hir::def::Def;
|
||||
use hir::map::Map;
|
||||
use super::itemlikevisit::DeepVisitor;
|
||||
|
||||
@ -155,6 +156,9 @@ pub trait Visitor<'v> : Sized {
|
||||
fn visit_id(&mut self, _node_id: NodeId) {
|
||||
// Nothing to do.
|
||||
}
|
||||
fn visit_def_mention(&mut self, _def: Def) {
|
||||
// Nothing to do.
|
||||
}
|
||||
fn visit_name(&mut self, _span: Span, _name: Name) {
|
||||
// Nothing to do.
|
||||
}
|
||||
@ -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);
|
||||
|
@ -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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
let proj_start = p.segments.len() - resolution.depth;
|
||||
let path = P(hir::Path {
|
||||
global: p.global,
|
||||
def: resolution.base_def,
|
||||
segments: p.segments[..proj_start].iter().enumerate().map(|(i, segment)| {
|
||||
let param_mode = match (qself_position, param_mode) {
|
||||
(Some(j), ParamMode::Optional) if i < j => {
|
||||
@ -353,12 +376,14 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
|
||||
fn lower_item_kind(&mut self,
|
||||
id: NodeId,
|
||||
name: &mut Name,
|
||||
attrs: &hir::HirVec<Attribute>,
|
||||
vis: &mut hir::Visibility,
|
||||
@ -690,7 +717,7 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
}).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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
|
||||
// `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 @@ impl<'a> LoweringContext<'a> {
|
||||
|
||||
// `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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
|
||||
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 @@ impl<'a> LoweringContext<'a> {
|
||||
})
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -436,7 +436,7 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> {
|
||||
fn visit_pat(&mut self, pat: &'ast hir::Pat) {
|
||||
let parent_def = self.parent_def;
|
||||
|
||||
if let hir::PatKind::Binding(_, name, _) = pat.node {
|
||||
if let hir::PatKind::Binding(_, _, name, _) = pat.node {
|
||||
let def = self.create_def(pat.id, DefPathData::Binding(name.node.as_str()));
|
||||
self.parent_def = Some(def);
|
||||
}
|
||||
|
@ -658,7 +658,7 @@ impl<'ast> Map<'ast> {
|
||||
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))
|
||||
}
|
||||
|
@ -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 @@ impl fmt::Display for Path {
|
||||
}
|
||||
}
|
||||
|
||||
impl Path {
|
||||
/// Convert a span and an identifier to the corresponding
|
||||
/// 1-segment path.
|
||||
pub fn from_name(s: Span, name: Name) -> Path {
|
||||
Path {
|
||||
span: s,
|
||||
global: false,
|
||||
segments: hir_vec![PathSegment {
|
||||
name: name,
|
||||
parameters: PathParameters::none()
|
||||
}],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A segment of a path: an identifier, an optional lifetime, and a set of
|
||||
/// types.
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
@ -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 type ExplicitSelf = Spanned<SelfKind>;
|
||||
|
||||
impl Arg {
|
||||
pub fn to_self(&self) -> Option<ExplicitSelf> {
|
||||
if let PatKind::Binding(BindByValue(mutbl), name, _) = self.pat.node {
|
||||
if let PatKind::Binding(BindByValue(mutbl), _, name, _) = self.pat.node {
|
||||
if name.node == keywords::SelfValue.name() {
|
||||
return match self.ty.node {
|
||||
TyInfer => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
|
||||
@ -1241,7 +1246,7 @@ impl Arg {
|
||||
}
|
||||
|
||||
pub fn is_self(&self) -> bool {
|
||||
if let PatKind::Binding(_, name, _) = self.pat.node {
|
||||
if let PatKind::Binding(_, _, name, _) = self.pat.node {
|
||||
name.node == keywords::SelfValue.name()
|
||||
} else {
|
||||
false
|
||||
|
@ -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 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
match pat.node {
|
||||
PatKind::Lit(_) |
|
||||
PatKind::Range(..) |
|
||||
PatKind::Path(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,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1481,11 +1481,11 @@ impl<'a> State<'a> {
|
||||
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 @@ impl<'a> State<'a> {
|
||||
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 @@ impl<'a> State<'a> {
|
||||
// is that it doesn't matter
|
||||
match pat.node {
|
||||
PatKind::Wild => word(&mut self.s, "_")?,
|
||||
PatKind::Binding(binding_mode, ref path1, ref sub) => {
|
||||
PatKind::Binding(binding_mode, _, ref path1, ref sub) => {
|
||||
match binding_mode {
|
||||
hir::BindByRef(mutbl) => {
|
||||
self.word_nbsp("ref")?;
|
||||
@ -2185,7 +2185,7 @@ impl<'a> State<'a> {
|
||||
if let Some(eself) = input.to_self() {
|
||||
self.print_explicit_self(&eself)?;
|
||||
} else {
|
||||
let invalid = if let PatKind::Binding(_, name, _) = input.pat.node {
|
||||
let invalid = if let PatKind::Binding(_, _, name, _) = input.pat.node {
|
||||
name.node == keywords::Invalid.name()
|
||||
} else {
|
||||
false
|
||||
|
@ -1441,7 +1441,7 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
|
||||
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 @@ impl<'a, 'gcx, 'tcx> Rebuilder<'a, 'gcx, 'tcx> {
|
||||
hir::Path {
|
||||
span: path.span,
|
||||
global: path.global,
|
||||
def: path.def,
|
||||
segments: new_segs.into()
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// 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
|
||||
|
@ -14,7 +14,7 @@
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use hir::map as ast_map;
|
||||
use hir::{self, pat_util, PatKind};
|
||||
use hir::{self, PatKind};
|
||||
use hir::intravisit::{self, Visitor};
|
||||
use hir::itemlikevisit::ItemLikeVisitor;
|
||||
|
||||
@ -86,9 +86,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn lookup_and_handle_definition(&mut self, id: ast::NodeId) {
|
||||
let def = self.tcx.expect_def(id);
|
||||
|
||||
fn handle_definition(&mut self, id: ast::NodeId, def: Def) {
|
||||
// If `bar` is a trait item, make sure to mark Foo as alive in `Foo::bar`
|
||||
match def {
|
||||
Def::AssociatedTy(..) | Def::Method(_) | Def::AssociatedConst(_)
|
||||
@ -147,12 +145,10 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_field_pattern_match(&mut self, lhs: &hir::Pat,
|
||||
fn handle_field_pattern_match(&mut self, lhs: &hir::Pat, def: Def,
|
||||
pats: &[codemap::Spanned<hir::FieldPat>]) {
|
||||
let variant = match self.tcx.tables().node_id_to_type(lhs.id).sty {
|
||||
ty::TyAdt(adt, _) => {
|
||||
adt.variant_of_def(self.tcx.expect_def(lhs.id))
|
||||
}
|
||||
ty::TyAdt(adt, _) => adt.variant_of_def(def),
|
||||
_ => span_bug!(lhs.span, "non-ADT in struct pattern")
|
||||
};
|
||||
for pat in pats {
|
||||
@ -240,8 +236,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
|
||||
|
||||
fn visit_arm(&mut self, arm: &hir::Arm) {
|
||||
if arm.pats.len() == 1 {
|
||||
let pat = &*arm.pats[0];
|
||||
let variants = pat_util::necessary_variants(&self.tcx.def_map.borrow(), pat);
|
||||
let variants = arm.pats[0].necessary_variants();
|
||||
|
||||
// Inside the body, ignore constructions of variants
|
||||
// necessary for the pattern to match. Those construction sites
|
||||
@ -276,14 +272,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &hir::Pat) {
|
||||
let def_map = &self.tcx.def_map;
|
||||
match pat.node {
|
||||
PatKind::Struct(_, ref fields, _) => {
|
||||
self.handle_field_pattern_match(pat, fields);
|
||||
PatKind::Struct(hir::QPath::Resolved(_, ref path), ref fields, _) => {
|
||||
self.handle_field_pattern_match(pat, path.def, fields);
|
||||
}
|
||||
_ if pat_util::pat_is_const(&def_map.borrow(), pat) => {
|
||||
// it might be the only use of a const
|
||||
self.lookup_and_handle_definition(pat.id)
|
||||
PatKind::Path(ref qpath @ hir::QPath::TypeRelative(..)) => {
|
||||
let def = self.tcx.tables().qpath_def(qpath, pat.id);
|
||||
self.handle_definition(pat.id, def);
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
@ -294,7 +289,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) {
|
||||
self.lookup_and_handle_definition(id);
|
||||
self.handle_definition(id, path.def);
|
||||
intravisit::walk_path(self, path);
|
||||
}
|
||||
}
|
||||
|
@ -186,8 +186,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
|
||||
hir::ExprInlineAsm(..) => {
|
||||
self.require_unsafe(expr.span, "use of inline assembly");
|
||||
}
|
||||
hir::ExprPath(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) {
|
||||
|
@ -19,7 +19,6 @@ pub use self::MatchMode::*;
|
||||
use self::TrackMatchMode::*;
|
||||
use self::OverloadedCallType::*;
|
||||
|
||||
use hir::pat_util;
|
||||
use hir::def::Def;
|
||||
use hir::def_id::{DefId};
|
||||
use infer::InferCtxt;
|
||||
@ -622,7 +621,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
match local.init {
|
||||
None => {
|
||||
let delegate = &mut self.delegate;
|
||||
pat_util::pat_bindings(&local.pat, |_, id, span, _| {
|
||||
local.pat.each_binding(|_, id, span, _| {
|
||||
delegate.decl_without_init(id, span);
|
||||
})
|
||||
}
|
||||
@ -957,7 +956,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
let infcx = self.mc.infcx;
|
||||
let delegate = &mut self.delegate;
|
||||
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
|
||||
if let PatKind::Binding(bmode, ..) = pat.node {
|
||||
if let PatKind::Binding(bmode, def_id, ..) = pat.node {
|
||||
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}", cmt_pat, pat, match_mode);
|
||||
|
||||
// pat_ty: the type of the binding being produced.
|
||||
@ -965,8 +964,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Each match binding is effectively an assignment to the
|
||||
// binding being produced.
|
||||
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty,
|
||||
tcx.expect_def(pat.id)) {
|
||||
let def = Def::Local(def_id);
|
||||
if let Ok(binding_cmt) = mc.cat_def(pat.id, pat.span, pat_ty, def) {
|
||||
delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init);
|
||||
}
|
||||
|
||||
@ -992,9 +991,16 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
// to the above loop's visit of than the bindings that form
|
||||
// the leaves of the pattern tree structure.
|
||||
return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
|
||||
match tcx.expect_def_or_none(pat.id) {
|
||||
Some(Def::Variant(variant_did)) |
|
||||
Some(Def::VariantCtor(variant_did, ..)) => {
|
||||
let qpath = match pat.node {
|
||||
PatKind::Path(ref qpath) |
|
||||
PatKind::TupleStruct(ref qpath, ..) |
|
||||
PatKind::Struct(ref qpath, ..) => qpath,
|
||||
_ => return
|
||||
};
|
||||
let def = tcx.tables().qpath_def(qpath, pat.id);
|
||||
match def {
|
||||
Def::Variant(variant_did) |
|
||||
Def::VariantCtor(variant_did, ..) => {
|
||||
let enum_did = tcx.parent_def_id(variant_did).unwrap();
|
||||
let downcast_cmt = if tcx.lookup_adt_def(enum_did).is_univariant() {
|
||||
cmt_pat
|
||||
@ -1006,14 +1012,12 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
debug!("variant downcast_cmt={:?} pat={:?}", downcast_cmt, pat);
|
||||
delegate.matched_pat(pat, downcast_cmt, match_mode);
|
||||
}
|
||||
Some(Def::Struct(..)) | Some(Def::StructCtor(..)) | Some(Def::Union(..)) |
|
||||
Some(Def::TyAlias(..)) | Some(Def::AssociatedTy(..)) | Some(Def::SelfTy(..)) => {
|
||||
Def::Struct(..) | Def::StructCtor(..) | Def::Union(..) |
|
||||
Def::TyAlias(..) | Def::AssociatedTy(..) | Def::SelfTy(..) => {
|
||||
debug!("struct cmt_pat={:?} pat={:?}", cmt_pat, pat);
|
||||
delegate.matched_pat(pat, cmt_pat, match_mode);
|
||||
}
|
||||
None | Some(Def::Local(..)) |
|
||||
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => {}
|
||||
def => bug!("unexpected definition: {:?}", def)
|
||||
_ => {}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -160,11 +160,10 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {
|
||||
|
||||
impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> {
|
||||
fn visit_expr(&mut self, expr: &hir::Expr) {
|
||||
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) => {
|
||||
|
@ -111,7 +111,6 @@ use self::VarKind::*;
|
||||
|
||||
use dep_graph::DepNode;
|
||||
use hir::def::*;
|
||||
use hir::pat_util;
|
||||
use ty::{self, TyCtxt, ParameterEnvironment};
|
||||
use traits::{self, Reveal};
|
||||
use ty::subst::Subst;
|
||||
@ -379,7 +378,7 @@ fn visit_fn(ir: &mut IrMaps,
|
||||
debug!("creating fn_maps: {:?}", &fn_maps as *const IrMaps);
|
||||
|
||||
for arg in &decl.inputs {
|
||||
pat_util::pat_bindings(&arg.pat, |_bm, arg_id, _x, path1| {
|
||||
arg.pat.each_binding(|_bm, arg_id, _x, path1| {
|
||||
debug!("adding argument {}", arg_id);
|
||||
let name = path1.node;
|
||||
fn_maps.add_variable(Arg(arg_id, name));
|
||||
@ -412,7 +411,7 @@ fn visit_fn(ir: &mut IrMaps,
|
||||
}
|
||||
|
||||
fn visit_local(ir: &mut IrMaps, local: &hir::Local) {
|
||||
pat_util::pat_bindings(&local.pat, |_, p_id, sp, path1| {
|
||||
local.pat.each_binding(|_, p_id, sp, path1| {
|
||||
debug!("adding local variable {}", p_id);
|
||||
let name = path1.node;
|
||||
ir.add_live_node_for_node(p_id, VarDefNode(sp));
|
||||
@ -426,7 +425,7 @@ fn visit_local(ir: &mut IrMaps, local: &hir::Local) {
|
||||
|
||||
fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) {
|
||||
for pat in &arm.pats {
|
||||
pat_util::pat_bindings(&pat, |bm, p_id, sp, path1| {
|
||||
pat.each_binding(|bm, p_id, sp, path1| {
|
||||
debug!("adding local variable {} from match with bm {:?}",
|
||||
p_id, bm);
|
||||
let name = path1.node;
|
||||
@ -443,10 +442,9 @@ fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) {
|
||||
fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
|
||||
match expr.node {
|
||||
// live nodes required for uses or definitions of variables:
|
||||
hir::ExprPath(_) => {
|
||||
let def = ir.tcx.expect_def(expr.id);
|
||||
debug!("expr {}: path that leads to {:?}", expr.id, def);
|
||||
if let Def::Local(..) = def {
|
||||
hir::ExprPath(hir::QPath::Resolved(_, ref path)) => {
|
||||
debug!("expr {}: path that leads to {:?}", expr.id, path.def);
|
||||
if let Def::Local(..) = path.def {
|
||||
ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
||||
}
|
||||
intravisit::walk_expr(ir, expr);
|
||||
@ -495,7 +493,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
|
||||
hir::ExprBlock(..) | hir::ExprAssign(..) | hir::ExprAssignOp(..) |
|
||||
hir::ExprStruct(..) | hir::ExprRepeat(..) |
|
||||
hir::ExprInlineAsm(..) | hir::ExprBox(..) |
|
||||
hir::ExprType(..) => {
|
||||
hir::ExprType(..) | hir::ExprPath(hir::QPath::TypeRelative(..)) => {
|
||||
intravisit::walk_expr(ir, expr);
|
||||
}
|
||||
}
|
||||
@ -587,7 +585,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
fn pat_bindings<F>(&mut self, pat: &hir::Pat, mut f: F) where
|
||||
F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId),
|
||||
{
|
||||
pat_util::pat_bindings(pat, |_bm, p_id, sp, _n| {
|
||||
pat.each_binding(|_bm, p_id, sp, _n| {
|
||||
let ln = self.live_node(p_id, sp);
|
||||
let var = self.variable(p_id, sp);
|
||||
f(self, ln, var, sp, p_id);
|
||||
@ -684,22 +682,13 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn find_loop_scope(&self,
|
||||
opt_label: Option<ast::Name>,
|
||||
id: NodeId,
|
||||
opt_label: Option<hir::Label>,
|
||||
sp: Span)
|
||||
-> NodeId {
|
||||
match opt_label {
|
||||
Some(_) => {
|
||||
// Refers to a labeled loop. Use the results of resolve
|
||||
// to find with one
|
||||
match self.ir.tcx.expect_def(id) {
|
||||
Def::Label(loop_id) => loop_id,
|
||||
_ => span_bug!(sp, "label on break/loop \
|
||||
doesn't refer to a loop")
|
||||
}
|
||||
}
|
||||
Some(label) => label.loop_id,
|
||||
None => {
|
||||
// Vanilla 'break' or 'loop', so use the enclosing
|
||||
// Vanilla 'break' or 'continue', so use the enclosing
|
||||
// loop scope
|
||||
if self.loop_scope.is_empty() {
|
||||
span_bug!(sp, "break outside loop");
|
||||
@ -922,8 +911,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
match expr.node {
|
||||
// Interesting cases with control flow or which gen/kill
|
||||
|
||||
hir::ExprPath(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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
hir::ExprBreak(opt_label, ref opt_expr) => {
|
||||
// Find which label this break jumps to
|
||||
let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span);
|
||||
let sc = self.find_loop_scope(opt_label, expr.span);
|
||||
|
||||
// Now that we know the label we're going to,
|
||||
// look it up in the break loop nodes table
|
||||
@ -1050,7 +1039,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
hir::ExprAgain(opt_label) => {
|
||||
// Find which label this expr continues to
|
||||
let sc = self.find_loop_scope(opt_label.map(|l| l.node), expr.id, expr.span);
|
||||
let sc = self.find_loop_scope(opt_label, expr.span);
|
||||
|
||||
// Now that we know the label we're going to,
|
||||
// look it up in the continue loop nodes table
|
||||
@ -1246,8 +1235,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
|
||||
-> LiveNode {
|
||||
match expr.node {
|
||||
hir::ExprPath(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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: u32)
|
||||
fn access_path(&mut self, id: NodeId, path: &hir::Path, succ: LiveNode, acc: u32)
|
||||
-> LiveNode {
|
||||
match self.ir.tcx.expect_def(expr.id) {
|
||||
match path.def {
|
||||
Def::Local(def_id) => {
|
||||
let nid = self.ir.tcx.map.as_local_node_id(def_id).unwrap();
|
||||
let ln = self.live_node(expr.id, expr.span);
|
||||
let ln = self.live_node(id, path.span);
|
||||
if acc != 0 {
|
||||
self.init_from_succ(ln, succ);
|
||||
let var = self.variable(nid, expr.span);
|
||||
let var = self.variable(nid, path.span);
|
||||
self.acc(ln, var, acc);
|
||||
}
|
||||
ln
|
||||
@ -1482,8 +1471,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
fn warn_about_unused_args(&self, decl: &hir::FnDecl, entry_ln: LiveNode) {
|
||||
for arg in &decl.inputs {
|
||||
pat_util::pat_bindings(&arg.pat, |_bm, p_id, sp, path1| {
|
||||
arg.pat.each_binding(|_bm, p_id, sp, path1| {
|
||||
let var = self.variable(p_id, sp);
|
||||
// Ignore unused self.
|
||||
let name = path1.node;
|
||||
|
@ -488,8 +488,9 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
hir::ExprPath(_) => {
|
||||
self.cat_def(expr.id, expr.span, expr_ty, self.tcx().expect_def(expr.id))
|
||||
hir::ExprPath(ref qpath) => {
|
||||
let def = self.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 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Note: This goes up here (rather than within the PatKind::TupleStruct arm
|
||||
// alone) because PatKind::Struct can also refer to variants.
|
||||
let cmt = match self.tcx().expect_def_or_none(pat.id) {
|
||||
Some(Def::Err) => return Err(()),
|
||||
Some(Def::Variant(variant_did)) |
|
||||
Some(Def::VariantCtor(variant_did, ..)) => {
|
||||
// univariant enums do not need downcasts
|
||||
let enum_did = self.tcx().parent_def_id(variant_did).unwrap();
|
||||
if !self.tcx().lookup_adt_def(enum_did).is_univariant() {
|
||||
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
|
||||
} else {
|
||||
cmt
|
||||
let cmt = match pat.node {
|
||||
PatKind::Path(hir::QPath::Resolved(_, ref path)) |
|
||||
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
|
||||
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
|
||||
match path.def {
|
||||
Def::Err => return Err(()),
|
||||
Def::Variant(variant_did) |
|
||||
Def::VariantCtor(variant_did, ..) => {
|
||||
// univariant enums do not need downcasts
|
||||
let enum_did = self.tcx().parent_def_id(variant_did).unwrap();
|
||||
if !self.tcx().lookup_adt_def(enum_did).is_univariant() {
|
||||
self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
|
||||
} else {
|
||||
cmt
|
||||
}
|
||||
}
|
||||
_ => cmt
|
||||
}
|
||||
}
|
||||
_ => cmt
|
||||
};
|
||||
|
||||
match pat.node {
|
||||
PatKind::TupleStruct(_, ref subpats, ddpos) => {
|
||||
let expected_len = match self.tcx().expect_def(pat.id) {
|
||||
PatKind::TupleStruct(ref qpath, ref subpats, ddpos) => {
|
||||
let def = self.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()
|
||||
|
@ -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)
|
||||
|
@ -21,7 +21,7 @@ use self::ScopeChain::*;
|
||||
use dep_graph::DepNode;
|
||||
use hir::map::Map;
|
||||
use session::Session;
|
||||
use hir::def::{Def, DefMap};
|
||||
use hir::def::Def;
|
||||
use hir::def_id::DefId;
|
||||
use middle::region;
|
||||
use ty;
|
||||
@ -65,7 +65,6 @@ struct LifetimeContext<'a, 'tcx: 'a> {
|
||||
hir_map: &'a Map<'tcx>,
|
||||
map: &'a mut NamedRegionMap,
|
||||
scope: Scope<'a>,
|
||||
def_map: &'a DefMap,
|
||||
// Deep breath. Our representation for poly trait refs contains a single
|
||||
// binder and thus we only allow a single level of quantification. However,
|
||||
// the syntax of Rust permits quantification in two places, e.g., `T: for <'a> Foo<'a>`
|
||||
@ -109,8 +108,7 @@ type Scope<'a> = &'a ScopeChain<'a>;
|
||||
static ROOT_SCOPE: ScopeChain<'static> = RootScope;
|
||||
|
||||
pub fn krate(sess: &Session,
|
||||
hir_map: &Map,
|
||||
def_map: &DefMap)
|
||||
hir_map: &Map)
|
||||
-> Result<NamedRegionMap, usize> {
|
||||
let _task = hir_map.dep_graph.in_task(DepNode::ResolveLifetimes);
|
||||
let krate = hir_map.krate();
|
||||
@ -124,7 +122,6 @@ pub fn krate(sess: &Session,
|
||||
hir_map: hir_map,
|
||||
map: &mut map,
|
||||
scope: &ROOT_SCOPE,
|
||||
def_map: def_map,
|
||||
trait_ref_hack: false,
|
||||
labels_in_fn: vec![],
|
||||
}, krate);
|
||||
@ -247,8 +244,8 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> {
|
||||
hir::TyPath(hir::QPath::Resolved(None, ref path)) => {
|
||||
// if this path references a trait, then this will resolve to
|
||||
// a trait ref, which introduces a binding scope.
|
||||
match self.def_map.get(&ty.id).map(|d| (d.base_def, d.depth)) {
|
||||
Some((Def::Trait(..), 0)) => {
|
||||
match path.def {
|
||||
Def::Trait(..) => {
|
||||
self.with(LateScope(&[], self.scope), |_, this| {
|
||||
this.visit_path(path, ty.id);
|
||||
});
|
||||
@ -541,7 +538,6 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
||||
hir_map: hir_map,
|
||||
map: *map,
|
||||
scope: &wrap_scope,
|
||||
def_map: self.def_map,
|
||||
trait_ref_hack: self.trait_ref_hack,
|
||||
labels_in_fn: self.labels_in_fn.clone(),
|
||||
};
|
||||
|
@ -468,8 +468,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ use dep_graph::{DepGraph, DepTrackingMap};
|
||||
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 @@ impl<'a, 'gcx, 'tcx> 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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
/// 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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
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())),
|
||||
|
@ -19,7 +19,7 @@ pub use self::fold::TypeFoldable;
|
||||
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 @@ impl Visibility {
|
||||
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
|| 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> {
|
||||
|
@ -14,7 +14,6 @@ use hir::def_id::DefId;
|
||||
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 @@ impl<'tcx> ParameterEnvironment<'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) => {
|
||||
|
@ -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})
|
||||
},
|
||||
|
@ -23,8 +23,8 @@ use rustc_data_structures::indexed_vec::Idx;
|
||||
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 @@ impl Witness {
|
||||
|
||||
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()
|
||||
|
@ -19,8 +19,6 @@ use eval::report_const_eval_err;
|
||||
|
||||
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 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> {
|
||||
|
||||
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));
|
||||
|
@ -19,9 +19,8 @@ use rustc::hir::map as ast_map;
|
||||
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 syntax_pos::{self, Span};
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,8 +163,9 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => self.lower_variant_or_leaf(pat, vec![])
|
||||
_ => self.lower_variant_or_leaf(def, vec![])
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,8 +243,7 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.lower_variant_or_leaf(pat, subpatterns)
|
||||
self.lower_variant_or_leaf(def, subpatterns)
|
||||
}
|
||||
};
|
||||
|
||||
@ -418,11 +420,11 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'gcx, 'tcx> PatternContext<'a, 'gcx, 'tcx> {
|
||||
PatternKind::Leaf { subpatterns: subpatterns }
|
||||
}
|
||||
|
||||
def => {
|
||||
span_bug!(pat.span, "inappropriate def for pattern: {:?}", def);
|
||||
}
|
||||
_ => bug!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -840,9 +840,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|
||||
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 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
|
||||
|
||||
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,
|
||||
|
@ -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,
|
||||
|
@ -23,7 +23,7 @@ use syntax_pos::{Span, NO_EXPANSION, COMMAND_LINE_EXPN, BytePos};
|
||||
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 @@ impl<'a, 'hash, 'tcx> visit::Visitor<'tcx> for StrictVersionHashVisitor<'a, 'has
|
||||
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 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
|
||||
// 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 @@ impl<'a, 'hash, 'tcx> StrictVersionHashVisitor<'a, 'hash, 'tcx> {
|
||||
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 +
|
||||
|
@ -288,12 +288,17 @@ impl LateLintPass for NonSnakeCase {
|
||||
}
|
||||
|
||||
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 @@ impl LateLintPass for NonUpperCaseGlobals {
|
||||
// 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,
|
||||
|
@ -167,7 +167,7 @@ impl LateLintPass for NonShorthandFieldPatterns {
|
||||
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 @@ impl LateLintPass for MissingDoc {
|
||||
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 @@ impl LateLintPass for Deprecated {
|
||||
&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 @@ impl LateLintPass for UnconditionalRecursion {
|
||||
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 @@ impl LateLintPass for UnconditionalRecursion {
|
||||
// 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 @@ impl LateLintPass for MutableTransmutes {
|
||||
(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;
|
||||
}
|
||||
|
@ -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 @@ impl UnusedMut {
|
||||
|
||||
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("_") {
|
||||
|
@ -18,7 +18,7 @@ use schema::*;
|
||||
|
||||
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 @@ impl<'a, 'b, 'tcx, 'v> Visitor<'v> for SideTableEncodingIdVisitor<'a, 'b, 'tcx>
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
|
@ -597,7 +597,7 @@ impl<'a, 'tcx> EncodeContext<'a, '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("")
|
||||
|
@ -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 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
@ -18,7 +18,6 @@ use rustc::hir::map;
|
||||
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])
|
||||
|
@ -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)
|
||||
|
@ -12,10 +12,10 @@ use self::Context::*;
|
||||
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 @@ impl<'a, 'ast, 'v> Visitor<'v> for CheckLoopVisitor<'a, 'ast> {
|
||||
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)
|
||||
|
@ -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 @@ use std::cell::RefCell;
|
||||
|
||||
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 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckCrateVisitor<'a, 'ast> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'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 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
|
||||
|
||||
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 @@ impl<'a, 'ast: 'a> Visitor<'ast> for CheckItemRecursionVisitor<'a, 'ast> {
|
||||
// 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);
|
||||
|
@ -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 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ impl<'b, 'a, 'tcx: 'a> Visitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
|
||||
}
|
||||
|
||||
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 @@ impl<'b, 'a, 'tcx: 'a> Visitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivacyVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
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 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
|
||||
|
||||
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);
|
||||
|
@ -1201,11 +1201,11 @@ impl<'a> ty::NodeIdTree for Resolver<'a> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a> hir::lowering::Resolver for Resolver<'a> {
|
||||
def: Def::Err,
|
||||
};
|
||||
resolve_error(self, path.span, error);
|
||||
Def::Err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -274,12 +274,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
}
|
||||
|
||||
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 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
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 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
}
|
||||
|
||||
// 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 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
|
||||
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 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
|
||||
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 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor for DumpVisitor<'l, 'tcx, 'll, D>
|
||||
|
||||
// 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 {
|
||||
|
@ -42,8 +42,8 @@ pub mod external_data;
|
||||
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 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
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 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
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 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
}
|
||||
|
||||
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()),
|
||||
}
|
||||
}
|
||||
|
@ -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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
|
||||
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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
}
|
||||
}
|
||||
|
||||
// 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
// 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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
_ => {
|
||||
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 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
|
||||
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) {
|
||||
|
@ -103,7 +103,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, '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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
// 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,
|
||||
|
@ -218,12 +218,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,9 +83,8 @@ use self::TupleArgumentsFlag::*;
|
||||
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 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
// 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
// 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
{
|
||||
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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
};
|
||||
|
||||
// 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
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 {
|
||||
|
@ -92,7 +92,6 @@ use rustc::ty::subst::Substs;
|
||||
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 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
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:
|
||||
|
@ -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 \
|
||||
|
@ -29,24 +29,21 @@ use clean::{self, GetDefId};
|
||||
|
||||
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| {
|
||||
|
@ -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 @@ impl Clean<Type> for hir::Ty {
|
||||
},
|
||||
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 @@ impl Clean<Type> for hir::Ty {
|
||||
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 @@ impl Clean<Type> for hir::Ty {
|
||||
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 @@ impl Clean<Type> for hir::Ty {
|
||||
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 @@ impl Clean<Span> for syntax_pos::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 @@ impl Clean<Vec<Item>> for doctree::Import {
|
||||
});
|
||||
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 {
|
||||
|
@ -234,8 +234,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
/// 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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
|
||||
}
|
||||
});
|
||||
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(),
|
||||
|
@ -16,7 +16,7 @@ fn main() {
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user