rustc: embed path resolutions into the HIR instead of keeping DefMap.
This commit is contained in:
parent
bc096549e8
commit
962633cdbb
55 changed files with 951 additions and 949 deletions
|
|
@ -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) => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue