From b00050f4cf7d602566afd511b66ae6645f92987d Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 1 Jul 2018 17:56:06 +0100 Subject: [PATCH] Add more safeguards to "missing binding mode" errors --- src/librustc/middle/expr_use_visitor.rs | 49 +++++++++++--------- src/librustc_borrowck/borrowck/unused.rs | 18 +++---- src/librustc_mir/build/mod.rs | 13 +++--- src/librustc_mir/hair/pattern/check_match.rs | 32 ++++++------- src/librustc_typeck/check/regionck.rs | 12 +++-- 5 files changed, 65 insertions(+), 59 deletions(-) diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 6ccf09f4dfc..a83aa47fd4f 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -840,6 +840,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { fn walk_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &hir::Pat, match_mode: MatchMode) { debug!("walk_pat(cmt_discr={:?}, pat={:?})", cmt_discr, pat); + let tcx = self.tcx(); let ExprUseVisitor { ref mc, ref mut delegate, param_env } = *self; return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |cmt_pat, pat| { if let PatKind::Binding(_, canonical_id, ..) = pat.node { @@ -849,34 +850,36 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { pat, match_mode, ); - let bm = *mc.tables.pat_binding_modes().get(pat.hir_id) - .expect("missing binding mode"); - debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); + if let Some(&bm) = mc.tables.pat_binding_modes().get(pat.hir_id) { + debug!("walk_pat: pat.hir_id={:?} bm={:?}", pat.hir_id, bm); - // pat_ty: the type of the binding being produced. - let pat_ty = return_if_err!(mc.node_ty(pat.hir_id)); - debug!("walk_pat: pat_ty={:?}", pat_ty); + // pat_ty: the type of the binding being produced. + let pat_ty = return_if_err!(mc.node_ty(pat.hir_id)); + debug!("walk_pat: pat_ty={:?}", pat_ty); - // Each match binding is effectively an assignment to the - // binding being produced. - let def = Def::Local(canonical_id); - if let Ok(ref binding_cmt) = mc.cat_def(pat.hir_id, pat.span, pat_ty, def) { - delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init); - } + // Each match binding is effectively an assignment to the + // binding being produced. + let def = Def::Local(canonical_id); + if let Ok(ref binding_cmt) = mc.cat_def(pat.hir_id, pat.span, pat_ty, def) { + delegate.mutate(pat.id, pat.span, binding_cmt, MutateMode::Init); + } - // It is also a borrow or copy/move of the value being matched. - match bm { - ty::BindByReference(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 bm { + ty::BindByReference(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); + } + } + ty::BindByValue(..) => { + let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); + debug!("walk_pat binding consuming pat"); + delegate.consume_pat(pat, &cmt_pat, mode); } } - ty::BindByValue(..) => { - let mode = copy_or_move(mc, param_env, &cmt_pat, PatBindingMove); - debug!("walk_pat binding consuming pat"); - delegate.consume_pat(pat, &cmt_pat, mode); - } + } else { + tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } } })); diff --git a/src/librustc_borrowck/borrowck/unused.rs b/src/librustc_borrowck/borrowck/unused.rs index 294ae1e63a9..475ff0b7443 100644 --- a/src/librustc_borrowck/borrowck/unused.rs +++ b/src/librustc_borrowck/borrowck/unused.rs @@ -54,16 +54,16 @@ impl<'a, 'tcx> UnusedMutCx<'a, 'tcx> { // Skip anything that looks like `&foo` or `&mut foo`, only look // for by-value bindings - let bm = match self.bccx.tables.pat_binding_modes().get(hir_id) { - Some(&bm) => bm, - None => span_bug!(span, "missing binding mode"), - }; - match bm { - ty::BindByValue(hir::MutMutable) => {} - _ => return, - } + if let Some(&bm) = self.bccx.tables.pat_binding_modes().get(hir_id) { + match bm { + ty::BindByValue(hir::MutMutable) => {} + _ => return, + } - mutables.entry(ident.name).or_insert(Vec::new()).push((hir_id, span)); + mutables.entry(ident.name).or_insert(Vec::new()).push((hir_id, span)); + } else { + tcx.sess.delay_span_bug(span, "missing binding mode"); + } }); } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4db5c8e9278..cdf0079e2ae 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -541,13 +541,14 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, if let hir::PatKind::Binding(_, _, ident, _) = pat.node { decl.debug_name = ident.name; - let bm = *hir.tables.pat_binding_modes() - .get(pat.hir_id) - .expect("missing binding mode"); - if bm == ty::BindByValue(hir::MutMutable) { - decl.mutability = Mutability::Mut; + if let Some(&bm) = hir.tables.pat_binding_modes().get(pat.hir_id) { + if bm == ty::BindByValue(hir::MutMutable) { + decl.mutability = Mutability::Mut; + } else { + decl.mutability = Mutability::Not; + } } else { - decl.mutability = Mutability::Not; + tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } } } diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index a7806131f2c..18ae7c77459 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -516,12 +516,12 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, let mut by_ref_span = None; for pat in pats { pat.each_binding(|_, hir_id, span, _path| { - let bm = *cx.tables - .pat_binding_modes() - .get(hir_id) - .expect("missing binding mode"); - if let ty::BindByReference(..) = bm { - by_ref_span = Some(span); + if let Some(&bm) = cx.tables.pat_binding_modes().get(hir_id) { + if let ty::BindByReference(..) = bm { + by_ref_span = Some(span); + } + } else { + cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } }) } @@ -552,18 +552,18 @@ fn check_legality_of_move_bindings(cx: &MatchVisitor, for pat in pats { pat.walk(|p| { if let PatKind::Binding(_, _, _, ref sub) = p.node { - let bm = *cx.tables - .pat_binding_modes() - .get(p.hir_id) - .expect("missing binding mode"); - match bm { - ty::BindByValue(..) => { - let pat_ty = cx.tables.node_id_to_type(p.hir_id); - if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { - check_move(p, sub.as_ref().map(|p| &**p)); + if let Some(&bm) = cx.tables.pat_binding_modes().get(p.hir_id) { + match bm { + ty::BindByValue(..) => { + let pat_ty = cx.tables.node_id_to_type(p.hir_id); + if pat_ty.moves_by_default(cx.tcx, cx.param_env, pat.span) { + check_move(p, sub.as_ref().map(|p| &**p)); + } } + _ => {} } - _ => {} + } else { + cx.tcx.sess.delay_span_bug(pat.span, "missing binding mode"); } } true diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index e489c4d4a46..68fcde0b165 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1039,11 +1039,13 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { match sub_pat.node { // `ref x` pattern PatKind::Binding(..) => { - let bm = *mc.tables.pat_binding_modes().get(sub_pat.hir_id) - .expect("missing binding mode"); - if let ty::BindByReference(mutbl) = bm { - self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id, - mutbl, &sub_cmt); + if let Some(&bm) = mc.tables.pat_binding_modes().get(sub_pat.hir_id) { + if let ty::BindByReference(mutbl) = bm { + self.link_region_from_node_type(sub_pat.span, sub_pat.hir_id, + mutbl, &sub_cmt); + } + } else { + self.tcx.sess.delay_span_bug(sub_pat.span, "missing binding mode"); } } _ => {}