diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-07-28 00:54:46 +0200 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-07-30 06:43:06 +0200 |
| commit | f64b66a407627ca151c56b3c30ecefaa984de095 (patch) | |
| tree | 21437d74bb799d63658c7838e788647377da51f2 | |
| parent | 04b88a9eba8abbac87eddcb2998beea09589c2c9 (diff) | |
| download | rust-f64b66a407627ca151c56b3c30ecefaa984de095.tar.gz rust-f64b66a407627ca151c56b3c30ecefaa984de095.zip | |
Do not downgrade NLL errors for bind_by_move_pattern_guards when AST says it is OK.
| -rw-r--r-- | src/librustc/query/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc/ty/query/mod.rs | 2 | ||||
| -rw-r--r-- | src/librustc_ast_borrowck/borrowck/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc_mir/hair/pattern/check_match.rs | 63 |
4 files changed, 47 insertions, 27 deletions
diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 67fc3520745..5ab1b90642a 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -461,7 +461,7 @@ rustc_queries! { } TypeChecking { - query check_match(key: DefId) -> () { + query check_match(key: DefId) -> SignalledError { cache_on_disk_if { key.is_local() } } diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index f4b99ca3688..fb2ad2aa54d 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -4,7 +4,7 @@ use crate::hir::def::{DefKind, Export}; use crate::hir::{self, TraitCandidate, ItemLocalId, CodegenFnAttrs}; use crate::infer::canonical::{self, Canonical}; use crate::lint; -use crate::middle::borrowck::BorrowCheckResult; +use crate::middle::borrowck::{BorrowCheckResult, SignalledError}; use crate::middle::cstore::{ExternCrate, LinkagePreference, NativeLibrary, ForeignModule}; use crate::middle::cstore::{NativeLibraryKind, DepKind, CrateSource}; use crate::middle::privacy::AccessLevels; diff --git a/src/librustc_ast_borrowck/borrowck/mod.rs b/src/librustc_ast_borrowck/borrowck/mod.rs index f8ad8baa597..3bbd7ae5c35 100644 --- a/src/librustc_ast_borrowck/borrowck/mod.rs +++ b/src/librustc_ast_borrowck/borrowck/mod.rs @@ -66,6 +66,13 @@ fn borrowck(tcx: TyCtxt<'_>, owner_def_id: DefId) -> &BorrowCheckResult { debug!("borrowck(body_owner_def_id={:?})", owner_def_id); + let signalled_error = tcx.check_match(owner_def_id); + if let SignalledError::SawSomeError = signalled_error { + return tcx.arena.alloc(BorrowCheckResult { + signalled_any_error: SignalledError::SawSomeError, + }) + } + let owner_id = tcx.hir().as_local_hir_id(owner_def_id).unwrap(); match tcx.hir().get(owner_id) { diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs index 32a8c5cd3bb..47f31fa0a82 100644 --- a/src/librustc_mir/hair/pattern/check_match.rs +++ b/src/librustc_mir/hair/pattern/check_match.rs @@ -4,6 +4,7 @@ use super::_match::WitnessPreference::*; use super::{Pattern, PatternContext, PatternError, PatternKind}; +use rustc::middle::borrowck::SignalledError; use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor}; use rustc::middle::expr_use_visitor::{LoanCause, MutateMode}; use rustc::middle::expr_use_visitor as euv; @@ -26,21 +27,24 @@ use std::slice; use syntax_pos::{Span, DUMMY_SP, MultiSpan}; -pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: DefId) { +crate fn check_match(tcx: TyCtxt<'_>, def_id: DefId) -> SignalledError { let body_id = if let Some(id) = tcx.hir().as_local_hir_id(def_id) { tcx.hir().body_owned_by(id) } else { - return; + return SignalledError::NoErrorsSeen; }; - MatchVisitor { + let mut visitor = MatchVisitor { tcx, body_owner: def_id, tables: tcx.body_tables(body_id), region_scope_tree: &tcx.region_scope_tree(def_id), param_env: tcx.param_env(def_id), identity_substs: InternalSubsts::identity_for_item(tcx, def_id), - }.visit_body(tcx.hir().body(body_id)); + signalled_error: SignalledError::NoErrorsSeen, + }; + visitor.visit_body(tcx.hir().body(body_id)); + visitor.signalled_error } fn create_e0004(sess: &Session, sp: Span, error_message: String) -> DiagnosticBuilder<'_> { @@ -54,6 +58,7 @@ struct MatchVisitor<'a, 'tcx> { param_env: ty::ParamEnv<'tcx>, identity_substs: SubstsRef<'tcx>, region_scope_tree: &'a region::ScopeTree, + signalled_error: SignalledError, } impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { @@ -64,11 +69,8 @@ impl<'a, 'tcx> Visitor<'tcx> for MatchVisitor<'a, 'tcx> { fn visit_expr(&mut self, ex: &'tcx hir::Expr) { intravisit::walk_expr(self, ex); - match ex.node { - hir::ExprKind::Match(ref scrut, ref arms, source) => { - self.check_match(scrut, arms, source); - } - _ => {} + if let hir::ExprKind::Match(ref scrut, ref arms, source) = ex.node { + self.check_match(scrut, arms, source); } } @@ -130,7 +132,7 @@ impl<'a, 'tcx> PatternContext<'a, 'tcx> { } impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { - fn check_patterns(&self, has_guard: bool, pats: &[P<Pat>]) { + fn check_patterns(&mut self, has_guard: bool, pats: &[P<Pat>]) { check_legality_of_move_bindings(self, has_guard, pats); for pat in pats { check_legality_of_bindings_in_at_patterns(self, pat); @@ -138,11 +140,11 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { } fn check_match( - &self, + &mut self, scrut: &hir::Expr, arms: &'tcx [hir::Arm], - source: hir::MatchSource) - { + source: hir::MatchSource + ) { for arm in arms { // First, check legality of move bindings. self.check_patterns(arm.guard.is_some(), &arm.pats); @@ -150,7 +152,9 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { // Second, if there is a guard on each arm, make sure it isn't // assigning or borrowing anything mutably. if let Some(ref guard) = arm.guard { - if !self.tcx.features().bind_by_move_pattern_guards { + if self.tcx.features().bind_by_move_pattern_guards { + self.signalled_error = SignalledError::SawSomeError; + } else { check_for_mutation_in_guard(self, &guard); } } @@ -548,7 +552,7 @@ fn maybe_point_at_variant( // Legality of move bindings checking fn check_legality_of_move_bindings( - cx: &MatchVisitor<'_, '_>, + cx: &mut MatchVisitor<'_, '_>, has_guard: bool, pats: &[P<Pat>], ) { @@ -565,7 +569,12 @@ fn check_legality_of_move_bindings( }) } let span_vec = &mut Vec::new(); - let check_move = |p: &Pat, sub: Option<&Pat>, span_vec: &mut Vec<Span>| { + let check_move = | + cx: &mut MatchVisitor<'_, '_>, + p: &Pat, + sub: Option<&Pat>, + span_vec: &mut Vec<Span>, + | { // check legality of moving out of the enum // x @ Foo(..) is legal, but x @ Foo(y) isn't. @@ -574,15 +583,19 @@ fn check_legality_of_move_bindings( "cannot bind by-move with sub-bindings") .span_label(p.span, "binds an already bound by-move value by moving it") .emit(); - } else if has_guard && !cx.tcx.features().bind_by_move_pattern_guards { - let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008, - "cannot bind by-move into a pattern guard"); - err.span_label(p.span, "moves value into pattern guard"); - if cx.tcx.sess.opts.unstable_features.is_nightly_build() { - err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \ - crate attributes to enable"); + } else if has_guard { + if cx.tcx.features().bind_by_move_pattern_guards { + cx.signalled_error = SignalledError::SawSomeError; + } else { + let mut err = struct_span_err!(cx.tcx.sess, p.span, E0008, + "cannot bind by-move into a pattern guard"); + err.span_label(p.span, "moves value into pattern guard"); + if cx.tcx.sess.opts.unstable_features.is_nightly_build() { + err.help("add `#![feature(bind_by_move_pattern_guards)]` to the \ + crate attributes to enable"); + } + err.emit(); } - err.emit(); } else if let Some(_by_ref_span) = by_ref_span { span_vec.push(p.span); } @@ -596,7 +609,7 @@ fn check_legality_of_move_bindings( ty::BindByValue(..) => { let pat_ty = cx.tables.node_type(p.hir_id); if !pat_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, pat.span) { - check_move(p, sub.as_ref().map(|p| &**p), span_vec); + check_move(cx, p, sub.as_ref().map(|p| &**p), span_vec); } } _ => {} |
