diff options
| author | bors <bors@rust-lang.org> | 2018-07-27 09:10:07 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-07-27 09:10:07 +0000 |
| commit | b18b9edf006c10f4e08794d31425001401e27a09 (patch) | |
| tree | 2e6c4791602dbf267f89a81ab42f506f3af84d7b /src/librustc | |
| parent | 7c2aeb9d974e85e54efa18cd63195bfd95347a44 (diff) | |
| parent | 9f05f29e564c03a432df78f7c4b6421e4fb1a338 (diff) | |
| download | rust-b18b9edf006c10f4e08794d31425001401e27a09.tar.gz rust-b18b9edf006c10f4e08794d31425001401e27a09.zip | |
Auto merge of #52681 - pnkfelix:z-borrowck-migrate, r=nikomatsakis
Add `-Z borrowck=migrate` This adds `-Z borrowck=migrate`, which represents the way we want to migrate to NLL under Rust versions to come. It also hooks this new mode into `--edition 2018`, which means we're officially turning NLL on in the 2018 edition. The basic idea of `-Z borrowck=migrate` that there are cases where NLL is fixing old soundness bugs in the borrow-checker, but in order to avoid just breaking code by immediately rejecting the programs that hit those soundness bugs, we instead use the following strategy: If your code is accepted by NLL, then we accept it. If your code is rejected by both NLL and the old AST-borrowck, then we reject it. If your code is rejected by NLL but accepted by the old AST-borrowck, then we emit the new NLL errors as **warnings**. These warnings will be turned into hard errors in the future, and they say so in these diagnostics. Fix #46908
Diffstat (limited to 'src/librustc')
| -rw-r--r-- | src/librustc/middle/borrowck.rs | 8 | ||||
| -rw-r--r-- | src/librustc/session/config.rs | 17 | ||||
| -rw-r--r-- | src/librustc/ty/context.rs | 60 |
3 files changed, 74 insertions, 11 deletions
diff --git a/src/librustc/middle/borrowck.rs b/src/librustc/middle/borrowck.rs index 6f5791ed5d7..c8d513a59f0 100644 --- a/src/librustc/middle/borrowck.rs +++ b/src/librustc/middle/borrowck.rs @@ -15,9 +15,15 @@ use util::nodemap::FxHashSet; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; +#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] +pub enum SignalledError { SawSomeError, NoErrorsSeen } + +impl_stable_hash_for!(enum self::SignalledError { SawSomeError, NoErrorsSeen }); + #[derive(Debug, RustcEncodable, RustcDecodable)] pub struct BorrowCheckResult { pub used_mut_nodes: FxHashSet<HirId>, + pub signalled_any_error: SignalledError, } impl<'a> HashStable<StableHashingContext<'a>> for BorrowCheckResult { @@ -26,7 +32,9 @@ impl<'a> HashStable<StableHashingContext<'a>> for BorrowCheckResult { hasher: &mut StableHasher<W>) { let BorrowCheckResult { ref used_mut_nodes, + ref signalled_any_error, } = *self; used_mut_nodes.hash_stable(hcx, hasher); + signalled_any_error.hash_stable(hcx, hasher); } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 54d9e24bbc0..4490b2f3fa9 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -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, } } } @@ -1127,7 +1141,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, emit_end_regions: bool = (false, parse_bool, [UNTRACKED], "emit EndRegion as part of MIR; enable transforms that solely process EndRegion"), borrowck: Option<String> = (None, parse_opt_string, [UNTRACKED], - "select which borrowck is used (`ast`, `mir`, or `compare`)"), + "select which borrowck is used (`ast`, `mir`, `migrate`, or `compare`)"), two_phase_borrows: bool = (false, parse_bool, [UNTRACKED], "use two-phase reserved/active distinction for `&mut` borrows in MIR borrowck"), two_phase_beyond_autoref: bool = (false, parse_bool, [UNTRACKED], @@ -2168,6 +2182,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)), }; diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 41007508c50..98568f860a4 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -74,6 +74,7 @@ use rustc_target::spec::abi; use syntax::ast::{self, NodeId}; use syntax::attr; use syntax::codemap::MultiSpan; +use syntax::edition::Edition; use syntax::feature_gate; use syntax::symbol::{Symbol, keywords, InternedString}; use syntax_pos::Span; @@ -1366,6 +1367,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 { @@ -1397,18 +1404,51 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// What mode(s) of borrowck should we run? AST? MIR? both? /// (Also considers the `#![feature(nll)]` setting.) pub fn borrowck_mode(&self) -> BorrowckMode { - match self.sess.opts.borrowck_mode { - mode @ BorrowckMode::Mir | - mode @ BorrowckMode::Compare => mode, + // Here are the main constraints we need to deal with: + // + // 1. An opts.borrowck_mode of `BorrowckMode::Ast` is + // synonymous with no `-Z borrowck=...` flag at all. + // (This is arguably a historical accident.) + // + // 2. `BorrowckMode::Migrate` is the limited migration to + // NLL that we are deploying with the 2018 edition. + // + // 3. We want to allow developers on the Nightly channel + // to opt back into the "hard error" mode for NLL, + // (which they can do via specifying `#![feature(nll)]` + // explicitly in their crate). + // + // So, this precedence list is how pnkfelix chose to work with + // the above constraints: + // + // * `#![feature(nll)]` *always* means use NLL with hard + // errors. (To simplify the code here, it now even overrides + // a user's attempt to specify `-Z borrowck=compare`, which + // we arguably do not need anymore and should remove.) + // + // * Otherwise, if no `-Z borrowck=...` flag was given (or + // if `borrowck=ast` was specified), then use the default + // as required by the edition. + // + // * Otherwise, use the behavior requested via `-Z borrowck=...` - mode @ BorrowckMode::Ast => { - if self.features().nll { - BorrowckMode::Mir - } else { - mode - } - } + if self.features().nll { return BorrowckMode::Mir; } + match self.sess.opts.borrowck_mode { + mode @ BorrowckMode::Mir | + mode @ BorrowckMode::Compare | + mode @ BorrowckMode::Migrate => mode, + + BorrowckMode::Ast => match self.sess.edition() { + Edition::Edition2015 => BorrowckMode::Ast, + Edition::Edition2018 => BorrowckMode::Migrate, + + // For now, future editions mean Migrate. (But it + // would make a lot of sense for it to be changed to + // `BorrowckMode::Mir`, depending on how we plan to + // time the forcing of full migration to NLL.) + _ => BorrowckMode::Migrate, + }, } } |
