diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index 8e176efb2a9ed..d59c91318b4e7 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -367,6 +367,19 @@ fn run_compiler( return early_exit(); } + // We need to get at least far before we have even a hope of generating a binary. + // FIXME: is that true? maybe we can ignore unresolved locals in dead code and that sort of thing + // That might require making name-resolution incremental, though. + if !sess.opts.unstable_opts.borrowck_unreachable { + // Make sure the user sees dead code warnings, so they know which items aren't checked. + // Normally that's done by `tcx.analysis()`, but we bypass that here. + queries.global_ctxt()?.peek_mut().enter(|tcx| { + tcx.hir() + .par_for_each_module(|module| tcx.ensure().check_mod_deathness(module)); + }); + return queries.linker().map(Some); + } + queries.global_ctxt()?; if sess.opts.unstable_opts.no_analysis { diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index fc0b11183f7bf..8924952e3e4f5 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -216,7 +216,7 @@ impl<'tcx> Queries<'tcx> { let crate_name = self.crate_name()?.peek().clone(); let outputs = self.prepare_outputs()?.peek().clone(); let dep_graph = self.dep_graph()?.peek().clone(); - let (krate, resolver, lint_store) = self.expansion()?.take(); + let (krate, resolver, lint_store) = self.expansion()?.peek().clone(); Ok(passes::create_global_ctxt( self.compiler, lint_store, @@ -237,7 +237,9 @@ impl<'tcx> Queries<'tcx> { self.ongoing_codegen.compute(|| { let outputs = self.prepare_outputs()?; self.global_ctxt()?.peek_mut().enter(|tcx| { - tcx.analysis(()).ok(); + if tcx.sess.opts.unstable_opts.borrowck_unreachable { + tcx.analysis(()).ok(); + } // Don't do code generation if there were any errors self.session().compile_status()?; diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 15a24aa4ace51..ba498c5c6242d 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -175,6 +175,13 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::GlobalAsm(..) => return true, }; + // We need this for `-Zborrowck-unreachable=no`, since we don't borrowck the whole crate at once, only on-demand. + if let Some(local) = def_id.as_local() { + if tcx.hir().maybe_body_owned_by(local).is_some() { + tcx.ensure().mir_borrowck(local); + } + } + !tcx.subst_and_check_impossible_predicates((def_id, &substs)) } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f9ee202466f67..7cf0351b6b77f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1225,6 +1225,8 @@ options! { binary_dep_depinfo: bool = (false, parse_bool, [TRACKED], "include artifacts (sysroot, crate dependencies) used during compilation in dep-info \ (default: no)"), + borrowck_unreachable: bool = (true, parse_bool, [TRACKED], + "force borrowck to run even on functions that are never used"), box_noalias: Option = (None, parse_opt_bool, [TRACKED], "emit noalias metadata for box (default: yes)"), branch_protection: Option = (None, parse_branch_protection, [TRACKED], diff --git a/src/test/ui/fuckit/borrowck-live-code.rs b/src/test/ui/fuckit/borrowck-live-code.rs new file mode 100644 index 0000000000000..6628017cc8f4f --- /dev/null +++ b/src/test/ui/fuckit/borrowck-live-code.rs @@ -0,0 +1,9 @@ +// compile-flags: -Z borrowck-unreachable=no +// build-fail +fn live_code(s: &str) -> &'static str { + s //~ ERROR lifetime may not live long enough +} + +fn main() { + println!("{}", live_code("he he he")); +} diff --git a/src/test/ui/fuckit/borrowck-live-code.stderr b/src/test/ui/fuckit/borrowck-live-code.stderr new file mode 100644 index 0000000000000..2659cc0decdc1 --- /dev/null +++ b/src/test/ui/fuckit/borrowck-live-code.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/borrowck-live-code.rs:4:5 + | +LL | fn live_code(s: &str) -> &'static str { + | - let's call the lifetime of this reference `'1` +LL | s + | ^ returning this value requires that `'1` must outlive `'static` + +error: aborting due to previous error + diff --git a/src/test/ui/fuckit/no-borrowck-dead-code.rs b/src/test/ui/fuckit/no-borrowck-dead-code.rs new file mode 100644 index 0000000000000..0c2934aaaedf6 --- /dev/null +++ b/src/test/ui/fuckit/no-borrowck-dead-code.rs @@ -0,0 +1,10 @@ +// compile-flags: -Z borrowck-unreachable=no +// run-pass + +fn dead_code(s: &str) -> &'static str { //~ WARNING dead_code + s +} + +fn main() { + println!("he he he") +} diff --git a/src/test/ui/fuckit/no-borrowck-dead-code.stderr b/src/test/ui/fuckit/no-borrowck-dead-code.stderr new file mode 100644 index 0000000000000..b08af3866b57b --- /dev/null +++ b/src/test/ui/fuckit/no-borrowck-dead-code.stderr @@ -0,0 +1,10 @@ +warning: function `dead_code` is never used + --> $DIR/no-borrowck-dead-code.rs:4:4 + | +LL | fn dead_code(s: &str) -> &'static str { + | ^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/fuckit/no-typeck-dead-code.rs b/src/test/ui/fuckit/no-typeck-dead-code.rs new file mode 100644 index 0000000000000..038058152b3f1 --- /dev/null +++ b/src/test/ui/fuckit/no-typeck-dead-code.rs @@ -0,0 +1,10 @@ +// compile-flags: -Z borrowck-unreachable=no +// run-pass + +fn dead_code(s: &str) -> bool { //~ WARNING never used + true +} + +fn main() { + println!("he he he") +} diff --git a/src/test/ui/fuckit/no-typeck-dead-code.stderr b/src/test/ui/fuckit/no-typeck-dead-code.stderr new file mode 100644 index 0000000000000..0cac8d85b2f87 --- /dev/null +++ b/src/test/ui/fuckit/no-typeck-dead-code.stderr @@ -0,0 +1,10 @@ +warning: function `dead_code` is never used + --> $DIR/no-typeck-dead-code.rs:4:4 + | +LL | fn dead_code(s: &str) -> bool { + | ^^^^^^^^^ + | + = note: `#[warn(dead_code)]` on by default + +warning: 1 warning emitted + diff --git a/src/test/ui/fuckit/typeck-live-code.rs b/src/test/ui/fuckit/typeck-live-code.rs new file mode 100644 index 0000000000000..bab3ee257e381 --- /dev/null +++ b/src/test/ui/fuckit/typeck-live-code.rs @@ -0,0 +1,8 @@ +// compile-flags: -Z borrowck-unreachable=no +fn live_code(s: &str) -> bool { + s //~ ERROR mismatched types +} + +fn main() { + println!("{}", live_code("he he he")); +} diff --git a/src/test/ui/fuckit/typeck-live-code.stderr b/src/test/ui/fuckit/typeck-live-code.stderr new file mode 100644 index 0000000000000..b7ba37dff8339 --- /dev/null +++ b/src/test/ui/fuckit/typeck-live-code.stderr @@ -0,0 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/typeck-live-code.rs:3:5 + | +LL | fn live_code(s: &str) -> bool { + | ---- expected `bool` because of return type +LL | s + | ^ expected `bool`, found `&str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.