From cd279a5b98c07a982824eb1b299cb0caad0c844d Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sun, 5 Nov 2017 18:09:39 +0200 Subject: [PATCH] run unsafety checking before dead block collection Fixes #45087. --- src/librustc/dep_graph/dep_node.rs | 2 +- src/librustc/ty/maps/mod.rs | 4 ++++ src/librustc/ty/maps/plumbing.rs | 2 +- src/librustc_mir/transform/check_unsafety.rs | 4 ++-- src/librustc_mir/transform/mod.rs | 12 ++++++++++-- .../issue-45087-unreachable-unsafe.rs | 15 +++++++++++++++ 6 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 src/test/compile-fail/issue-45087-unreachable-unsafe.rs diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 70cfe57d150..8e48513baa0 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -473,6 +473,7 @@ define_dep_nodes!( <'tcx> // Represents the MIR for a fn; also used as the task node for // things read/modify that MIR. [] MirConstQualif(DefId), + [] MirBuilt(DefId), [] MirConst(DefId), [] MirValidated(DefId), [] MirOptimized(DefId), @@ -812,4 +813,3 @@ impl WorkProductId { impl_stable_hash_for!(struct ::dep_graph::WorkProductId { hash }); - diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 7d8586741fb..8a9c38fde32 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -151,6 +151,10 @@ define_maps! { <'tcx> /// the value isn't known except to the pass itself. [] fn mir_const_qualif: MirConstQualif(DefId) -> (u8, Rc>), + /// Fetch the MIR for a given def-id right after it's built - this includes + /// unreachable code. + [] fn mir_built: MirBuilt(DefId) -> &'tcx Steal>, + /// Fetch the MIR for a given def-id up till the point where it is /// ready for const evaluation. /// diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index cc698cf03da..fc5f9b88ef3 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -712,6 +712,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, force!(crate_inherent_impls_overlap_check, LOCAL_CRATE) }, DepKind::PrivacyAccessLevels => { force!(privacy_access_levels, LOCAL_CRATE); } + DepKind::MirBuilt => { force!(mir_built, def_id!()); } DepKind::MirConstQualif => { force!(mir_const_qualif, def_id!()); } DepKind::MirConst => { force!(mir_const, def_id!()); } DepKind::MirValidated => { force!(mir_validated, def_id!()); } @@ -852,4 +853,3 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, true } - diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index dd5914e46ec..30a60cc7590 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -344,8 +344,8 @@ fn unsafety_violations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> debug!("unsafety_violations({:?})", def_id); // NB: this borrow is valid because all the consumers of - // `mir_const` force this. - let mir = &tcx.mir_const(def_id).borrow(); + // `mir_built` force this. + let mir = &tcx.mir_built(def_id).borrow(); let visibility_scope_info = match mir.visibility_scope_info { ClearOnDecode::Set(ref data) => data, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 322f46cf02b..ad17cc5e58f 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -50,6 +50,7 @@ pub(crate) fn provide(providers: &mut Providers) { self::check_unsafety::provide(providers); *providers = Providers { mir_keys, + mir_built, mir_const, mir_validated, optimized_mir, @@ -103,9 +104,17 @@ fn mir_keys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, krate: CrateNum) Rc::new(set) } +fn mir_built<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { + let mir = build::mir_build(tcx, def_id); + tcx.alloc_steal_mir(mir) +} + fn mir_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx Steal> { - let mut mir = build::mir_build(tcx, def_id); + // Unsafety check uses the raw mir, so make sure it is run + let _ = tcx.unsafety_violations(def_id); + let source = MirSource::from_local_def_id(tcx, def_id); + let mut mir = tcx.mir_built(def_id).steal(); transform::run_suite(tcx, source, MIR_CONST, &mut mir); tcx.alloc_steal_mir(mir) } @@ -117,7 +126,6 @@ fn mir_validated<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx // this point, before we steal the mir-const result. let _ = tcx.mir_const_qualif(def_id); } - let _ = tcx.unsafety_violations(def_id); let mut mir = tcx.mir_const(def_id).steal(); transform::run_suite(tcx, source, MIR_VALIDATED, &mut mir); diff --git a/src/test/compile-fail/issue-45087-unreachable-unsafe.rs b/src/test/compile-fail/issue-45087-unreachable-unsafe.rs new file mode 100644 index 00000000000..eeb66fa0e2c --- /dev/null +++ b/src/test/compile-fail/issue-45087-unreachable-unsafe.rs @@ -0,0 +1,15 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + return; + *(1 as *mut u32) = 42; + //~^ ERROR dereference of raw pointer requires unsafe +}