Ast,
Mir,
Compare,
+ Migrate,
}
impl BorrowckMode {
+ /// Should we run the MIR-based borrow check, but also fall back
+ /// on the AST borrow check if the MIR-based one errors.
+ pub fn migrate(self) -> bool {
+ match self {
+ BorrowckMode::Ast => false,
+ BorrowckMode::Compare => false,
+ BorrowckMode::Mir => false,
+ BorrowckMode::Migrate => true,
+ }
+ }
+
/// Should we emit the AST-based borrow checker errors?
pub fn use_ast(self) -> bool {
match self {
BorrowckMode::Ast => true,
BorrowckMode::Compare => true,
BorrowckMode::Mir => false,
+ BorrowckMode::Migrate => false,
}
}
/// Should we emit the MIR-based borrow checker errors?
BorrowckMode::Ast => false,
BorrowckMode::Compare => true,
BorrowckMode::Mir => true,
+ BorrowckMode::Migrate => true,
}
}
}
None | Some("ast") => BorrowckMode::Ast,
Some("mir") => BorrowckMode::Mir,
Some("compare") => BorrowckMode::Compare,
+ Some("migrate") => BorrowckMode::Migrate,
Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
};
self.borrowck_mode().use_mir()
}
+ /// If true, we should use the MIR-based borrow check, but also
+ /// fall back on the AST borrow check if the MIR-based one errors.
+ pub fn migrate_borrowck(self) -> bool {
+ self.borrowck_mode().migrate()
+ }
+
/// If true, make MIR codegen for `match` emit a temp that holds a
/// borrow of the input to the match expression.
pub fn generate_borrow_of_any_match_input(&self) -> bool {
pub fn borrowck_mode(&self) -> BorrowckMode {
match self.sess.opts.borrowck_mode {
mode @ BorrowckMode::Mir |
+ mode @ BorrowckMode::Migrate |
mode @ BorrowckMode::Compare => mode,
mode @ BorrowckMode::Ast => {
fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
-> Lrc<BorrowCheckResult>
{
- assert!(tcx.use_ast_borrowck());
+ assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck());
debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
}
}
+ pub fn is_error(&self) -> bool {
+ match self.level {
+ Level::Bug |
+ Level::Fatal |
+ Level::PhaseFatal |
+ Level::Error |
+ Level::FailureNote => {
+ true
+ }
+
+ Level::Warning |
+ Level::Note |
+ Level::Help |
+ Level::Cancelled => {
+ false
+ }
+ }
+ }
+
/// Cancel the diagnostic (a structured diagnostic must either be emitted or
/// canceled or it will panic when dropped).
pub fn cancel(&mut self) {
buffered_diagnostics.push(diagnostic);
}
- pub fn is_error(&self) -> bool {
- match self.level {
- Level::Bug |
- Level::Fatal |
- Level::PhaseFatal |
- Level::Error |
- Level::FailureNote => {
- true
- }
-
- Level::Warning |
- Level::Note |
- Level::Help |
- Level::Cancelled => {
- false
- }
- }
- }
-
/// Convenience function for internal use, clients should use one of the
/// span_* methods instead.
pub fn sub<S: Into<MultiSpan>>(
use rustc::hir::map::definitions::DefPathData;
use rustc::infer::InferCtxt;
use rustc::lint::builtin::UNUSED_MUT;
+use rustc::middle::borrowck::SignalledError;
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
use rustc::ty::query::Providers;
use rustc::ty::{self, ParamEnv, TyCtxt};
-use rustc_errors::{Diagnostic, DiagnosticBuilder};
+use rustc_errors::{Diagnostic, DiagnosticBuilder, Level};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_set::IdxSetBuf;
}
}
- for diag in mbcx.errors_buffer.drain(..) {
- DiagnosticBuilder::new_diagnostic(mbcx.tcx.sess.diagnostic(), diag).emit();
+ if mbcx.errors_buffer.len() > 0 {
+ if tcx.migrate_borrowck() {
+ match tcx.borrowck(def_id).signalled_any_error {
+ SignalledError::NoErrorsSeen => {
+ // if AST-borrowck signalled no errors, then
+ // downgrade all the buffered MIR-borrowck errors
+ // to warnings.
+ for err in &mut mbcx.errors_buffer {
+ if err.is_error() { err.level = Level::Warning; }
+ }
+ }
+ SignalledError::SawSomeError => {
+ // if AST-borrowck signalled a (cancelled) error,
+ // then we will just emit the buffered
+ // MIR-borrowck errors as normal.
+ }
+ }
+ }
+
+ for diag in mbcx.errors_buffer.drain(..) {
+ DiagnosticBuilder::new_diagnostic(mbcx.tcx.sess.diagnostic(), diag).emit();
+ }
}
let result = BorrowCheckResult {