Add `-Z borrowck=migrate` flag, use it to link NLL up to AST-borrowck.

This commit is contained in:
Felix S. Klock II 2018-07-20 17:29:29 +02:00
parent 655894baf9
commit a23e8a726c
6 changed files with 66 additions and 23 deletions

View File

@ -455,15 +455,28 @@ pub enum BorrowckMode {
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?
@ -472,6 +485,7 @@ impl BorrowckMode {
BorrowckMode::Ast => false,
BorrowckMode::Compare => true,
BorrowckMode::Mir => true,
BorrowckMode::Migrate => true,
}
}
}
@ -2166,6 +2180,7 @@ pub fn build_session_options_and_crate_config(
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)),
};

View File

@ -1366,6 +1366,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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 {
@ -1399,6 +1405,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
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 => {

View File

@ -90,7 +90,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
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);

View File

@ -99,6 +99,25 @@ impl 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
}
}
}
/// Cancel the diagnostic (a structured diagnostic must either be emitted or
/// canceled or it will panic when dropped).
pub fn cancel(&mut self) {

View File

@ -100,25 +100,6 @@ impl<'a> DiagnosticBuilder<'a> {
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>>(

View File

@ -16,6 +16,7 @@ use rustc::hir::def_id::DefId;
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};
@ -23,7 +24,7 @@ use rustc::mir::{Terminator, TerminatorKind};
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;
@ -329,8 +330,28 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
}
}
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 {