Auto merge of #33929 - petrochenkov:pathir, r=eddyb
Separate bindings from other patterns in HIR Now when name resolution is done on AST, we can avoid dumping everything that looks like an identifier into `PatKind::Ident` in HIR. `hir::PatKind::Ident` is removed, fresh bindings are now called `hir::PatKind::Binding`, everything else goes to `hir::PatKind::Path`. I intend to do something with `PatKind::Path`/`PatKind::QPath` as well using resolution results, but it requires some audit and maybe some deeper refactoring of relevant resolution/type checking code to do it properly. I'm submitting this part of the patch earlier to notify interested parties that I'm working on this. cc @jseyfried r? @eddyb
This commit is contained in:
commit
bf9c60c9a6
@ -99,7 +99,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
|
||||
fn pat(&mut self, pat: &hir::Pat, pred: CFGIndex) -> CFGIndex {
|
||||
match pat.node {
|
||||
PatKind::Ident(_, _, None) |
|
||||
PatKind::Binding(_, _, None) |
|
||||
PatKind::Path(..) |
|
||||
PatKind::QPath(..) |
|
||||
PatKind::Lit(..) |
|
||||
@ -110,7 +110,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
|
||||
PatKind::Box(ref subpat) |
|
||||
PatKind::Ref(ref subpat, _) |
|
||||
PatKind::Ident(_, _, Some(ref subpat)) => {
|
||||
PatKind::Binding(_, _, Some(ref subpat)) => {
|
||||
let subpat_exit = self.pat(&subpat, pred);
|
||||
self.add_ast_node(pat.id, &[subpat_exit])
|
||||
}
|
||||
@ -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
|
||||
|
@ -914,8 +914,8 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
|
||||
id: folder.new_id(id),
|
||||
node: match node {
|
||||
PatKind::Wild => PatKind::Wild,
|
||||
PatKind::Ident(binding_mode, pth1, sub) => {
|
||||
PatKind::Ident(binding_mode,
|
||||
PatKind::Binding(binding_mode, pth1, sub) => {
|
||||
PatKind::Binding(binding_mode,
|
||||
Spanned {
|
||||
span: folder.new_span(pth1.span),
|
||||
node: folder.fold_name(pth1.node),
|
||||
|
@ -478,7 +478,7 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
|
||||
PatKind::Ref(ref subpattern, _) => {
|
||||
visitor.visit_pat(subpattern)
|
||||
}
|
||||
PatKind::Ident(_, ref pth1, ref optional_subpattern) => {
|
||||
PatKind::Binding(_, ref pth1, ref optional_subpattern) => {
|
||||
visitor.visit_name(pth1.span, pth1.node);
|
||||
walk_list!(visitor, visit_pat, optional_subpattern);
|
||||
}
|
||||
|
@ -866,14 +866,16 @@ impl<'a> LoweringContext<'a> {
|
||||
PatKind::Wild => hir::PatKind::Wild,
|
||||
PatKind::Ident(ref binding_mode, pth1, ref sub) => {
|
||||
self.with_parent_def(p.id, |this| {
|
||||
let name = match this.resolver.get_resolution(p.id).map(|d| d.full_def()) {
|
||||
// Only pattern bindings are renamed
|
||||
None | Some(Def::Local(..)) => this.lower_ident(pth1.node),
|
||||
_ => pth1.node.name,
|
||||
};
|
||||
hir::PatKind::Ident(this.lower_binding_mode(binding_mode),
|
||||
respan(pth1.span, name),
|
||||
sub.as_ref().map(|x| this.lower_pat(x)))
|
||||
match this.resolver.get_resolution(p.id).map(|d| d.full_def()) {
|
||||
// `None` can occur in body-less function signatures
|
||||
None | Some(Def::Local(..)) => {
|
||||
hir::PatKind::Binding(this.lower_binding_mode(binding_mode),
|
||||
respan(pth1.span,
|
||||
this.lower_ident(pth1.node)),
|
||||
sub.as_ref().map(|x| this.lower_pat(x)))
|
||||
}
|
||||
_ => hir::PatKind::Path(hir::Path::from_name(pth1.span, pth1.node.name))
|
||||
}
|
||||
})
|
||||
}
|
||||
PatKind::Lit(ref e) => hir::PatKind::Lit(self.lower_expr(e)),
|
||||
@ -1868,7 +1870,7 @@ 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::Ident(bm,
|
||||
let pat_ident = hir::PatKind::Binding(bm,
|
||||
Spanned {
|
||||
span: span,
|
||||
node: name,
|
||||
|
@ -165,7 +165,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, pat: &'ast Pat) {
|
||||
let node = if let PatKind::Ident(..) = pat.node {
|
||||
let node = if let PatKind::Binding(..) = pat.node {
|
||||
NodeLocal(pat)
|
||||
} else {
|
||||
NodePat(pat)
|
||||
|
@ -396,7 +396,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::Ident(_, name, _) = pat.node {
|
||||
if let hir::PatKind::Binding(_, name, _) = pat.node {
|
||||
let def = self.create_def(pat.id, DefPathData::Binding(name.node));
|
||||
self.parent_def = Some(def);
|
||||
}
|
||||
|
@ -561,7 +561,7 @@ impl<'ast> Map<'ast> {
|
||||
NodeVariant(v) => v.node.name,
|
||||
NodeLifetime(lt) => lt.name,
|
||||
NodeTyParam(tp) => tp.name,
|
||||
NodeLocal(&Pat { node: PatKind::Ident(_,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))
|
||||
}
|
||||
|
@ -466,7 +466,7 @@ impl Pat {
|
||||
}
|
||||
|
||||
match self.node {
|
||||
PatKind::Ident(_, _, Some(ref p)) => p.walk_(it),
|
||||
PatKind::Binding(_, _, Some(ref p)) => p.walk_(it),
|
||||
PatKind::Struct(_, ref fields, _) => {
|
||||
fields.iter().all(|field| field.node.pat.walk_(it))
|
||||
}
|
||||
@ -484,7 +484,7 @@ impl Pat {
|
||||
PatKind::Wild |
|
||||
PatKind::Lit(_) |
|
||||
PatKind::Range(_, _) |
|
||||
PatKind::Ident(_, _, _) |
|
||||
PatKind::Binding(..) |
|
||||
PatKind::Path(..) |
|
||||
PatKind::QPath(_, _) => {
|
||||
true
|
||||
@ -524,15 +524,8 @@ 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").
|
||||
Ident(BindingMode, Spanned<Name>, Option<P<Pat>>),
|
||||
/// 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, ..}`.
|
||||
/// The `bool` is `true` in the presence of a `..`.
|
||||
@ -1144,7 +1137,7 @@ pub type ExplicitSelf = Spanned<SelfKind>;
|
||||
|
||||
impl Arg {
|
||||
pub fn to_self(&self) -> Option<ExplicitSelf> {
|
||||
if let PatKind::Ident(BindByValue(mutbl), name, _) = self.pat.node {
|
||||
if let PatKind::Binding(BindByValue(mutbl), name, _) = self.pat.node {
|
||||
if name.node.unhygienize() == keywords::SelfValue.name() {
|
||||
return match self.ty.node {
|
||||
TyInfer => Some(respan(self.pat.span, SelfKind::Value(mutbl))),
|
||||
@ -1160,7 +1153,7 @@ impl Arg {
|
||||
}
|
||||
|
||||
pub fn is_self(&self) -> bool {
|
||||
if let PatKind::Ident(_, name, _) = self.pat.node {
|
||||
if let PatKind::Binding(_, name, _) = self.pat.node {
|
||||
name.node.unhygienize() == keywords::SelfValue.name()
|
||||
} else {
|
||||
false
|
||||
|
@ -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
|
||||
@ -70,7 +68,6 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
PatKind::Lit(_) | PatKind::Range(_, _) | PatKind::QPath(..) => true,
|
||||
PatKind::TupleStruct(..) |
|
||||
PatKind::Path(..) |
|
||||
PatKind::Ident(_, _, None) |
|
||||
PatKind::Struct(..) => {
|
||||
match dm.get(&pat.id).map(|d| d.full_def()) {
|
||||
Some(Def::Variant(..)) => true,
|
||||
@ -86,7 +83,6 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
match pat.node {
|
||||
PatKind::TupleStruct(..) |
|
||||
PatKind::Path(..) |
|
||||
PatKind::Ident(_, _, None) |
|
||||
PatKind::Struct(..) => {
|
||||
match dm.get(&pat.id).map(|d| d.full_def()) {
|
||||
Some(Def::Variant(..)) | Some(Def::Struct(..)) | Some(Def::TyAlias(..)) => true,
|
||||
@ -99,7 +95,7 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
|
||||
pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
match pat.node {
|
||||
PatKind::Ident(_, _, None) | PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
match dm.get(&pat.id).map(|d| d.full_def()) {
|
||||
Some(Def::Const(..)) | Some(Def::AssociatedConst(..)) => true,
|
||||
_ => false
|
||||
@ -113,7 +109,7 @@ pub fn pat_is_const(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
// returned instead of a panic.
|
||||
pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
match pat.node {
|
||||
PatKind::Ident(_, _, None) | PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
match dm.get(&pat.id)
|
||||
.and_then(|d| if d.depth == 0 { Some(d.base_def) }
|
||||
else { None } ) {
|
||||
@ -125,35 +121,14 @@ pub fn pat_is_resolved_const(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pat_is_binding(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
match pat.node {
|
||||
PatKind::Ident(..) => {
|
||||
!pat_is_variant_or_struct(dm, pat) &&
|
||||
!pat_is_const(dm, pat)
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pat_is_binding_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
match pat.node {
|
||||
PatKind::Ident(..) => pat_is_binding(dm, pat),
|
||||
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>(dm: &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::Ident(binding_mode, ref pth, _) if pat_is_binding(&dm.borrow(), p) => {
|
||||
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
|
||||
});
|
||||
@ -161,10 +136,10 @@ pub fn pat_bindings<I>(dm: &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 {
|
||||
@ -176,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
|
||||
@ -195,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,
|
||||
@ -206,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
|
||||
@ -221,7 +194,7 @@ pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &hir::Pat) -> bool {
|
||||
|
||||
pub fn simple_name<'a>(pat: &'a hir::Pat) -> Option<ast::Name> {
|
||||
match pat.node {
|
||||
PatKind::Ident(hir::BindByValue(_), ref path1, None) => {
|
||||
PatKind::Binding(hir::BindByValue(..), ref path1, None) => {
|
||||
Some(path1.node)
|
||||
}
|
||||
_ => {
|
||||
@ -241,7 +214,6 @@ pub fn necessary_variants(dm: &DefMap, pat: &hir::Pat) -> Vec<DefId> {
|
||||
match p.node {
|
||||
PatKind::TupleStruct(..) |
|
||||
PatKind::Path(..) |
|
||||
PatKind::Ident(_, _, None) |
|
||||
PatKind::Struct(..) => {
|
||||
match dm.get(&p.id) {
|
||||
Some(&PathResolution { base_def: Def::Variant(_, id), .. }) => {
|
||||
|
@ -1716,7 +1716,7 @@ impl<'a> State<'a> {
|
||||
// is that it doesn't matter
|
||||
match pat.node {
|
||||
PatKind::Wild => word(&mut self.s, "_")?,
|
||||
PatKind::Ident(binding_mode, ref path1, ref sub) => {
|
||||
PatKind::Binding(binding_mode, ref path1, ref sub) => {
|
||||
match binding_mode {
|
||||
hir::BindByRef(mutbl) => {
|
||||
self.word_nbsp("ref")?;
|
||||
@ -2170,7 +2170,7 @@ impl<'a> State<'a> {
|
||||
if let Some(eself) = input.to_self() {
|
||||
self.print_explicit_self(&eself)?;
|
||||
} else {
|
||||
let invalid = if let PatKind::Ident(_, name, _) = input.pat.node {
|
||||
let invalid = if let PatKind::Binding(_, name, _) = input.pat.node {
|
||||
name.node == keywords::Invalid.name()
|
||||
} else {
|
||||
false
|
||||
|
@ -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::Ident(hir::BindByRef(_), _, _) =>
|
||||
mode.lub(BorrowingMatch),
|
||||
PatKind::Ident(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::Ident(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::Ident(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);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}));
|
||||
|
||||
@ -1057,14 +1040,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
let tcx = infcx.tcx;
|
||||
|
||||
match pat.node {
|
||||
PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::QPath(..) |
|
||||
PatKind::Ident(_, _, None) | PatKind::Struct(..) => {
|
||||
PatKind::Struct(..) | PatKind::TupleStruct(..) |
|
||||
PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
match def_map.get(&pat.id).map(|d| d.full_def()) {
|
||||
None => {
|
||||
// no definition found: pat is not a
|
||||
// struct or enum pattern.
|
||||
}
|
||||
|
||||
Some(Def::Variant(enum_did, variant_did)) => {
|
||||
let downcast_cmt =
|
||||
if tcx.lookup_adt_def(enum_did).is_univariant() {
|
||||
@ -1094,14 +1072,13 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
|
||||
Some(Def::Const(..)) |
|
||||
Some(Def::AssociatedConst(..)) |
|
||||
Some(Def::Local(..)) => {
|
||||
Some(Def::AssociatedConst(..)) => {
|
||||
// This is a leaf (i.e. identifier binding
|
||||
// or constant value to match); thus no
|
||||
// `matched_pat` call.
|
||||
}
|
||||
|
||||
Some(def) => {
|
||||
def => {
|
||||
// An enum type should never be in a pattern.
|
||||
// Remaining cases are e.g. Def::Fn, to
|
||||
// which identifiers within patterns
|
||||
@ -1121,16 +1098,10 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Ident(_, _, Some(_)) => {
|
||||
// Do nothing; this is a binding (not an enum
|
||||
// variant or struct), and the cat_pattern call
|
||||
// will visit the substructure recursively.
|
||||
}
|
||||
|
||||
PatKind::Wild | PatKind::Tuple(..) | PatKind::Box(..) |
|
||||
PatKind::Ref(..) | PatKind::Lit(..) | PatKind::Range(..) |
|
||||
PatKind::Vec(..) => {
|
||||
// Similarly, each of these cases does not
|
||||
PatKind::Vec(..) | PatKind::Binding(..) => {
|
||||
// Each of these cases does not
|
||||
// correspond to an enum variant or struct, so we
|
||||
// do not do any `matched_pat` calls for these
|
||||
// cases either.
|
||||
|
@ -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;
|
||||
|
@ -306,7 +306,7 @@ impl MutabilityCategory {
|
||||
fn from_local(tcx: TyCtxt, id: ast::NodeId) -> MutabilityCategory {
|
||||
let ret = match tcx.map.get(id) {
|
||||
ast_map::NodeLocal(p) => match p.node {
|
||||
PatKind::Ident(bind_mode, _, _) => {
|
||||
PatKind::Binding(bind_mode, _, _) => {
|
||||
if bind_mode == hir::BindByValue(hir::MutMutable) {
|
||||
McDeclared
|
||||
} else {
|
||||
@ -398,7 +398,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
// *being borrowed* is. But ideally we would put in a more
|
||||
// fundamental fix to this conflated use of the node id.
|
||||
let ret_ty = match pat.node {
|
||||
PatKind::Ident(hir::BindByRef(_), _, _) => {
|
||||
PatKind::Binding(hir::BindByRef(_), _, _) => {
|
||||
// a bind-by-ref means that the base_ty will be the type of the ident itself,
|
||||
// but what we want here is the type of the underlying value being borrowed.
|
||||
// So peel off one-level, turning the &T into T.
|
||||
@ -1276,11 +1276,11 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Path(..) | PatKind::QPath(..) | PatKind::Ident(_, _, None) => {
|
||||
PatKind::Path(..) | PatKind::QPath(..) | PatKind::Binding(_, _, None) => {
|
||||
// Lone constant, or unit variant or identifier: ignore
|
||||
}
|
||||
|
||||
PatKind::Ident(_, _, Some(ref subpat)) => {
|
||||
PatKind::Binding(_, _, Some(ref subpat)) => {
|
||||
self.cat_pattern_(cmt, &subpat, op)?;
|
||||
}
|
||||
|
||||
|
@ -752,13 +752,9 @@ fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &hir::Arm) {
|
||||
fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &hir::Pat) {
|
||||
visitor.new_node_extent(pat.id);
|
||||
|
||||
// If this is a binding (or maybe a binding, I'm too lazy to check
|
||||
// the def map) then record the lifetime of that binding.
|
||||
match pat.node {
|
||||
PatKind::Ident(..) => {
|
||||
record_var_lifetime(visitor, pat.id, pat.span);
|
||||
}
|
||||
_ => { }
|
||||
// If this is a binding then record the lifetime of that binding.
|
||||
if let PatKind::Binding(..) = pat.node {
|
||||
record_var_lifetime(visitor, pat.id, pat.span);
|
||||
}
|
||||
|
||||
intravisit::walk_pat(visitor, pat);
|
||||
@ -958,7 +954,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) {
|
||||
/// | box P&
|
||||
fn is_binding_pat(pat: &hir::Pat) -> bool {
|
||||
match pat.node {
|
||||
PatKind::Ident(hir::BindByRef(_), _, _) => true,
|
||||
PatKind::Binding(hir::BindByRef(_), _, _) => true,
|
||||
|
||||
PatKind::Struct(_, ref field_pats, _) => {
|
||||
field_pats.iter().any(|fp| is_binding_pat(&fp.node.pat))
|
||||
|
@ -2216,7 +2216,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||
match self.map.find(id) {
|
||||
Some(ast_map::NodeLocal(pat)) => {
|
||||
match pat.node {
|
||||
PatKind::Ident(_, ref path1, _) => path1.node.as_str(),
|
||||
PatKind::Binding(_, ref path1, _) => path1.node.as_str(),
|
||||
_ => {
|
||||
bug!("Variable id {} maps to {:?}, not local", id, pat);
|
||||
},
|
||||
|
@ -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`.
|
||||
|
@ -98,7 +98,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
||||
move_pat: &hir::Pat,
|
||||
cmt: mc::cmt<'tcx>) {
|
||||
let pat_span_path_opt = match move_pat.node {
|
||||
PatKind::Ident(_, ref path1, _) => {
|
||||
PatKind::Binding(_, ref path1, _) => {
|
||||
Some(MoveSpanAndPath{span: move_pat.span,
|
||||
name: path1.node})
|
||||
},
|
||||
|
@ -239,31 +239,28 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &hir::Expr) {
|
||||
|
||||
fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat) {
|
||||
pat.walk(|p| {
|
||||
match p.node {
|
||||
PatKind::Ident(hir::BindByValue(hir::MutImmutable), name, None) => {
|
||||
let pat_ty = cx.tcx.pat_ty(p);
|
||||
if let ty::TyEnum(edef, _) = pat_ty.sty {
|
||||
let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
|
||||
if let Some(Def::Local(..)) = def {
|
||||
if edef.variants.iter().any(|variant|
|
||||
variant.name == name.node.unhygienize()
|
||||
&& variant.kind() == VariantKind::Unit
|
||||
) {
|
||||
let ty_path = cx.tcx.item_path_str(edef.did);
|
||||
let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
|
||||
"pattern binding `{}` is named the same as one \
|
||||
of the variants of the type `{}`",
|
||||
name.node, ty_path);
|
||||
help!(err,
|
||||
"if you meant to match on a variant, \
|
||||
consider making the path in the pattern qualified: `{}::{}`",
|
||||
ty_path, name.node);
|
||||
err.emit();
|
||||
}
|
||||
if let PatKind::Binding(hir::BindByValue(hir::MutImmutable), name, None) = p.node {
|
||||
let pat_ty = cx.tcx.pat_ty(p);
|
||||
if let ty::TyEnum(edef, _) = pat_ty.sty {
|
||||
let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
|
||||
if let Some(Def::Local(..)) = def {
|
||||
if edef.variants.iter().any(|variant|
|
||||
variant.name == name.node.unhygienize()
|
||||
&& variant.kind() == VariantKind::Unit
|
||||
) {
|
||||
let ty_path = cx.tcx.item_path_str(edef.did);
|
||||
let mut err = struct_span_warn!(cx.tcx.sess, p.span, E0170,
|
||||
"pattern binding `{}` is named the same as one \
|
||||
of the variants of the type `{}`",
|
||||
name.node, ty_path);
|
||||
help!(err,
|
||||
"if you meant to match on a variant, \
|
||||
consider making the path in the pattern qualified: `{}::{}`",
|
||||
ty_path, name.node);
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => ()
|
||||
}
|
||||
true
|
||||
});
|
||||
@ -371,8 +368,8 @@ fn check_arms(cx: &MatchCheckCtxt,
|
||||
/// Checks for common cases of "catchall" patterns that may not be intended as such.
|
||||
fn pat_is_catchall(dm: &DefMap, p: &Pat) -> bool {
|
||||
match p.node {
|
||||
PatKind::Ident(_, _, None) => pat_is_binding(dm, p),
|
||||
PatKind::Ident(_, _, Some(ref s)) => pat_is_catchall(dm, &s),
|
||||
PatKind::Binding(_, _, None) => true,
|
||||
PatKind::Binding(_, _, Some(ref s)) => pat_is_catchall(dm, &s),
|
||||
PatKind::Ref(ref s, _) => pat_is_catchall(dm, &s),
|
||||
PatKind::Tuple(ref v, _) => v.iter().all(|p| pat_is_catchall(dm, &p)),
|
||||
_ => false
|
||||
@ -381,7 +378,7 @@ fn pat_is_catchall(dm: &DefMap, p: &Pat) -> bool {
|
||||
|
||||
fn raw_pat(p: &Pat) -> &Pat {
|
||||
match p.node {
|
||||
PatKind::Ident(_, _, Some(ref s)) => raw_pat(&s),
|
||||
PatKind::Binding(_, _, Some(ref s)) => raw_pat(&s),
|
||||
_ => p
|
||||
}
|
||||
}
|
||||
@ -487,11 +484,10 @@ impl<'map> IdVisitingOperation for RenamingRecorder<'map> {
|
||||
impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
|
||||
fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
|
||||
return match pat.node {
|
||||
PatKind::Ident(..) | PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
PatKind::Path(..) | PatKind::QPath(..) => {
|
||||
let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
|
||||
match def {
|
||||
Some(Def::AssociatedConst(did)) |
|
||||
Some(Def::Const(did)) => {
|
||||
Some(Def::AssociatedConst(did)) | Some(Def::Const(did)) => {
|
||||
let substs = Some(self.tcx.node_id_item_substs(pat.id).substs);
|
||||
if let Some((const_expr, _)) = lookup_const_by_id(self.tcx, did, substs) {
|
||||
match const_expr_to_pat(self.tcx, const_expr, pat.id, pat.span) {
|
||||
@ -717,7 +713,7 @@ fn is_useful(cx: &MatchCheckCtxt,
|
||||
let left_ty = cx.tcx.pat_ty(&real_pat);
|
||||
|
||||
match real_pat.node {
|
||||
PatKind::Ident(hir::BindByRef(..), _, _) => {
|
||||
PatKind::Binding(hir::BindByRef(..), _, _) => {
|
||||
left_ty.builtin_deref(false, NoPreference).unwrap().ty
|
||||
}
|
||||
_ => left_ty,
|
||||
@ -752,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) {
|
||||
@ -804,38 +799,37 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
|
||||
left_ty: Ty, max_slice_length: usize) -> Vec<Constructor> {
|
||||
let pat = raw_pat(p);
|
||||
match pat.node {
|
||||
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::Ident(..) =>
|
||||
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) =>
|
||||
match cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def() {
|
||||
Def::Const(..) | Def::AssociatedConst(..) =>
|
||||
span_bug!(pat.span, "const pattern should've \
|
||||
been rewritten"),
|
||||
Def::Struct(..) | Def::TyAlias(..) => vec![Single],
|
||||
Def::Variant(_, id) => vec![Variant(id)],
|
||||
Def::Local(..) => vec![],
|
||||
def => span_bug!(pat.span, "pat_constructors: unexpected \
|
||||
definition {:?}", def),
|
||||
},
|
||||
PatKind::QPath(..) =>
|
||||
span_bug!(pat.span, "const pattern should've been rewritten"),
|
||||
PatKind::Lit(ref expr) =>
|
||||
vec!(ConstantValue(eval_const_expr(cx.tcx, &expr))),
|
||||
vec![ConstantValue(eval_const_expr(cx.tcx, &expr))],
|
||||
PatKind::Range(ref lo, ref hi) =>
|
||||
vec!(ConstantRange(eval_const_expr(cx.tcx, &lo), eval_const_expr(cx.tcx, &hi))),
|
||||
vec![ConstantRange(eval_const_expr(cx.tcx, &lo), eval_const_expr(cx.tcx, &hi))],
|
||||
PatKind::Vec(ref before, ref slice, ref after) =>
|
||||
match left_ty.sty {
|
||||
ty::TyArray(_, _) => vec!(Single),
|
||||
ty::TyArray(_, _) => vec![Single],
|
||||
_ => if slice.is_some() {
|
||||
(before.len() + after.len()..max_slice_length+1)
|
||||
.map(|length| Slice(length))
|
||||
.collect()
|
||||
} else {
|
||||
vec!(Slice(before.len() + after.len()))
|
||||
vec![Slice(before.len() + after.len())]
|
||||
}
|
||||
},
|
||||
PatKind::Box(..) | PatKind::Tuple(..) | PatKind::Ref(..) =>
|
||||
vec!(Single),
|
||||
PatKind::Wild =>
|
||||
vec!(),
|
||||
vec![Single],
|
||||
PatKind::Binding(..) | PatKind::Wild =>
|
||||
vec![],
|
||||
}
|
||||
}
|
||||
|
||||
@ -897,10 +891,10 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
|
||||
id: pat_id, ref node, span: pat_span
|
||||
} = raw_pat(r[col]);
|
||||
let head: Option<Vec<&Pat>> = match *node {
|
||||
PatKind::Wild =>
|
||||
PatKind::Binding(..) | PatKind::Wild =>
|
||||
Some(vec![DUMMY_WILD_PAT; arity]),
|
||||
|
||||
PatKind::Path(..) | PatKind::Ident(..) => {
|
||||
PatKind::Path(..) => {
|
||||
let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
|
||||
match def {
|
||||
Def::Const(..) | Def::AssociatedConst(..) =>
|
||||
@ -908,7 +902,6 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
|
||||
been rewritten"),
|
||||
Def::Variant(_, id) if *constructor != Variant(id) => None,
|
||||
Def::Variant(..) | Def::Struct(..) => Some(Vec::new()),
|
||||
Def::Local(..) => Some(vec![DUMMY_WILD_PAT; arity]),
|
||||
_ => span_bug!(pat_span, "specialize: unexpected \
|
||||
definition {:?}", def),
|
||||
}
|
||||
@ -1095,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);
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -1114,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");
|
||||
@ -1128,28 +1115,15 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
|
||||
|
||||
for pat in pats {
|
||||
pat.walk(|p| {
|
||||
if pat_is_binding(&def_map.borrow(), &p) {
|
||||
match p.node {
|
||||
PatKind::Ident(hir::BindByValue(_), _, ref sub) => {
|
||||
let pat_ty = 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| {
|
||||
if infcx.type_moves_by_default(pat_ty, pat.span) {
|
||||
check_move(p, sub.as_ref().map(|p| &**p));
|
||||
}
|
||||
});
|
||||
if let PatKind::Binding(hir::BindByValue(..), _, ref sub) = p.node {
|
||||
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| {
|
||||
if infcx.type_moves_by_default(pat_ty, pat.span) {
|
||||
check_move(p, sub.as_ref().map(|p| &**p));
|
||||
}
|
||||
PatKind::Ident(hir::BindByRef(_), _, _) => {
|
||||
}
|
||||
_ => {
|
||||
span_bug!(
|
||||
p.span,
|
||||
"binding pattern {} is not an identifier: {:?}",
|
||||
p.id,
|
||||
p.node);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
true
|
||||
});
|
||||
@ -1218,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::Ident(_, _, 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),
|
||||
}
|
||||
|
@ -274,9 +274,9 @@ impl LateLintPass for NonSnakeCase {
|
||||
}
|
||||
|
||||
fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
|
||||
if let &PatKind::Ident(_, ref path1, _) = &p.node {
|
||||
let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
|
||||
if let Some(Def::Local(..)) = def {
|
||||
if let &PatKind::Binding(_, ref path1, _) = &p.node {
|
||||
// Exclude parameter names from foreign functions (they have no `Def`)
|
||||
if cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def()).is_some() {
|
||||
self.check_snake_case(cx, "variable", &path1.node.as_str(), Some(p.span));
|
||||
}
|
||||
}
|
||||
@ -360,12 +360,14 @@ impl LateLintPass for NonUpperCaseGlobals {
|
||||
|
||||
fn check_pat(&mut self, cx: &LateContext, p: &hir::Pat) {
|
||||
// Lint for constants that look like binding identifiers (#7526)
|
||||
match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
|
||||
(&PatKind::Ident(_, ref path1, _), Some(Def::Const(..))) => {
|
||||
NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
|
||||
path1.node, p.span);
|
||||
if let PatKind::Path(ref path) = p.node {
|
||||
if !path.global && path.segments.len() == 1 && path.segments[0].parameters.is_empty() {
|
||||
if let Some(Def::Const(..)) = cx.tcx.def_map.borrow().get(&p.id)
|
||||
.map(|d| d.full_def()) {
|
||||
NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
|
||||
path.segments[0].name, path.span);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +171,7 @@ impl LateLintPass for NonShorthandFieldPatterns {
|
||||
}
|
||||
});
|
||||
for fieldpat in field_pats {
|
||||
if let PatKind::Ident(_, ident, None) = fieldpat.node.pat.node {
|
||||
if let PatKind::Binding(_, ident, None) = fieldpat.node.pat.node {
|
||||
if ident.node.unhygienize() == fieldpat.node.name {
|
||||
cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
|
||||
&format!("the `{}:` in this pattern is redundant and can \
|
||||
|
@ -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("_") {
|
||||
|
@ -744,7 +744,7 @@ fn encode_method_argument_names(rbml_w: &mut Encoder,
|
||||
rbml_w.start_tag(tag_method_argument_names);
|
||||
for arg in &decl.inputs {
|
||||
let tag = tag_method_argument_name;
|
||||
if let PatKind::Ident(_, ref path1, _) = arg.pat.node {
|
||||
if let PatKind::Binding(_, ref path1, _) = arg.pat.node {
|
||||
let name = path1.node.as_str();
|
||||
rbml_w.wr_tagged_bytes(tag, name.as_bytes());
|
||||
} else {
|
||||
|
@ -14,7 +14,6 @@ use rustc::ty::{self, Ty};
|
||||
use rustc::mir::repr::*;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc::hir;
|
||||
use rustc::hir::pat_util::pat_is_binding;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use syntax::abi::Abi;
|
||||
use syntax::ast;
|
||||
@ -221,7 +220,7 @@ pub fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>,
|
||||
by_ref: by_ref
|
||||
};
|
||||
if let Some(hir::map::NodeLocal(pat)) = tcx.map.find(fv.def.var_id()) {
|
||||
if let hir::PatKind::Ident(_, ref ident, _) = pat.node {
|
||||
if let hir::PatKind::Binding(_, ref ident, _) = pat.node {
|
||||
decl.debug_name = ident.node;
|
||||
}
|
||||
}
|
||||
@ -333,10 +332,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
|
||||
let mut name = keywords::Invalid.name();
|
||||
if let Some(pat) = pattern {
|
||||
if let hir::PatKind::Ident(_, ref ident, _) = pat.node {
|
||||
if pat_is_binding(&self.hir.tcx().def_map.borrow(), pat) {
|
||||
name = ident.node;
|
||||
}
|
||||
if let hir::PatKind::Binding(_, ref ident, _) = pat.node {
|
||||
name = ident.node;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -13,7 +13,7 @@ use hair::cx::Cx;
|
||||
use rustc_data_structures::fnv::FnvHashMap;
|
||||
use rustc_const_eval as const_eval;
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const, pat_is_binding};
|
||||
use rustc::hir::pat_util::{EnumerateAndAdjustIterator, pat_is_resolved_const};
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::mir::repr::*;
|
||||
use rustc::hir::{self, PatKind};
|
||||
@ -81,7 +81,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
PatternKind::Range { lo: lo, hi: hi }
|
||||
},
|
||||
|
||||
PatKind::Path(..) | PatKind::Ident(..) | PatKind::QPath(..)
|
||||
PatKind::Path(..) | PatKind::QPath(..)
|
||||
if pat_is_resolved_const(&self.cx.tcx.def_map.borrow(), pat) =>
|
||||
{
|
||||
let def = self.cx.tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
|
||||
@ -167,9 +167,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Ident(bm, ref ident, ref sub)
|
||||
if pat_is_binding(&self.cx.tcx.def_map.borrow(), pat) =>
|
||||
{
|
||||
PatKind::Binding(bm, ref ident, ref sub) => {
|
||||
let id = match self.binding_map {
|
||||
None => pat.id,
|
||||
Some(ref map) => map[&ident.node],
|
||||
@ -210,7 +208,7 @@ impl<'patcx, 'cx, 'gcx, 'tcx> PatCx<'patcx, 'cx, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
PatKind::Ident(..) | PatKind::Path(..) => {
|
||||
PatKind::Path(..) => {
|
||||
self.variant_or_leaf(pat, vec![])
|
||||
}
|
||||
|
||||
|
@ -424,12 +424,11 @@ impl<'a, 'p, 'blk, 'tcx> fmt::Debug for Match<'a, 'p, 'blk, 'tcx> {
|
||||
|
||||
fn has_nested_bindings(m: &[Match], col: usize) -> bool {
|
||||
for br in m {
|
||||
match br.pats[col].node {
|
||||
PatKind::Ident(_, _, Some(_)) => return true,
|
||||
_ => ()
|
||||
if let PatKind::Binding(_, _, Some(..)) = br.pats[col].node {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false;
|
||||
false
|
||||
}
|
||||
|
||||
// As noted in `fn match_datum`, we should eventually pass around a
|
||||
@ -481,7 +480,7 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let mut pat = br.pats[col];
|
||||
loop {
|
||||
pat = match pat.node {
|
||||
PatKind::Ident(_, ref path, Some(ref inner)) => {
|
||||
PatKind::Binding(_, ref path, Some(ref inner)) => {
|
||||
bound_ptrs.push((path.node, val.val));
|
||||
&inner
|
||||
},
|
||||
@ -501,7 +500,6 @@ fn expand_nested_bindings<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
}
|
||||
|
||||
fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
||||
dm: &RefCell<DefMap>,
|
||||
m: &[Match<'a, 'p, 'blk, 'tcx>],
|
||||
col: usize,
|
||||
val: MatchInput,
|
||||
@ -518,13 +516,11 @@ fn enter_match<'a, 'b, 'p, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
|
||||
let this = br.pats[col];
|
||||
let mut bound_ptrs = br.bound_ptrs.clone();
|
||||
match this.node {
|
||||
PatKind::Ident(_, ref path, None) => {
|
||||
if pat_is_binding(&dm.borrow(), &this) {
|
||||
bound_ptrs.push((path.node, val.val));
|
||||
}
|
||||
PatKind::Binding(_, ref path, None) => {
|
||||
bound_ptrs.push((path.node, val.val));
|
||||
}
|
||||
PatKind::Vec(ref before, Some(ref slice), ref after) => {
|
||||
if let PatKind::Ident(_, ref path, None) = slice.node {
|
||||
if let PatKind::Binding(_, ref path, None) = slice.node {
|
||||
let subslice_val = bind_subslice_pat(
|
||||
bcx, this.id, val,
|
||||
before.len(), after.len());
|
||||
@ -544,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)
|
||||
@ -554,13 +549,14 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let _indenter = indenter();
|
||||
|
||||
// Collect all of the matches that can match against anything.
|
||||
enter_match(bcx, dm, 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
|
||||
enter_match(bcx, m, col, val, |pats| {
|
||||
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
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -596,7 +592,6 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
fn enter_opt<'a, 'p, 'blk, 'tcx>(
|
||||
bcx: Block<'blk, 'tcx>,
|
||||
_: ast::NodeId,
|
||||
dm: &RefCell<DefMap>,
|
||||
m: &[Match<'a, 'p, 'blk, 'tcx>],
|
||||
opt: &Opt,
|
||||
col: usize,
|
||||
@ -628,7 +623,7 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>(
|
||||
tcx: bcx.tcx(),
|
||||
param_env: param_env,
|
||||
};
|
||||
enter_match(bcx, dm, m, col, val, |pats|
|
||||
enter_match(bcx, m, col, val, |pats|
|
||||
check_match::specialize(&mcx, &pats[..], &ctor, col, variant_size)
|
||||
)
|
||||
}
|
||||
@ -659,9 +654,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
PatKind::Lit(ref l) => {
|
||||
ConstantValue(ConstantExpr(&l), debug_loc)
|
||||
}
|
||||
PatKind::Ident(..) | PatKind::Path(..) |
|
||||
PatKind::TupleStruct(..) | PatKind::Struct(..) => {
|
||||
// This is either an enum variant or a variable binding.
|
||||
PatKind::Path(..) | PatKind::TupleStruct(..) | PatKind::Struct(..) => {
|
||||
let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
|
||||
match opt_def {
|
||||
Some(Def::Variant(enum_id, var_id)) => {
|
||||
@ -793,8 +786,7 @@ fn any_irrefutable_adt_pat(tcx: TyCtxt, m: &[Match], col: usize) -> bool {
|
||||
let pat = br.pats[col];
|
||||
match pat.node {
|
||||
PatKind::Tuple(..) => true,
|
||||
PatKind::Struct(..) | PatKind::TupleStruct(..) |
|
||||
PatKind::Path(..) | PatKind::Ident(_, _, None) => {
|
||||
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) => {
|
||||
match tcx.def_map.borrow().get(&pat.id).unwrap().full_def() {
|
||||
Def::Struct(..) | Def::TyAlias(..) => true,
|
||||
_ => false,
|
||||
@ -839,7 +831,7 @@ impl FailureHandler {
|
||||
fn pick_column_to_specialize(def_map: &RefCell<DefMap>, m: &[Match]) -> Option<usize> {
|
||||
fn pat_score(def_map: &RefCell<DefMap>, pat: &hir::Pat) -> usize {
|
||||
match pat.node {
|
||||
PatKind::Ident(_, _, Some(ref inner)) => pat_score(def_map, &inner),
|
||||
PatKind::Binding(_, _, Some(ref inner)) => pat_score(def_map, &inner),
|
||||
_ if pat_is_refutable(&def_map.borrow(), pat) => 1,
|
||||
_ => 0
|
||||
}
|
||||
@ -1153,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..]);
|
||||
@ -1226,7 +1217,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
};
|
||||
match adt_vals {
|
||||
Some(field_vals) => {
|
||||
let pats = enter_match(bcx, dm, m, col, val, |pats|
|
||||
let pats = enter_match(bcx, m, col, val, |pats|
|
||||
check_match::specialize(&mcx, pats,
|
||||
&Constructor::Single, col,
|
||||
field_vals.len())
|
||||
@ -1287,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();
|
||||
|
||||
@ -1391,7 +1382,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
|
||||
}
|
||||
ConstantValue(..) | ConstantRange(..) => ()
|
||||
}
|
||||
let opt_ms = enter_opt(opt_cx, pat_id, dm, m, opt, col, size, val);
|
||||
let opt_ms = enter_opt(opt_cx, pat_id, m, opt, col, size, val);
|
||||
let mut opt_vals: Vec<_> = unpacked.into_iter()
|
||||
.map(|v|MatchInput::from_val(v))
|
||||
.collect();
|
||||
@ -1517,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);
|
||||
@ -1663,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, (),
|
||||
@ -1796,38 +1786,35 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let tcx = bcx.tcx();
|
||||
let ccx = bcx.ccx();
|
||||
match pat.node {
|
||||
PatKind::Ident(pat_binding_mode, ref path1, ref inner) => {
|
||||
if pat_is_binding(&tcx.def_map.borrow(), &pat) {
|
||||
// Allocate the stack slot where the value of this
|
||||
// binding will live and place it into the appropriate
|
||||
// map.
|
||||
bcx = mk_binding_alloca(
|
||||
bcx, pat.id, path1.node, cleanup_scope, (),
|
||||
"_match::bind_irrefutable_pat",
|
||||
|(), bcx, Datum { val: llval, ty, kind: _ }| {
|
||||
match pat_binding_mode {
|
||||
hir::BindByValue(_) => {
|
||||
// By value binding: move the value that `val`
|
||||
// points at into the binding's stack slot.
|
||||
let d = val.to_datum(ty);
|
||||
d.store_to(bcx, llval)
|
||||
}
|
||||
PatKind::Binding(pat_binding_mode, ref path1, ref inner) => {
|
||||
// Allocate the stack slot where the value of this
|
||||
// binding will live and place it into the appropriate
|
||||
// map.
|
||||
bcx = mk_binding_alloca(bcx, pat.id, path1.node, cleanup_scope, (),
|
||||
"_match::bind_irrefutable_pat",
|
||||
|(), bcx, Datum { val: llval, ty, kind: _ }| {
|
||||
match pat_binding_mode {
|
||||
hir::BindByValue(_) => {
|
||||
// By value binding: move the value that `val`
|
||||
// points at into the binding's stack slot.
|
||||
let d = val.to_datum(ty);
|
||||
d.store_to(bcx, llval)
|
||||
}
|
||||
|
||||
hir::BindByRef(_) => {
|
||||
// By ref binding: the value of the variable
|
||||
// is the pointer `val` itself or fat pointer referenced by `val`
|
||||
if type_is_fat_ptr(bcx.tcx(), ty) {
|
||||
expr::copy_fat_ptr(bcx, val.val, llval);
|
||||
}
|
||||
else {
|
||||
Store(bcx, val.val, llval);
|
||||
}
|
||||
|
||||
bcx
|
||||
}
|
||||
hir::BindByRef(_) => {
|
||||
// By ref binding: the value of the variable
|
||||
// is the pointer `val` itself or fat pointer referenced by `val`
|
||||
if type_is_fat_ptr(bcx.tcx(), ty) {
|
||||
expr::copy_fat_ptr(bcx, val.val, llval);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
Store(bcx, val.val, llval);
|
||||
}
|
||||
|
||||
bcx
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if let Some(ref inner_pat) = *inner {
|
||||
bcx = bind_irrefutable_pat(bcx, &inner_pat, val, cleanup_scope);
|
||||
@ -1941,7 +1928,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let val = if type_is_fat_ptr(tcx, pat_ty) {
|
||||
// We need to check for this, as the pattern could be binding
|
||||
// a fat pointer by-value.
|
||||
if let PatKind::Ident(hir::BindByRef(_),_,_) = inner.node {
|
||||
if let PatKind::Binding(hir::BindByRef(..),_,_) = inner.node {
|
||||
val.val
|
||||
} else {
|
||||
Load(bcx, val.val)
|
||||
@ -1960,7 +1947,7 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
let val = if type_is_fat_ptr(tcx, pat_ty) {
|
||||
// We need to check for this, as the pattern could be binding
|
||||
// a fat pointer by-value.
|
||||
if let PatKind::Ident(hir::BindByRef(_),_,_) = inner.node {
|
||||
if let PatKind::Binding(hir::BindByRef(..),_,_) = inner.node {
|
||||
val.val
|
||||
} else {
|
||||
Load(bcx, val.val)
|
||||
@ -2001,8 +1988,8 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
cleanup_scope)
|
||||
});
|
||||
}
|
||||
PatKind::Path(..) | PatKind::QPath(..) | PatKind::Wild | PatKind::Lit(_) |
|
||||
PatKind::Range(_, _) => ()
|
||||
PatKind::Path(..) | PatKind::QPath(..) | PatKind::Wild |
|
||||
PatKind::Lit(..) | PatKind::Range(..) => ()
|
||||
}
|
||||
return bcx;
|
||||
}
|
||||
|
@ -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);
|
||||
@ -235,76 +232,66 @@ fn walk_pattern(cx: &CrateContext,
|
||||
pat: &hir::Pat,
|
||||
scope_stack: &mut Vec<ScopeStackEntry> ,
|
||||
scope_map: &mut NodeMap<DIScope>) {
|
||||
|
||||
let def_map = &cx.tcx().def_map;
|
||||
|
||||
// Unfortunately, we cannot just use pat_util::pat_bindings() or
|
||||
// ast_util::walk_pat() here because we have to visit *all* nodes in
|
||||
// order to put them into the scope map. The above functions don't do that.
|
||||
match pat.node {
|
||||
PatKind::Ident(_, ref path1, ref sub_pat_opt) => {
|
||||
PatKind::Binding(_, ref path1, ref sub_pat_opt) => {
|
||||
// LLVM does not properly generate 'DW_AT_start_scope' fields
|
||||
// for variable DIEs. For this reason we have to introduce
|
||||
// an artificial scope at bindings whenever a variable with
|
||||
// the same name is declared in *any* parent scope.
|
||||
//
|
||||
// Otherwise the following error occurs:
|
||||
//
|
||||
// let x = 10;
|
||||
//
|
||||
// do_something(); // 'gdb print x' correctly prints 10
|
||||
//
|
||||
// {
|
||||
// do_something(); // 'gdb print x' prints 0, because it
|
||||
// // already reads the uninitialized 'x'
|
||||
// // from the next line...
|
||||
// let x = 100;
|
||||
// do_something(); // 'gdb print x' correctly prints 100
|
||||
// }
|
||||
|
||||
// Check if this is a binding. If so we need to put it on the
|
||||
// scope stack and maybe introduce an artificial scope
|
||||
if pat_util::pat_is_binding(&def_map.borrow(), &pat) {
|
||||
// Is there already a binding with that name?
|
||||
// N.B.: this comparison must be UNhygienic... because
|
||||
// gdb knows nothing about the context, so any two
|
||||
// variables with the same name will cause the problem.
|
||||
let name = path1.node.unhygienize();
|
||||
let need_new_scope = scope_stack
|
||||
.iter()
|
||||
.any(|entry| entry.name == Some(name));
|
||||
|
||||
let name = path1.node.unhygienize();
|
||||
if need_new_scope {
|
||||
// Create a new lexical scope and push it onto the stack
|
||||
let loc = span_start(cx, pat.span);
|
||||
let file_metadata = file_metadata(cx, &loc.file.name);
|
||||
let parent_scope = scope_stack.last().unwrap().scope_metadata;
|
||||
|
||||
// LLVM does not properly generate 'DW_AT_start_scope' fields
|
||||
// for variable DIEs. For this reason we have to introduce
|
||||
// an artificial scope at bindings whenever a variable with
|
||||
// the same name is declared in *any* parent scope.
|
||||
//
|
||||
// Otherwise the following error occurs:
|
||||
//
|
||||
// let x = 10;
|
||||
//
|
||||
// do_something(); // 'gdb print x' correctly prints 10
|
||||
//
|
||||
// {
|
||||
// do_something(); // 'gdb print x' prints 0, because it
|
||||
// // already reads the uninitialized 'x'
|
||||
// // from the next line...
|
||||
// let x = 100;
|
||||
// do_something(); // 'gdb print x' correctly prints 100
|
||||
// }
|
||||
let scope_metadata = unsafe {
|
||||
llvm::LLVMDIBuilderCreateLexicalBlock(
|
||||
DIB(cx),
|
||||
parent_scope,
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
loc.col.to_usize() as c_uint)
|
||||
};
|
||||
|
||||
// Is there already a binding with that name?
|
||||
// N.B.: this comparison must be UNhygienic... because
|
||||
// gdb knows nothing about the context, so any two
|
||||
// variables with the same name will cause the problem.
|
||||
let need_new_scope = scope_stack
|
||||
.iter()
|
||||
.any(|entry| entry.name == Some(name));
|
||||
scope_stack.push(ScopeStackEntry {
|
||||
scope_metadata: scope_metadata,
|
||||
name: Some(name)
|
||||
});
|
||||
|
||||
if need_new_scope {
|
||||
// Create a new lexical scope and push it onto the stack
|
||||
let loc = span_start(cx, pat.span);
|
||||
let file_metadata = file_metadata(cx, &loc.file.name);
|
||||
let parent_scope = scope_stack.last().unwrap().scope_metadata;
|
||||
|
||||
let scope_metadata = unsafe {
|
||||
llvm::LLVMDIBuilderCreateLexicalBlock(
|
||||
DIB(cx),
|
||||
parent_scope,
|
||||
file_metadata,
|
||||
loc.line as c_uint,
|
||||
loc.col.to_usize() as c_uint)
|
||||
};
|
||||
|
||||
scope_stack.push(ScopeStackEntry {
|
||||
scope_metadata: scope_metadata,
|
||||
name: Some(name)
|
||||
});
|
||||
|
||||
} else {
|
||||
// Push a new entry anyway so the name can be found
|
||||
let prev_metadata = scope_stack.last().unwrap().scope_metadata;
|
||||
scope_stack.push(ScopeStackEntry {
|
||||
scope_metadata: prev_metadata,
|
||||
name: Some(name)
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Push a new entry anyway so the name can be found
|
||||
let prev_metadata = scope_stack.last().unwrap().scope_metadata;
|
||||
scope_stack.push(ScopeStackEntry {
|
||||
scope_metadata: prev_metadata,
|
||||
name: Some(name)
|
||||
});
|
||||
}
|
||||
|
||||
scope_map.insert(pat.id, scope_stack.last().unwrap().scope_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 => {
|
||||
@ -1945,7 +1942,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
||||
}
|
||||
Some(hir_map::NodeLocal(pat)) => {
|
||||
match pat.node {
|
||||
PatKind::Ident(_, ref path1, _) => {
|
||||
PatKind::Binding(_, ref path1, _) => {
|
||||
path1.node
|
||||
}
|
||||
_ => {
|
||||
@ -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};
|
||||
@ -149,8 +149,7 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
// subtyping doesn't matter here, as the value is some kind of scalar
|
||||
self.demand_eqtype(pat.span, expected, lhs_ty);
|
||||
}
|
||||
PatKind::Path(..) | PatKind::Ident(..)
|
||||
if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
|
||||
PatKind::Path(..) if pat_is_resolved_const(&tcx.def_map.borrow(), pat) => {
|
||||
if let Some(pat_def) = tcx.def_map.borrow().get(&pat.id) {
|
||||
let const_did = pat_def.def_id();
|
||||
let const_scheme = tcx.lookup_item_type(const_did);
|
||||
@ -170,8 +169,7 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
self.write_error(pat.id);
|
||||
}
|
||||
}
|
||||
PatKind::Ident(bm, ref path, ref sub)
|
||||
if pat_is_binding(&tcx.def_map.borrow(), pat) => {
|
||||
PatKind::Binding(bm, ref path, ref sub) => {
|
||||
let typ = self.local_ty(pat.span, pat.id);
|
||||
match bm {
|
||||
hir::BindByRef(mutbl) => {
|
||||
@ -211,10 +209,6 @@ impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
|
||||
}
|
||||
}
|
||||
}
|
||||
PatKind::Ident(_, ref path, _) => {
|
||||
let path = hir::Path::from_name(path.span, path.node);
|
||||
self.check_pat_enum(pat, &path, &[], None, expected, false);
|
||||
}
|
||||
PatKind::TupleStruct(ref path, ref subpats, ddpos) => {
|
||||
self.check_pat_enum(pat, path, &subpats, ddpos, expected, true);
|
||||
}
|
||||
@ -442,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
|
||||
}
|
||||
}
|
||||
|
||||
@ -497,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);
|
||||
|
@ -573,19 +573,17 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
|
||||
|
||||
// Add pattern bindings.
|
||||
fn visit_pat(&mut self, p: &'gcx hir::Pat) {
|
||||
if let PatKind::Ident(_, ref path1, _) = p.node {
|
||||
if pat_util::pat_is_binding(&self.fcx.tcx.def_map.borrow(), p) {
|
||||
let var_ty = self.assign(p.span, p.id, None);
|
||||
if let PatKind::Binding(_, ref path1, _) = p.node {
|
||||
let var_ty = self.assign(p.span, p.id, None);
|
||||
|
||||
self.fcx.require_type_is_sized(var_ty, p.span,
|
||||
traits::VariableType(p.id));
|
||||
self.fcx.require_type_is_sized(var_ty, p.span,
|
||||
traits::VariableType(p.id));
|
||||
|
||||
debug!("Pattern binding {} is assigned to {} with type {:?}",
|
||||
path1.node,
|
||||
self.fcx.ty_to_string(
|
||||
self.fcx.locals.borrow().get(&p.id).unwrap().clone()),
|
||||
var_ty);
|
||||
}
|
||||
debug!("Pattern binding {} is assigned to {} with type {:?}",
|
||||
path1.node,
|
||||
self.fcx.ty_to_string(
|
||||
self.fcx.locals.borrow().get(&p.id).unwrap().clone()),
|
||||
var_ty);
|
||||
}
|
||||
intravisit::walk_pat(self, p);
|
||||
}
|
||||
@ -633,8 +631,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;
|
||||
|
||||
@ -670,19 +666,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);
|
||||
}
|
||||
@ -3797,8 +3789,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);
|
||||
|
||||
@ -3812,7 +3802,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:
|
||||
@ -1160,7 +1160,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
|
||||
let _ = mc.cat_pattern(discr_cmt, root_pat, |mc, sub_cmt, sub_pat| {
|
||||
match sub_pat.node {
|
||||
// `ref x` pattern
|
||||
PatKind::Ident(hir::BindByRef(mutbl), _, _) => {
|
||||
PatKind::Binding(hir::BindByRef(mutbl), _, _) => {
|
||||
self.link_region_from_node_type(sub_pat.span, sub_pat.id,
|
||||
mutbl, sub_cmt);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -2152,12 +2152,9 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
|
||||
{
|
||||
for i in &decl.inputs {
|
||||
match i.pat.node {
|
||||
PatKind::Ident(_, _, _) => (),
|
||||
PatKind::Wild => (),
|
||||
_ => {
|
||||
span_err!(ccx.tcx.sess, i.pat.span, E0130,
|
||||
"patterns aren't allowed in foreign function declarations");
|
||||
}
|
||||
PatKind::Binding(..) | PatKind::Wild => {}
|
||||
_ => span_err!(ccx.tcx.sess, i.pat.span, E0130,
|
||||
"patterns aren't allowed in foreign function declarations")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2578,7 +2578,7 @@ fn name_from_pat(p: &hir::Pat) -> String {
|
||||
|
||||
match p.node {
|
||||
PatKind::Wild => "_".to_string(),
|
||||
PatKind::Ident(_, ref p, _) => p.node.to_string(),
|
||||
PatKind::Binding(_, ref p, _) => p.node.to_string(),
|
||||
PatKind::TupleStruct(ref p, _, _) | PatKind::Path(ref p) => path_to_string(p),
|
||||
PatKind::QPath(..) => panic!("tried to get argument name from PatKind::QPath, \
|
||||
which is not allowed in function arguments"),
|
||||
|
@ -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, ..}`.
|
||||
|
Loading…
x
Reference in New Issue
Block a user