提交 cf468206 编写于 作者: V Vadim Petrochenkov

Refactor away some functions from hir::pat_util

上级 216f5fba
......@@ -456,8 +456,7 @@ fn match_(&mut self, id: ast::NodeId, discr: &hir::Expr,
// Visit the guard expression
let guard_exit = self.expr(&guard, guard_start);
let this_has_bindings = pat_util::pat_contains_bindings_or_wild(
&self.tcx.def_map.borrow(), &pat);
let this_has_bindings = pat_util::pat_contains_bindings_or_wild(&pat);
// If both this pattern and the previous pattern
// were free of bindings, they must consist only
......
......@@ -524,14 +524,7 @@ pub enum PatKind {
/// Represents a wildcard pattern (`_`)
Wild,
/// A `PatKind::Ident` may either be a new bound variable,
/// or a unit struct/variant pattern, or a const pattern (in the last two cases
/// the third field must be `None`).
///
/// In the unit or const pattern case, the parser can't determine
/// which it is. The resolver determines this, and
/// records this pattern's `NodeId` in an auxiliary
/// set (of "PatIdents that refer to unit patterns or constants").
/// A fresh binding `ref mut binding @ OPT_SUBPATTERN`.
Binding(BindingMode, Spanned<Name>, Option<P<Pat>>),
/// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
......@@ -547,10 +540,8 @@ pub enum PatKind {
/// Such pattern can be resolved to a unit struct/variant or a constant.
Path(Path),
/// An associated const named using the qualified path `<T>::CONST` or
/// `<T as Trait>::CONST`. Associated consts from inherent impls can be
/// referred to as simply `T::CONST`, in which case they will end up as
/// PatKind::Path, and the resolver will have to sort that out.
/// A path pattern written in qualified form, i.e. `<T as Trait>::CONST` or `<T>::CONST`.
/// Such patterns can only refer to associated constants at the moment.
QPath(QSelf, Path),
/// A tuple pattern `(a, b)`.
......
......@@ -10,14 +10,12 @@
use hir::def::*;
use hir::def_id::DefId;
use hir::{self, PatKind};
use ty::TyCtxt;
use util::nodemap::FnvHashMap;
use syntax::ast;
use hir::{self, PatKind};
use syntax::codemap::{respan, Span, Spanned, DUMMY_SP};
use syntax::codemap::{Span, Spanned, DUMMY_SP};
use std::cell::RefCell;
use std::iter::{Enumerate, ExactSizeIterator};
pub type PatIdMap = FnvHashMap<ast::Name, ast::NodeId>;
......@@ -57,9 +55,9 @@ fn enumerate_and_adjust(self, expected_len: usize, gap_pos: Option<usize>)
// This is used because same-named variables in alternative patterns need to
// use the NodeId of their namesake in the first pattern.
pub fn pat_id_map(dm: &RefCell<DefMap>, pat: &hir::Pat) -> PatIdMap {
pub fn pat_id_map(pat: &hir::Pat) -> PatIdMap {
let mut map = FnvHashMap();
pat_bindings(dm, pat, |_bm, p_id, _s, path1| {
pat_bindings(pat, |_bm, p_id, _s, path1| {
map.insert(path1.node, p_id);
});
map
......@@ -123,31 +121,14 @@ pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
}
}
pub fn pat_is_binding(_: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Binding(..) => true,
_ => false
}
}
pub fn pat_is_binding_or_wild(_: &DefMap, pat: &hir::Pat) -> bool {
match pat.node {
PatKind::Binding(..) | PatKind::Wild => true,
_ => false
}
}
/// Call `it` on every "binding" in a pattern, e.g., on `a` in
/// Call `f` on every "binding" in a pattern, e.g., on `a` in
/// `match foo() { Some(a) => (), None => () }`
pub fn pat_bindings<I>(_: &RefCell<DefMap>, pat: &hir::Pat, mut it: I) where
I: FnMut(hir::BindingMode, ast::NodeId, Span, &Spanned<ast::Name>),
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| {
match p.node {
PatKind::Binding(binding_mode, ref pth, _) => {
it(binding_mode, p.id, p.span, &respan(pth.span, pth.node));
}
_ => {}
if let PatKind::Binding(binding_mode, ref pth, _) = p.node {
f(binding_mode, p.id, p.span, pth);
}
true
});
......@@ -155,10 +136,10 @@ pub fn pat_bindings<I>(_: &RefCell<DefMap>, pat: &hir::Pat, mut it: I) where
/// 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(dm: &DefMap, pat: &hir::Pat) -> bool {
pub fn pat_contains_bindings(pat: &hir::Pat) -> bool {
let mut contains_bindings = false;
pat.walk(|p| {
if pat_is_binding(dm, p) {
if let PatKind::Binding(..) = p.node {
contains_bindings = true;
false // there's at least one binding, can short circuit now.
} else {
......@@ -170,28 +151,25 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &hir::Pat) -> bool {
/// 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(dm: &RefCell<DefMap>, pat: &hir::Pat) -> Option<hir::Mutability> {
pub fn pat_contains_ref_binding(pat: &hir::Pat) -> Option<hir::Mutability> {
let mut result = None;
pat_bindings(dm, pat, |mode, _, _, _| {
match mode {
hir::BindingMode::BindByRef(m) => {
pat_bindings(pat, |mode, _, _, _| {
if let hir::BindingMode::BindByRef(m) = mode {
// Pick Mutable as maximum
match result {
None | Some(hir::MutImmutable) => result = Some(m),
_ => (),
}
}
hir::BindingMode::BindByValue(_) => { }
}
});
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(dm: &RefCell<DefMap>, arm: &hir::Arm) -> Option<hir::Mutability> {
pub fn arm_contains_ref_binding(arm: &hir::Arm) -> Option<hir::Mutability> {
arm.pats.iter()
.filter_map(|pat| pat_contains_ref_binding(dm, pat))
.filter_map(|pat| pat_contains_ref_binding(pat))
.max_by_key(|m| match *m {
hir::MutMutable => 1,
hir::MutImmutable => 0,
......@@ -200,14 +178,15 @@ pub fn arm_contains_ref_binding(dm: &RefCell<DefMap>, arm: &hir::Arm) -> Option<
/// 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(dm: &DefMap, pat: &hir::Pat) -> bool {
pub fn pat_contains_bindings_or_wild(pat: &hir::Pat) -> bool {
let mut contains_bindings = false;
pat.walk(|p| {
if pat_is_binding_or_wild(dm, p) {
match p.node {
PatKind::Binding(..) | PatKind::Wild => {
contains_bindings = true;
false // there's at least one binding/wildcard, can short circuit now.
} else {
true
}
_ => true
}
});
contains_bindings
......
......@@ -612,8 +612,7 @@ fn walk_local(&mut self, local: &hir::Local) {
match local.init {
None => {
let delegate = &mut self.delegate;
pat_util::pat_bindings(&self.mc.infcx.tcx.def_map, &local.pat,
|_, id, span, _| {
pat_util::pat_bindings(&local.pat, |_, id, span, _| {
delegate.decl_without_init(id, span);
})
}
......@@ -932,23 +931,16 @@ fn determine_pat_move_mode(&mut self,
debug!("determine_pat_move_mode cmt_discr={:?} pat={:?}", cmt_discr,
pat);
return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
let def_map = &self.tcx().def_map;
if pat_util::pat_is_binding(&def_map.borrow(), pat) {
match pat.node {
PatKind::Binding(hir::BindByRef(_), _, _) =>
PatKind::Binding(hir::BindByRef(..), _, _) =>
mode.lub(BorrowingMatch),
PatKind::Binding(hir::BindByValue(_), _, _) => {
PatKind::Binding(hir::BindByValue(..), _, _) => {
match copy_or_move(self.mc.infcx, &cmt_pat, PatBindingMove) {
Copy => mode.lub(CopyingMatch),
Move(_) => mode.lub(MovingMatch),
}
}
_ => {
span_bug!(
pat.span,
"binding pattern not an identifier");
Move(..) => mode.lub(MovingMatch),
}
}
_ => {}
}
}));
}
......@@ -968,7 +960,8 @@ fn walk_pat(&mut self,
let def_map = &self.tcx().def_map;
let delegate = &mut self.delegate;
return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
if pat_util::pat_is_binding(&def_map.borrow(), pat) {
match pat.node {
PatKind::Binding(bmode, _, _) => {
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
cmt_pat,
pat,
......@@ -980,35 +973,26 @@ fn walk_pat(&mut self,
// Each match binding is effectively an assignment to the
// binding being produced.
let def = def_map.borrow().get(&pat.id).unwrap().full_def();
match mc.cat_def(pat.id, pat.span, pat_ty, def) {
Ok(binding_cmt) => {
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);
}
Err(_) => { }
}
// It is also a borrow or copy/move of the value being matched.
match pat.node {
PatKind::Binding(hir::BindByRef(m), _, _) => {
match bmode {
hir::BindByRef(m) => {
if let ty::TyRef(&r, _) = pat_ty.sty {
let bk = ty::BorrowKind::from_mutbl(m);
delegate.borrow(pat.id, pat.span, cmt_pat,
r, bk, RefBinding);
}
}
PatKind::Binding(hir::BindByValue(_), _, _) => {
hir::BindByValue(..) => {
let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
debug!("walk_pat binding consuming pat");
delegate.consume_pat(pat, cmt_pat, mode);
}
_ => {
span_bug!(
pat.span,
"binding pattern not an identifier");
}
}
} else {
match pat.node {
PatKind::Vec(_, Some(ref slice_pat), _) => {
// The `slice_pat` here creates a slice into
// the original vector. This is effectively a
......@@ -1043,8 +1027,7 @@ fn walk_pat(&mut self,
slice_cmt, slice_r,
slice_bk, RefBinding);
}
_ => { }
}
_ => {}
}
}));
......
......@@ -380,9 +380,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(&ir.tcx.def_map,
&arg.pat,
|_bm, arg_id, _x, path1| {
pat_util::pat_bindings(&arg.pat, |_bm, arg_id, _x, path1| {
debug!("adding argument {}", arg_id);
let name = path1.node;
fn_maps.add_variable(Arg(arg_id, name));
......@@ -415,7 +413,7 @@ fn visit_fn(ir: &mut IrMaps,
}
fn visit_local(ir: &mut IrMaps, local: &hir::Local) {
pat_util::pat_bindings(&ir.tcx.def_map, &local.pat, |_, p_id, sp, path1| {
pat_util::pat_bindings(&local.pat, |_, p_id, sp, path1| {
debug!("adding local variable {}", p_id);
let name = path1.node;
ir.add_live_node_for_node(p_id, VarDefNode(sp));
......@@ -429,7 +427,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(&ir.tcx.def_map, &pat, |bm, p_id, sp, path1| {
pat_util::pat_bindings(&pat, |bm, p_id, sp, path1| {
debug!("adding local variable {} from match with bm {:?}",
p_id, bm);
let name = path1.node;
......@@ -589,7 +587,7 @@ fn variable(&self, node_id: NodeId, span: Span) -> Variable {
fn pat_bindings<F>(&mut self, pat: &hir::Pat, mut f: F) where
F: FnMut(&mut Liveness<'a, 'tcx>, LiveNode, Variable, Span, NodeId),
{
pat_util::pat_bindings(&self.ir.tcx.def_map, pat, |_bm, p_id, sp, _n| {
pat_util::pat_bindings(pat, |_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);
......@@ -1567,9 +1565,7 @@ fn should_warn(&self, var: Variable) -> Option<String> {
fn warn_about_unused_args(&self, decl: &hir::FnDecl, entry_ln: LiveNode) {
for arg in &decl.inputs {
pat_util::pat_bindings(&self.ir.tcx.def_map,
&arg.pat,
|_bm, p_id, sp, path1| {
pat_util::pat_bindings(&arg.pat, |_bm, p_id, sp, path1| {
let var = self.variable(p_id, sp);
// Ignore unused self.
let name = path1.node;
......
......@@ -173,11 +173,11 @@ pub fn can_type_implement_copy<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
pub fn pat_contains_ref_binding(self, pat: &hir::Pat) -> Option<hir::Mutability> {
pat_util::pat_contains_ref_binding(&self.def_map, pat)
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(&self.def_map, arm)
pat_util::arm_contains_ref_binding(arm)
}
/// Returns the type of element at index `i` in tuple or tuple-like type `t`.
......
......@@ -748,10 +748,9 @@ fn is_useful(cx: &MatchCheckCtxt,
}).find(|result| result != &NotUseful).unwrap_or(NotUseful)
} else {
let matrix = rows.iter().filter_map(|r| {
if pat_is_binding_or_wild(&cx.tcx.def_map.borrow(), raw_pat(r[0])) {
Some(r[1..].to_vec())
} else {
None
match raw_pat(r[0]).node {
PatKind::Binding(..) | PatKind::Wild => Some(r[1..].to_vec()),
_ => None,
}
}).collect();
match is_useful(cx, &matrix, &v[1..], witness) {
......@@ -1089,18 +1088,12 @@ fn is_refutable<A, F>(cx: &MatchCheckCtxt, pat: &Pat, refutable: F) -> Option<A>
fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
has_guard: bool,
pats: &[P<Pat>]) {
let tcx = cx.tcx;
let def_map = &tcx.def_map;
let mut by_ref_span = None;
for pat in pats {
pat_bindings(def_map, &pat, |bm, _, span, _path| {
match bm {
hir::BindByRef(_) => {
pat_bindings(&pat, |bm, _, span, _path| {
if let hir::BindByRef(..) = bm {
by_ref_span = Some(span);
}
hir::BindByValue(_) => {
}
}
})
}
......@@ -1108,7 +1101,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
// 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(&def_map.borrow(), &p)) {
if sub.map_or(false, |p| pat_contains_bindings(&p)) {
span_err!(cx.tcx.sess, p.span, E0007, "cannot bind by-move with sub-bindings");
} else if has_guard {
span_err!(cx.tcx.sess, p.span, E0008, "cannot bind by-move into a pattern guard");
......@@ -1123,7 +1116,7 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
for pat in pats {
pat.walk(|p| {
if let PatKind::Binding(hir::BindByValue(..), _, ref sub) = p.node {
let pat_ty = tcx.node_id_to_type(p.id);
let pat_ty = cx.tcx.node_id_to_type(p.id);
//FIXME: (@jroesch) this code should be floated up as well
cx.tcx.infer_ctxt(None, Some(cx.param_env.clone()),
ProjectionMode::AnyFinal).enter(|infcx| {
......@@ -1199,19 +1192,20 @@ struct AtBindingPatternVisitor<'a, 'b:'a, 'tcx:'b> {
impl<'a, 'b, 'tcx, 'v> Visitor<'v> for AtBindingPatternVisitor<'a, 'b, 'tcx> {
fn visit_pat(&mut self, pat: &Pat) {
if !self.bindings_allowed && pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) {
match pat.node {
PatKind::Binding(_, _, ref subpat) => {
if !self.bindings_allowed {
span_err!(self.cx.tcx.sess, pat.span, E0303,
"pattern bindings are not allowed \
after an `@`");
"pattern bindings are not allowed after an `@`");
}
match pat.node {
PatKind::Binding(_, _, Some(_)) => {
if subpat.is_some() {
let bindings_were_allowed = self.bindings_allowed;
self.bindings_allowed = false;
intravisit::walk_pat(self, pat);
self.bindings_allowed = bindings_were_allowed;
}
}
_ => intravisit::walk_pat(self, pat),
}
}
......
......@@ -43,7 +43,7 @@ fn check_unused_mut_pat(&self, cx: &LateContext, pats: &[P<hir::Pat>]) {
let mut mutables = FnvHashMap();
for p in pats {
pat_util::pat_bindings(&cx.tcx.def_map, p, |mode, id, _, path1| {
pat_util::pat_bindings(p, |mode, id, _, path1| {
let name = path1.node;
if let hir::BindByValue(hir::MutMutable) = mode {
if !name.as_str().starts_with("_") {
......
......@@ -656,7 +656,7 @@ fn convert_arm<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
None
} else {
map = FnvHashMap();
pat_util::pat_bindings(&cx.tcx.def_map, &arm.pats[0], |_, p_id, _, path| {
pat_util::pat_bindings(&arm.pats[0], |_, p_id, _, path| {
map.insert(path.node, p_id);
});
Some(&map)
......
......@@ -540,7 +540,6 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
}
fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
dm: &RefCell<DefMap>,
m: &[Match<'a, 'p, 'blk, 'tcx>],
col: usize,
val: MatchInput)
......@@ -551,12 +550,13 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// Collect all of the matches that can match against anything.
enter_match(bcx, m, col, val, |pats| {
if pat_is_binding_or_wild(&dm.borrow(), &pats[col]) {
match pats[col].node {
PatKind::Binding(..) | PatKind::Wild => {
let mut r = pats[..col].to_vec();
r.extend_from_slice(&pats[col + 1..]);
Some(r)
} else {
None
}
_ => None
}
})
}
......@@ -1145,7 +1145,6 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
has_genuine_default: bool) {
let fcx = bcx.fcx;
let tcx = bcx.tcx();
let dm = &tcx.def_map;
let mut vals_left = vals[0..col].to_vec();
vals_left.extend_from_slice(&vals[col + 1..]);
......@@ -1279,7 +1278,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
C_int(ccx, 0) // Placeholder for when not using a switch
};
let defaults = enter_default(else_cx, dm, m, col, val);
let defaults = enter_default(else_cx, m, col, val);
let exhaustive = chk.is_infallible() && defaults.is_empty();
let len = opts.len();
......@@ -1509,10 +1508,9 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &hir::Pat,
// Note that we use the names because each binding will have many ids
// from the various alternatives.
let ccx = bcx.ccx();
let tcx = bcx.tcx();
let reassigned = is_discr_reassigned(bcx, discr, body);
let mut bindings_map = FnvHashMap();
pat_bindings(&tcx.def_map, &pat, |bm, p_id, span, path1| {
pat_bindings(&pat, |bm, p_id, span, path1| {
let name = path1.node;
let variable_ty = node_id_type(bcx, p_id);
let llvariable_ty = type_of::type_of(ccx, variable_ty);
......@@ -1655,7 +1653,7 @@ fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
// create dummy memory for the variables if we have no
// value to store into them immediately
let tcx = bcx.tcx();
pat_bindings(&tcx.def_map, pat, |_, p_id, _, path1| {
pat_bindings(pat, |_, p_id, _, path1| {
let scope = cleanup::var_scope(tcx, p_id);
bcx = mk_binding_alloca(
bcx, p_id, path1.node, scope, (),
......
......@@ -42,16 +42,13 @@ pub fn create_scope_map(cx: &CrateContext,
fn_ast_id: ast::NodeId)
-> NodeMap<DIScope> {
let mut scope_map = NodeMap();
let def_map = &cx.tcx().def_map;
let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, name: None });
scope_map.insert(fn_ast_id, fn_metadata);
// Push argument identifiers onto the stack so arguments integrate nicely
// with variable shadowing.
for arg in args {
pat_util::pat_bindings(def_map, &arg.pat, |_, node_id, _, path1| {
pat_util::pat_bindings(&arg.pat, |_, node_id, _, path1| {
scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
name: Some(path1.node.unhygienize()) });
scope_map.insert(node_id, fn_metadata);
......
......@@ -1889,11 +1889,8 @@ pub fn create_local_var_metadata(bcx: Block, local: &hir::Local) {
return;
}
let cx = bcx.ccx();
let def_map = &cx.tcx().def_map;
let locals = bcx.fcx.lllocals.borrow();
pat_util::pat_bindings(def_map, &local.pat, |_, node_id, span, var_name| {
pat_util::pat_bindings(&local.pat, |_, node_id, span, var_name| {
let datum = match locals.get(&node_id) {
Some(datum) => datum,
None => {
......@@ -2062,7 +2059,6 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
return;
}
let def_map = &bcx.tcx().def_map;
let scope_metadata = bcx
.fcx
.debug_context
......@@ -2070,7 +2066,7 @@ pub fn create_argument_metadata(bcx: Block, arg: &hir::Arg) {
.fn_metadata;
let locals = bcx.fcx.lllocals.borrow();
pat_util::pat_bindings(def_map, &arg.pat, |_, node_id, span, var_name| {
pat_util::pat_bindings(&arg.pat, |_, node_id, span, var_name| {
let datum = match locals.get(&node_id) {
Some(v) => v,
None => {
......
......@@ -10,7 +10,7 @@
use hir::def::{self, Def};
use rustc::infer::{self, InferOk, TypeOrigin};
use hir::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
use hir::pat_util::{PatIdMap, pat_id_map};
use hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
use rustc::ty::subst::Substs;
use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
......@@ -436,24 +436,20 @@ fn check_assoc_item_is_const(&self, def: Def, span: Span) -> bool {
}
pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool {
let tcx = self.tcx;
if pat_is_binding(&tcx.def_map.borrow(), inner) {
let expected = self.shallow_resolve(expected);
expected.builtin_deref(true, ty::NoPreference).map_or(true, |mt| match mt.ty.sty {
ty::TyTrait(_) => {
if let PatKind::Binding(..) = inner.node {
if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) {
if let ty::TyTrait(..) = mt.ty.sty {
// This is "x = SomeTrait" being reduced from
// "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
span_err!(tcx.sess, span, E0033,
span_err!(self.tcx.sess, span, E0033,
"type `{}` cannot be dereferenced",
self.ty_to_string(expected));
false
return false
}
_ => true
})
} else {
true
}
}
true
}
}
impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
......@@ -491,7 +487,7 @@ pub fn check_match(&self,
for arm in arms {
let pcx = PatCtxt {
fcx: self,
map: pat_id_map(&tcx.def_map, &arm.pats[0]),
map: pat_id_map(&arm.pats[0]),
};
for p in &arm.pats {
pcx.check_pat(&p, discrim_ty);
......
......@@ -630,8 +630,6 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
body: &'gcx hir::Block)
-> FnCtxt<'a, 'gcx, 'tcx>
{
let tcx = inherited.tcx;
let arg_tys = &fn_sig.inputs;
let ret_ty = fn_sig.output;
......@@ -667,19 +665,15 @@ 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(
&tcx.def_map,
&input.pat,
|_bm, pat_id, sp, _path| {
pat_util::pat_bindings(&input.pat, |_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));
fcx.require_type_is_sized(var_ty, sp, traits::VariableType(pat_id));
});
// Check the pattern.
let pcx = PatCtxt {
fcx: &fcx,
map: pat_id_map(&tcx.def_map, &input.pat),
map: pat_id_map(&input.pat),
};
pcx.check_pat(&input.pat, *arg_ty);
}
......@@ -3932,8 +3926,6 @@ pub fn check_decl_initializer(&self,
}
pub fn check_decl_local(&self, local: &'gcx hir::Local) {
let tcx = self.tcx;
let t = self.local_ty(local.span, local.id);
self.write_ty(local.id, t);
......@@ -3947,7 +3939,7 @@ pub fn check_decl_local(&self, local: &'gcx hir::Local) {
let pcx = PatCtxt {
fcx: self,
map: pat_id_map(&tcx.def_map, &local.pat),
map: pat_id_map(&local.pat),
};
pcx.check_pat(&local.pat, t);
let pat_ty = self.node_ty(local.pat.id);
......
......@@ -452,7 +452,7 @@ fn resolve_regions_and_report_errors(&self) {
fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
let tcx = self.tcx;
debug!("regionck::visit_pat(pat={:?})", pat);
pat_util::pat_bindings(&tcx.def_map, pat, |_, id, span, _| {
pat_util::pat_bindings(pat, |_, 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:
......
......@@ -15,7 +15,6 @@
use check::FnCtxt;
use hir::def_id::DefId;
use hir::pat_util;
use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
use rustc::ty::adjustment;
use rustc::ty::fold::{TypeFolder,TypeFoldable};
......@@ -29,7 +28,7 @@
use syntax::codemap::{DUMMY_SP, Span};
use rustc::hir::print::pat_to_string;
use rustc::hir::intravisit::{self, Visitor};
use rustc::hir;
use rustc::hir::{self, PatKind};
///////////////////////////////////////////////////////////////////////////
// Entry point functions
......@@ -54,9 +53,8 @@ pub fn resolve_type_vars_in_fn(&self, decl: &hir::FnDecl, blk: &hir::Block) {
wbcx.visit_pat(&arg.pat);
// Privacy needs the type for the whole pattern, not just each binding
if !pat_util::pat_is_binding(&self.tcx.def_map.borrow(), &arg.pat) {
wbcx.visit_node_id(ResolvingPattern(arg.pat.span),
arg.pat.id);
if let PatKind::Binding(..) = arg.pat.node {} else {
wbcx.visit_node_id(ResolvingPattern(arg.pat.span), arg.pat.id);
}
}
wbcx.visit_upvar_borrow_map();
......
......@@ -616,14 +616,10 @@ pub enum PatKind {
/// Represents a wildcard pattern (`_`)
Wild,
/// A `PatKind::Ident` may either be a new bound variable,
/// or a unit struct/variant pattern, or a const pattern (in the last two cases
/// the third field must be `None`).
///
/// In the unit or const pattern case, the parser can't determine
/// which it is. The resolver determines this, and
/// records this pattern's `NodeId` in an auxiliary
/// set (of "PatIdents that refer to unit patterns or constants").
/// A `PatKind::Ident` may either be a new bound variable (`ref mut binding @ OPT_SUBPATTERN`),
/// or a unit struct/variant pattern, or a const pattern (in the last two cases the third
/// field must be `None`). Disambiguation cannot be done with parser alone, so it happens
/// during name resolution.
Ident(BindingMode, SpannedIdent, Option<P<Pat>>),
/// A struct or struct variant pattern, e.g. `Variant {x, y, ..}`.
......@@ -639,10 +635,8 @@ pub enum PatKind {
/// Such pattern can be resolved to a unit struct/variant or a constant.
Path(Path),
/// An associated const named using the qualified path `<T>::CONST` or
/// `<T as Trait>::CONST`. Associated consts from inherent impls can be
/// referred to as simply `T::CONST`, in which case they will end up as
/// PatKind::Path, and the resolver will have to sort that out.
/// A path pattern written in qualified form, i.e. `<T as Trait>::CONST` or `<T>::CONST`.
/// Such patterns can only refer to associated constants at the moment.
QPath(QSelf, Path),
/// A tuple pattern `(a, b)`.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册