about summary refs log tree commit diff
diff options
context:
space:
mode:
authorest31 <MTest31@outlook.com>2017-11-19 23:35:53 +0100
committerest31 <MTest31@outlook.com>2017-11-26 16:36:52 +0100
commitc9af68e90cc7a551130873363a6776a4c04e2a6d (patch)
tree7cacceb88af3e9ae5012ccb89d7eea3e09896809
parent2ca00a948934766950167e997903a2cc0243c5cf (diff)
downloadrust-c9af68e90cc7a551130873363a6776a4c04e2a6d.tar.gz
rust-c9af68e90cc7a551130873363a6776a4c04e2a6d.zip
Replace -Zborrowck-mir with -Zborrowck=mode
where mode is one of {ast,mir,compare}.

This commit only implements the functionality.
The tests will be updated in a follow up commit.
-rw-r--r--src/librustc/session/config.rs44
-rw-r--r--src/librustc/session/mod.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs11
-rw-r--r--src/librustc_mir/borrow_check.rs2
-rw-r--r--src/librustc_mir/util/borrowck_errors.rs154
5 files changed, 160 insertions, 53 deletions
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index a56f850942c..97b9d776a57 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -362,6 +362,9 @@ top_level_options!(
 
         debugging_opts: DebuggingOptions [TRACKED],
         prints: Vec<PrintRequest> [UNTRACKED],
+        // Determines which borrow checker(s) to run. This is the parsed, sanitized
+        // version of `debugging_opts.borrowck`, which is just a plain string.
+        borrowck_mode: BorrowckMode [UNTRACKED],
         cg: CodegenOptions [TRACKED],
         // FIXME(mw): We track this for now but it actually doesn't make too
         //            much sense: The value of this option can stay the same
@@ -401,6 +404,32 @@ pub enum PrintRequest {
     NativeStaticLibs,
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+pub enum BorrowckMode {
+    Ast,
+    Mir,
+    Compare,
+}
+
+impl BorrowckMode {
+    /// 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,
+        }
+    }
+    /// Should we emit the MIR-based borrow checker errors?
+    pub fn use_mir(self) -> bool {
+        match self {
+            BorrowckMode::Ast => false,
+            BorrowckMode::Compare => true,
+            BorrowckMode::Mir => true,
+        }
+    }
+}
+
 pub enum Input {
     /// Load source from file
     File(PathBuf),
@@ -526,6 +555,7 @@ pub fn basic_options() -> Options {
         incremental: None,
         debugging_opts: basic_debugging_options(),
         prints: Vec::new(),
+        borrowck_mode: BorrowckMode::Ast,
         cg: basic_codegen_options(),
         error_format: ErrorOutputType::default(),
         externs: Externs(BTreeMap::new()),
@@ -973,8 +1003,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "make unnamed regions display as '# (where # is some non-ident unique id)"),
     emit_end_regions: bool = (false, parse_bool, [UNTRACKED],
         "emit EndRegion as part of MIR; enable transforms that solely process EndRegion"),
-    borrowck_mir: bool = (false, parse_bool, [UNTRACKED],
-        "implicitly treat functions as if they have `#[rustc_mir_borrowck]` attribute"),
+    borrowck: Option<String> = (None, parse_opt_string, [UNTRACKED],
+        "select which borrowck is used (`ast`, `mir`, or `compare`)"),
     time_passes: bool = (false, parse_bool, [UNTRACKED],
         "measure time of each rustc pass"),
     count_llvm_insns: bool = (false, parse_bool,
@@ -1743,6 +1773,15 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         }
     }));
 
+    let borrowck_mode = match debugging_opts.borrowck.as_ref().map(|s| &s[..]) {
+        None | Some("ast") => BorrowckMode::Ast,
+        Some("mir") => BorrowckMode::Mir,
+        Some("compare") => BorrowckMode::Compare,
+        Some(m) => {
+            early_error(error_format, &format!("unknown borrowchk mode `{}`", m))
+        },
+    };
+
     if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
         early_warn(error_format, "-C remark will not show source locations without \
                                 --debuginfo");
@@ -1784,6 +1823,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
         incremental,
         debugging_opts,
         prints,
