Refactor away some functions from hir::pat_util
This commit is contained in:
parent
216f5fba04
commit
cf46820694
@ -456,8 +456,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(
|
||||
&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 @@ impl<T: ExactSizeIterator> EnumerateAndAdjustIterator for T {
|
||||
|
||||
// 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,18 +151,15 @@ 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) => {
|
||||
// Pick Mutable as maximum
|
||||
match result {
|
||||
None | Some(hir::MutImmutable) => result = Some(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
|
||||
@ -189,9 +167,9 @@ pub fn pat_contains_ref_binding(dm: &RefCell<DefMap>, pat: &hir::Pat) -> Option<
|
||||
|
||||
/// 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) {
|
||||
contains_bindings = true;
|
||||
false // there's at least one binding/wildcard, can short circuit now.
|
||||
} else {
|
||||
true
|
||||
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
|
||||
|
@ -612,8 +612,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
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 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
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(_), _, _) =>
|
||||
mode.lub(BorrowingMatch),
|
||||
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");
|
||||
match pat.node {
|
||||
PatKind::Binding(hir::BindByRef(..), _, _) =>
|
||||
mode.lub(BorrowingMatch),
|
||||
PatKind::Binding(hir::BindByValue(..), _, _) => {
|
||||
match copy_or_move(self.mc.infcx, &cmt_pat, PatBindingMove) {
|
||||
Copy => mode.lub(CopyingMatch),
|
||||
Move(..) => mode.lub(MovingMatch),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}));
|
||||
}
|
||||
@ -968,83 +960,74 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
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) {
|
||||
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
|
||||
cmt_pat,
|
||||
pat,
|
||||
match_mode);
|
||||
match pat.node {
|
||||
PatKind::Binding(bmode, _, _) => {
|
||||
debug!("binding cmt_pat={:?} pat={:?} match_mode={:?}",
|
||||
cmt_pat,
|
||||
pat,
|
||||
match_mode);
|
||||
|
||||
// pat_ty: the type of the binding being produced.
|
||||
let pat_ty = return_if_err!(infcx.node_ty(pat.id));
|
||||
// pat_ty: the type of the binding being produced.
|
||||
let pat_ty = return_if_err!(infcx.node_ty(pat.id));
|
||||
|
||||
// Each match binding is effectively an assignment to the
|
||||
// binding being produced.
|
||||
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) => {
|
||||
// Each match binding is effectively an assignment to the
|
||||
// binding being produced.
|
||||
let def = def_map.borrow().get(&pat.id).unwrap().full_def();
|
||||
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), _, _) => {
|
||||
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);
|
||||
// It is also a borrow or copy/move of the value being matched.
|
||||
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);
|
||||
}
|
||||
}
|
||||
hir::BindByValue(..) => {
|
||||
let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
|
||||
debug!("walk_pat binding consuming pat");
|
||||
delegate.consume_pat(pat, cmt_pat, mode);
|
||||
}
|
||||
}
|
||||
PatKind::Binding(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
|
||||
// borrow of the elements of the vector being
|
||||
// matched.
|
||||
PatKind::Vec(_, Some(ref slice_pat), _) => {
|
||||
// The `slice_pat` here creates a slice into
|
||||
// the original vector. This is effectively a
|
||||
// borrow of the elements of the vector being
|
||||
// matched.
|
||||
|
||||
let (slice_cmt, slice_mutbl, slice_r) =
|
||||
return_if_err!(mc.cat_slice_pattern(cmt_pat, &slice_pat));
|
||||
let (slice_cmt, slice_mutbl, slice_r) =
|
||||
return_if_err!(mc.cat_slice_pattern(cmt_pat, &slice_pat));
|
||||
|
||||
// Note: We declare here that the borrow
|
||||
// occurs upon entering the `[...]`
|
||||
// pattern. This implies that something like
|
||||
// `[a; b]` where `a` is a move is illegal,
|
||||
// because the borrow is already in effect.
|
||||
// In fact such a move would be safe-ish, but
|
||||
// it effectively *requires* that we use the
|
||||
// nulling out semantics to indicate when a
|
||||
// value has been moved, which we are trying
|
||||
// to move away from. Otherwise, how can we
|
||||
// indicate that the first element in the
|
||||
// vector has been moved? Eventually, we
|
||||
// could perhaps modify this rule to permit
|
||||
// `[..a, b]` where `b` is a move, because in
|
||||
// that case we can adjust the length of the
|
||||
// original vec accordingly, but we'd have to
|
||||
// make trans do the right thing, and it would
|
||||
// only work for `Box<[T]>`s. It seems simpler
|
||||
// to just require that people call
|
||||
// `vec.pop()` or `vec.unshift()`.
|
||||
let slice_bk = ty::BorrowKind::from_mutbl(slice_mutbl);
|
||||
delegate.borrow(pat.id, pat.span,
|
||||
slice_cmt, slice_r,
|
||||
slice_bk, RefBinding);
|
||||
}
|
||||
_ => { }
|
||||
// Note: We declare here that the borrow
|
||||
// occurs upon entering the `[...]`
|
||||
// pattern. This implies that something like
|
||||
// `[a; b]` where `a` is a move is illegal,
|
||||
// because the borrow is already in effect.
|
||||
// In fact such a move would be safe-ish, but
|
||||
// it effectively *requires* that we use the
|
||||
// nulling out semantics to indicate when a
|
||||
// value has been moved, which we are trying
|
||||
// to move away from. Otherwise, how can we
|
||||
// indicate that the first element in the
|
||||
// vector has been moved? Eventually, we
|
||||
// could perhaps modify this rule to permit
|
||||
// `[..a, b]` where `b` is a move, because in
|
||||
// that case we can adjust the length of the
|
||||
// original vec accordingly, but we'd have to
|
||||
// make trans do the right thing, and it would
|
||||
// only work for `Box<[T]>`s. It seems simpler
|
||||
// to just require that people call
|
||||
// `vec.pop()` or `vec.unshift()`.
|
||||
let slice_bk = ty::BorrowKind::from_mutbl(slice_mutbl);
|
||||
delegate.borrow(pat.id, pat.span,
|
||||
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 @@ 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(&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 @@ 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(&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 @@ 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(&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,17 +1088,11 @@ 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(_) => {
|
||||
by_ref_span = Some(span);
|
||||
}
|
||||
hir::BindByValue(_) => {
|
||||
}
|
||||
pat_bindings(&pat, |bm, _, span, _path| {
|
||||
if let hir::BindByRef(..) = bm {
|
||||
by_ref_span = Some(span);
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -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,18 +1192,19 @@ 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) {
|
||||
span_err!(self.cx.tcx.sess, pat.span, E0303,
|
||||
"pattern bindings are not allowed \
|
||||
after an `@`");
|
||||
}
|
||||
|
||||
match pat.node {
|
||||
PatKind::Binding(_, _, Some(_)) => {
|
||||
let bindings_were_allowed = self.bindings_allowed;
|
||||
self.bindings_allowed = false;
|
||||
intravisit::walk_pat(self, pat);
|
||||
self.bindings_allowed = bindings_were_allowed;
|
||||
PatKind::Binding(_, _, ref subpat) => {
|
||||
if !self.bindings_allowed {
|
||||
span_err!(self.cx.tcx.sess, pat.span, E0303,
|
||||
"pattern bindings are not allowed after an `@`");
|
||||
}
|
||||
|
||||
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 @@ impl UnusedMut {
|
||||
|
||||
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]) {
|
||||
let mut r = pats[..col].to_vec();
|
||||
r.extend_from_slice(&pats[col + 1..]);
|
||||
Some(r)
|
||||
} else {
|
||||
None
|
||||
match pats[col].node {
|
||||
PatKind::Binding(..) | PatKind::Wild => {
|
||||
let mut r = pats[..col].to_vec();
|
||||
r.extend_from_slice(&pats[col + 1..]);
|
||||
Some(r)
|
||||
}
|
||||
_ => 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 @@ pub fn store_local<'blk, 'tcx>(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,23 +436,19 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@ -491,7 +487,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
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| {
|
||||
let var_ty = visit.assign(sp, pat_id, None);
|
||||
fcx.require_type_is_sized(var_ty, sp,
|
||||
traits::VariableType(pat_id));
|
||||
});
|
||||
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));
|
||||
});
|
||||
|
||||
// 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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
|
||||
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 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
|
||||
let tcx = self.tcx;
|
||||
debug!("regionck::visit_pat(pat={:?})", pat);
|
||||
pat_util::pat_bindings(&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 self::ResolveReason::*;
|
||||
|
||||
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::ast;
|
||||
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 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
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)`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user