about summary refs log tree commit diff
path: root/src/librustc
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-07-27 09:10:07 +0000
committerbors <bors@rust-lang.org>2018-07-27 09:10:07 +0000
commitb18b9edf006c10f4e08794d31425001401e27a09 (patch)
tree2e6c4791602dbf267f89a81ab42f506f3af84d7b /src/librustc
parent7c2aeb9d974e85e54efa18cd63195bfd95347a44 (diff)
parent9f05f29e564c03a432df78f7c4b6421e4fb1a338 (diff)
downloadrust-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.rs8
-rw-r--r--src/librustc/session/config.rs17
-rw-r--r--src/librustc/ty/context.rs60
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,
+            },
         }
     }