+        borrowck_mode,
         cg,
         error_format,
         externs: Externs(externs),
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 642153c08f6..227efcf4d6e 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -416,7 +416,7 @@ impl Session {
     pub fn emit_end_regions(&self) -> bool {
         self.opts.debugging_opts.emit_end_regions ||
             (self.opts.debugging_opts.mir_emit_validate > 0) ||
-            self.opts.debugging_opts.borrowck_mir
+            self.opts.borrowck_mode.use_mir()
     }
     pub fn lto(&self) -> bool {
         self.opts.cg.lto || self.target.target.options.requires_lto
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index 36b397bbbe5..40837c5e8d6 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -269,6 +269,17 @@ impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> {
     {
         self.tcx.sess.struct_span_err(sp, msg)
     }
+
+    fn cancel_if_wrong_origin<'a>(&'a self,
+                                mut diag: DiagnosticBuilder<'a>,
+                                o: Origin)
+                                -> DiagnosticBuilder<'a>
+    {
+        if !o.should_emit_errors(self.tcx.sess.opts.borrowck_mode) {
+            self.tcx.sess.diagnostic().cancel(&mut diag);
+        }
+        diag
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs
index 4d54c6f473c..289636be321 100644
--- a/src/librustc_mir/borrow_check.rs
+++ b/src/librustc_mir/borrow_check.rs
@@ -54,7 +54,7 @@ fn mir_borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
 
     if {
         !tcx.has_attr(def_id, "rustc_mir_borrowck") &&
-            !tcx.sess.opts.debugging_opts.borrowck_mir &&
+            !tcx.sess.opts.borrowck_mode.use_mir() &&
             !tcx.sess.opts.debugging_opts.nll
     } {
         return;
diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs
index 2f29b79eeb6..00248400c55 100644
--- a/src/librustc_mir/util/borrowck_errors.rs
+++ b/src/librustc_mir/util/borrowck_errors.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use rustc::ty::{self, TyCtxt};
+use rustc::session::config::BorrowckMode;
 use rustc_errors::{DiagnosticBuilder, DiagnosticId};
 use syntax_pos::{MultiSpan, Span};
 
@@ -19,20 +20,34 @@ pub enum Origin { Ast, Mir }
 
 impl fmt::Display for Origin {
     fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
-        match *self {
-            Origin::Mir => write!(w, " (Mir)"),
-            Origin::Ast => ty::tls::with_opt(|opt_tcx| {
-                // If user passed `-Z borrowck-mir`, then include an
-                // AST origin as part of the error report
-                if let Some(tcx) = opt_tcx {
-                    if tcx.sess.opts.debugging_opts.borrowck_mir {
-                        return write!(w, " (Ast)");
-                    }
-                }
-                // otherwise, do not include the origin (i.e., print
-                // nothing at all)
-                Ok(())
-            }),
+        // If the user passed `-Z borrowck=compare`, then include
+        // origin info as part of the error report,
+        // otherwise
+        let display_origin = ty::tls::with_opt(|opt_tcx| {
+            if let Some(tcx) = opt_tcx {
+                tcx.sess.opts.borrowck_mode == BorrowckMode::Compare
+            } else {
+                false
+            }
+        });
+        if display_origin {
+            match *self {
+                Origin::Mir => write!(w, " (Mir)"),
+                Origin::Ast => write!(w, " (Ast)"),
+            }
+        } else {
+            // Print no origin info
+            Ok(())
+        }
+    }
+}
+
+impl Origin {
+    /// Whether we should emit errors for the origin in the given mode
+    pub fn should_emit_errors(self, mode: BorrowckMode) -> bool {
+        match self {
+            Origin::Ast => mode.use_ast(),
+            Origin::Mir => mode.use_mir(),
         }
     }
 }
@@ -49,12 +64,23 @@ pub trait BorrowckErrors {
                                                msg: &str)
                                                -> DiagnosticBuilder<'a>;
 
+    /// Cancels the given error if we shouldn't emit errors for a given
+    /// origin in the current mode.
+    ///
+    /// Always make sure that the error gets passed through this function
+    /// before you return it.
+    fn cancel_if_wrong_origin<'a>(&'a self,
+                                diag: DiagnosticBuilder<'a>,
+                                o: Origin)
+                                -> DiagnosticBuilder<'a>;
+
     fn cannot_move_when_borrowed(&self, span: Span, desc: &str, o: Origin)
                                  -> DiagnosticBuilder
     {
-        struct_span_err!(self, span, E0505,
-                         "cannot move out of `{}` because it is borrowed{OGN}",
-                         desc, OGN=o)
+        let err = struct_span_err!(self, span, E0505,
+                                   "cannot move out of `{}` because it is borrowed{OGN}",
+                                   desc, OGN=o);
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_use_when_mutably_borrowed(&self,
@@ -72,7 +98,7 @@ pub trait BorrowckErrors {
         err.span_label(borrow_span, format!("borrow of `{}` occurs here", borrow_desc));
         err.span_label(span, format!("use of borrowed `{}`", borrow_desc));
 
-        err
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_act_on_uninitialized_variable(&self,
@@ -82,9 +108,10 @@ pub trait BorrowckErrors {
                                             o: Origin)
                                             -> DiagnosticBuilder
     {
-        struct_span_err!(self, span, E0381,
-                         "{} of possibly uninitialized variable: `{}`{OGN}",
-                         verb, desc, OGN=o)
+        let err = struct_span_err!(self, span, E0381,
+                                   "{} of possibly uninitialized variable: `{}`{OGN}",
+                                   verb, desc, OGN=o);
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_mutably_borrow_multiply(&self,
@@ -118,7 +145,7 @@ pub trait BorrowckErrors {
                 err.span_label(old_load_end_span, "first borrow ends here");
             }
         }
-        err
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_uniquely_borrow_by_two_closures(&self,
@@ -143,7 +170,7 @@ pub trait BorrowckErrors {
                 old_load_end_span,
                 "borrow from first closure ends here");
         }
-        err
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_uniquely_borrow_by_one_closure(&self,
@@ -167,7 +194,7 @@ pub trait BorrowckErrors {
         if let Some(previous_end_span) = previous_end_span {
             err.span_label(previous_end_span, "borrow ends here");
         }
-        err
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_reborrow_already_uniquely_borrowed(&self,
@@ -192,7 +219,7 @@ pub trait BorrowckErrors {
         if let Some(previous_end_span) = previous_end_span {
             err.span_label(previous_end_span, "borrow from closure ends here");
         }
-        err
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_reborrow_already_borrowed(&self,
@@ -216,7 +243,7 @@ pub trait BorrowckErrors {
         if let Some(old_load_end_span) = old_load_end_span {
             err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old));
         }
-        err
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_assign_to_borrowed(&self, span: Span, borrow_span: Span, desc: &str, o: Origin)
@@ -229,30 +256,35 @@ pub trait BorrowckErrors {
         err.span_label(borrow_span, format!("borrow of `{}` occurs here", desc));
         err.span_label(span, format!("assignment to borrowed `{}` occurs here", desc));
 
-        err
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_move_into_closure(&self, span: Span, desc: &str, o: Origin)
                                 -> DiagnosticBuilder
     {
-        struct_span_err!(self, span, E0504,
-                         "cannot move `{}` into closure because it is borrowed{OGN}",
-                         desc, OGN=o)
+        let err = struct_span_err!(self, span, E0504,
+                                   "cannot move `{}` into closure because it is borrowed{OGN}",
+                                   desc, OGN=o);
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_reassign_immutable(&self, span: Span, desc: &str, o: Origin)
                                  -> DiagnosticBuilder
     {
-        struct_span_err!(self, span, E0384,
-                         "cannot assign twice to immutable variable `{}`{OGN}",
-                         desc, OGN=o)
+        let err = struct_span_err!(self, span, E0384,
+                                   "cannot assign twice to immutable variable `{}`{OGN}",
+                                   desc, OGN=o);
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_assign(&self, span: Span, desc: &str, o: Origin) -> DiagnosticBuilder
     {
-        struct_span_err!(self, span, E0594,
-                         "cannot assign to {}{OGN}",
-                         desc, OGN=o)
+        let err = struct_span_err!(self, span, E0594,
+                                  "cannot assign to {}{OGN}",
+                                  desc, OGN=o);
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_assign_static(&self, span: Span, desc: &str, o: Origin)
@@ -270,7 +302,8 @@ pub trait BorrowckErrors {
         err.span_label(
             move_from_span,
             format!("cannot move out of {}", move_from_desc));
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_move_out_of_interior_noncopy(&self,
@@ -290,7 +323,8 @@ pub trait BorrowckErrors {
                                         a non-copy {}{OGN}",
                                        ty, type_name, OGN=o);
         err.span_label(move_from_span, "cannot move out of here");
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_move_out_of_interior_of_drop(&self,
@@ -304,7 +338,8 @@ pub trait BorrowckErrors {
                                         which implements the `Drop` trait{OGN}",
                                        container_ty, OGN=o);
         err.span_label(move_from_span, "cannot move out of here");
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_act_on_moved_value(&self,
@@ -318,7 +353,8 @@ pub trait BorrowckErrors {
         let err = struct_span_err!(self, use_span, E0382,
                                    "{} of {}moved value: `{}`{OGN}",
                                    verb, optional_adverb_for_moved, moved_path, OGN=o);
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_partially_reinit_an_uninit_struct(&self,
@@ -332,7 +368,8 @@ pub trait BorrowckErrors {
                                    E0383,
                                    "partial reinitialization of uninitialized structure `{}`{OGN}",
                                    uninit_path, OGN=o);
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn closure_cannot_assign_to_borrowed(&self,
@@ -343,7 +380,8 @@ pub trait BorrowckErrors {
     {
         let err = struct_span_err!(self, span, E0595, "closure cannot assign to {}{OGN}",
                                    descr, OGN=o);
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_borrow_path_as_mutable(&self,
@@ -354,7 +392,8 @@ pub trait BorrowckErrors {
     {
         let err = struct_span_err!(self, span, E0596, "cannot borrow {} as mutable{OGN}",
                                    path, OGN=o);
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_borrow_across_generator_yield(&self,
@@ -369,7 +408,8 @@ pub trait BorrowckErrors {
                                        "borrow may still be in use when generator yields{OGN}",
                                        OGN=o);
         err.span_label(yield_span, "possible yield occurs here");
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn path_does_not_live_long_enough(&self,
@@ -380,7 +420,8 @@ pub trait BorrowckErrors {
     {
         let err = struct_span_err!(self, span, E0597, "{} does not live long enough{OGN}",
                                    path, OGN=o);
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn lifetime_too_short_for_reborrow(&self,
@@ -393,7 +434,8 @@ pub trait BorrowckErrors {
                                    "lifetime of {} is too short to guarantee \
                                     its contents can be safely reborrowed{OGN}",
                                    path, OGN=o);
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_act_on_capture_in_sharable_fn(&self,
@@ -408,7 +450,8 @@ pub trait BorrowckErrors {
                                        "{} in a captured outer variable in an `Fn` closure{OGN}",
                                        bad_thing, OGN=o);
         err.span_help(help_span, help_msg);
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_assign_into_immutable_reference(&self,
@@ -420,7 +463,8 @@ pub trait BorrowckErrors {
         let mut err = struct_span_err!(self, span, E0389, "{} in a `&` reference{OGN}",
                                        bad_thing, OGN=o);
         err.span_label(span, "assignment into an immutable reference");
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 
     fn cannot_capture_in_long_lived_closure(&self,
@@ -437,7 +481,8 @@ pub trait BorrowckErrors {
                                        borrowed_path, OGN=o);
         err.span_label(capture_span, format!("{} is borrowed here", borrowed_path))
             .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path));
-        err
+
+        self.cancel_if_wrong_origin(err, o)
     }
 }
 
@@ -458,4 +503,15 @@ impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> {
     {
         self.sess.struct_span_err(sp, msg)
     }
+
+    fn cancel_if_wrong_origin<'a>(&'a self,
+                                mut diag: DiagnosticBuilder<'a>,
+                                o: Origin)
+                                -> DiagnosticBuilder<'a>
+    {
+        if !o.should_emit_errors(self.sess.opts.borrowck_mode) {
+            self.sess.diagnostic().cancel(&mut diag);
+        }
+        diag
+    }
 }