Add `-Z borrowck=migrate` flag, use it to link NLL up to AST-borrowck.
This commit is contained in:
parent
655894baf9
commit
a23e8a726c
|
@ -455,15 +455,28 @@ pub enum BorrowckMode {
|
||||||
Ast,
|
Ast,
|
||||||
Mir,
|
Mir,
|
||||||
Compare,
|
Compare,
|
||||||
|
Migrate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BorrowckMode {
|
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?
|
/// Should we emit the AST-based borrow checker errors?
|
||||||
pub fn use_ast(self) -> bool {
|
pub fn use_ast(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
BorrowckMode::Ast => true,
|
BorrowckMode::Ast => true,
|
||||||
BorrowckMode::Compare => true,
|
BorrowckMode::Compare => true,
|
||||||
BorrowckMode::Mir => false,
|
BorrowckMode::Mir => false,
|
||||||
|
BorrowckMode::Migrate => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// Should we emit the MIR-based borrow checker errors?
|
/// Should we emit the MIR-based borrow checker errors?
|
||||||
|
@ -472,6 +485,7 @@ impl BorrowckMode {
|
||||||
BorrowckMode::Ast => false,
|
BorrowckMode::Ast => false,
|
||||||
BorrowckMode::Compare => true,
|
BorrowckMode::Compare => true,
|
||||||
BorrowckMode::Mir => true,
|
BorrowckMode::Mir => true,
|
||||||
|
BorrowckMode::Migrate => true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2166,6 +2180,7 @@ pub fn build_session_options_and_crate_config(
|
||||||
None | Some("ast") => BorrowckMode::Ast,
|
None | Some("ast") => BorrowckMode::Ast,
|
||||||
Some("mir") => BorrowckMode::Mir,
|
Some("mir") => BorrowckMode::Mir,
|
||||||
Some("compare") => BorrowckMode::Compare,
|
Some("compare") => BorrowckMode::Compare,
|
||||||
|
Some("migrate") => BorrowckMode::Migrate,
|
||||||
Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
|
Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1366,6 +1366,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
self.borrowck_mode().use_mir()
|
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
|
/// If true, make MIR codegen for `match` emit a temp that holds a
|
||||||
/// borrow of the input to the match expression.
|
/// borrow of the input to the match expression.
|
||||||
pub fn generate_borrow_of_any_match_input(&self) -> bool {
|
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 {
|
pub fn borrowck_mode(&self) -> BorrowckMode {
|
||||||
match self.sess.opts.borrowck_mode {
|
match self.sess.opts.borrowck_mode {
|
||||||
mode @ BorrowckMode::Mir |
|
mode @ BorrowckMode::Mir |
|
||||||
|
mode @ BorrowckMode::Migrate |
|
||||||
mode @ BorrowckMode::Compare => mode,
|
mode @ BorrowckMode::Compare => mode,
|
||||||
|
|
||||||
mode @ BorrowckMode::Ast => {
|
mode @ BorrowckMode::Ast => {
|
||||||
|
|
|
@ -90,7 +90,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
|
||||||
fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
|
fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
|
||||||
-> Lrc<BorrowCheckResult>
|
-> Lrc<BorrowCheckResult>
|
||||||
{
|
{
|
||||||
assert!(tcx.use_ast_borrowck());
|
assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck());
|
||||||
|
|
||||||
debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
|
debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
|
||||||
|
|
||||||
|
|
|
@ -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
|
/// Cancel the diagnostic (a structured diagnostic must either be emitted or
|
||||||
/// canceled or it will panic when dropped).
|
/// canceled or it will panic when dropped).
|
||||||
pub fn cancel(&mut self) {
|
pub fn cancel(&mut self) {
|
||||||
|
|
|
@ -100,25 +100,6 @@ impl<'a> DiagnosticBuilder<'a> {
|
||||||
buffered_diagnostics.push(diagnostic);
|
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
|
/// Convenience function for internal use, clients should use one of the
|
||||||
/// span_* methods instead.
|
/// span_* methods instead.
|
||||||
pub fn sub<S: Into<MultiSpan>>(
|
pub fn sub<S: Into<MultiSpan>>(
|
||||||
|
|
|
@ -16,6 +16,7 @@ use rustc::hir::def_id::DefId;
|
||||||
use rustc::hir::map::definitions::DefPathData;
|
use rustc::hir::map::definitions::DefPathData;
|
||||||
use rustc::infer::InferCtxt;
|
use rustc::infer::InferCtxt;
|
||||||
use rustc::lint::builtin::UNUSED_MUT;
|
use rustc::lint::builtin::UNUSED_MUT;
|
||||||
|
use rustc::middle::borrowck::SignalledError;
|
||||||
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
|
||||||
use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
|
use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
|
||||||
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
|
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::query::Providers;
|
||||||
use rustc::ty::{self, ParamEnv, TyCtxt};
|
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::graph::dominators::Dominators;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_data_structures::indexed_set::IdxSetBuf;
|
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(..) {
|
if mbcx.errors_buffer.len() > 0 {
|
||||||
DiagnosticBuilder::new_diagnostic(mbcx.tcx.sess.diagnostic(), diag).emit();
|
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 {
|
let result = BorrowCheckResult {
|
||||||
|
|
Loading…
Reference in New Issue