Skip to content

Commit a23e8a7

Browse files
committed
Add -Z borrowck=migrate flag, use it to link NLL up to AST-borrowck.
1 parent 655894b commit a23e8a7

File tree

6 files changed

+66
-23
lines changed

6 files changed

+66
-23
lines changed

src/librustc/session/config.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,15 +455,28 @@ pub enum BorrowckMode {
455455
Ast,
456456
Mir,
457457
Compare,
458+
Migrate,
458459
}
459460

460461
impl BorrowckMode {
462+
/// Should we run the MIR-based borrow check, but also fall back
463+
/// on the AST borrow check if the MIR-based one errors.
464+
pub fn migrate(self) -> bool {
465+
match self {
466+
BorrowckMode::Ast => false,
467+
BorrowckMode::Compare => false,
468+
BorrowckMode::Mir => false,
469+
BorrowckMode::Migrate => true,
470+
}
471+
}
472+
461473
/// Should we emit the AST-based borrow checker errors?
462474
pub fn use_ast(self) -> bool {
463475
match self {
464476
BorrowckMode::Ast => true,
465477
BorrowckMode::Compare => true,
466478
BorrowckMode::Mir => false,
479+
BorrowckMode::Migrate => false,
467480
}
468481
}
469482
/// Should we emit the MIR-based borrow checker errors?
@@ -472,6 +485,7 @@ impl BorrowckMode {
472485
BorrowckMode::Ast => false,
473486
BorrowckMode::Compare => true,
474487
BorrowckMode::Mir => true,
488+
BorrowckMode::Migrate => true,
475489
}
476490
}
477491
}
@@ -2166,6 +2180,7 @@ pub fn build_session_options_and_crate_config(
21662180
None | Some("ast") => BorrowckMode::Ast,
21672181
Some("mir") => BorrowckMode::Mir,
21682182
Some("compare") => BorrowckMode::Compare,
2183+
Some("migrate") => BorrowckMode::Migrate,
21692184
Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
21702185
};
21712186

src/librustc/ty/context.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1366,6 +1366,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
13661366
self.borrowck_mode().use_mir()
13671367
}
13681368

1369+
/// If true, we should use the MIR-based borrow check, but also
1370+
/// fall back on the AST borrow check if the MIR-based one errors.
1371+
pub fn migrate_borrowck(self) -> bool {
1372+
self.borrowck_mode().migrate()
1373+
}
1374+
13691375
/// If true, make MIR codegen for `match` emit a temp that holds a
13701376
/// borrow of the input to the match expression.
13711377
pub fn generate_borrow_of_any_match_input(&self) -> bool {
@@ -1399,6 +1405,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
13991405
pub fn borrowck_mode(&self) -> BorrowckMode {
14001406
match self.sess.opts.borrowck_mode {
14011407
mode @ BorrowckMode::Mir |
1408+
mode @ BorrowckMode::Migrate |
14021409
mode @ BorrowckMode::Compare => mode,
14031410

14041411
mode @ BorrowckMode::Ast => {

src/librustc_borrowck/borrowck/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub struct AnalysisData<'a, 'tcx: 'a> {
9090
fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId)
9191
-> Lrc<BorrowCheckResult>
9292
{
93-
assert!(tcx.use_ast_borrowck());
93+
assert!(tcx.use_ast_borrowck() || tcx.migrate_borrowck());
9494

9595
debug!("borrowck(body_owner_def_id={:?})", owner_def_id);
9696

src/librustc_errors/diagnostic.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,25 @@ impl Diagnostic {
9999
}
100100
}
101101

102+
pub fn is_error(&self) -> bool {
103+
match self.level {
104+
Level::Bug |
105+
Level::Fatal |
106+
Level::PhaseFatal |
107+
Level::Error |
108+
Level::FailureNote => {
109+
true
110+
}
111+
112+
Level::Warning |
113+
Level::Note |
114+
Level::Help |
115+
Level::Cancelled => {
116+
false
117+
}
118+
}
119+
}
120+
102121
/// Cancel the diagnostic (a structured diagnostic must either be emitted or
103122
/// canceled or it will panic when dropped).
104123
pub fn cancel(&mut self) {

src/librustc_errors/diagnostic_builder.rs

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -100,25 +100,6 @@ impl<'a> DiagnosticBuilder<'a> {
100100
buffered_diagnostics.push(diagnostic);
101101
}
102102

103-
pub fn is_error(&self) -> bool {
104-
match self.level {
105-
Level::Bug |
106-
Level::Fatal |
107-
Level::PhaseFatal |
108-
Level::Error |
109-
Level::FailureNote => {
110-
true
111-
}
112-
113-
Level::Warning |
114-
Level::Note |
115-
Level::Help |
116-
Level::Cancelled => {
117-
false
118-
}
119-
}
120-
}
121-
122103
/// Convenience function for internal use, clients should use one of the
123104
/// span_* methods instead.
124105
pub fn sub<S: Into<MultiSpan>>(

src/librustc_mir/borrow_check/mod.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ use rustc::hir::def_id::DefId;
1616
use rustc::hir::map::definitions::DefPathData;
1717
use rustc::infer::InferCtxt;
1818
use rustc::lint::builtin::UNUSED_MUT;
19+
use rustc::middle::borrowck::SignalledError;
1920
use rustc::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind};
2021
use rustc::mir::{ClearCrossCrate, Local, Location, Mir, Mutability, Operand, Place};
2122
use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind};
2223
use rustc::mir::{Terminator, TerminatorKind};
2324
use rustc::ty::query::Providers;
2425
use rustc::ty::{self, ParamEnv, TyCtxt};
2526

26-
use rustc_errors::{Diagnostic, DiagnosticBuilder};
27+
use rustc_errors::{Diagnostic, DiagnosticBuilder, Level};
2728
use rustc_data_structures::graph::dominators::Dominators;
2829
use rustc_data_structures::fx::FxHashSet;
2930
use rustc_data_structures::indexed_set::IdxSetBuf;
@@ -329,8 +330,28 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
329330
}
330331
}
331332

332-
for diag in mbcx.errors_buffer.drain(..) {
333-
DiagnosticBuilder::new_diagnostic(mbcx.tcx.sess.diagnostic(), diag).emit();
333+
if mbcx.errors_buffer.len() > 0 {
334+
if tcx.migrate_borrowck() {
335+
match tcx.borrowck(def_id).signalled_any_error {
336+
SignalledError::NoErrorsSeen => {
337+
// if AST-borrowck signalled no errors, then
338+
// downgrade all the buffered MIR-borrowck errors
339+
// to warnings.
340+
for err in &mut mbcx.errors_buffer {
341+
if err.is_error() { err.level = Level::Warning; }
342+
}
343+
}
344+
SignalledError::SawSomeError => {
345+
// if AST-borrowck signalled a (cancelled) error,
346+
// then we will just emit the buffered
347+
// MIR-borrowck errors as normal.
348+
}
349+
}
350+
}
351+
352+
for diag in mbcx.errors_buffer.drain(..) {
353+
DiagnosticBuilder::new_diagnostic(mbcx.tcx.sess.diagnostic(), diag).emit();
354+
}
334355
}
335356

336357
let result = BorrowCheckResult {

0 commit comments

Comments
 (0)