diff options
| author | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2018-05-10 13:11:36 +0300 |
|---|---|---|
| committer | Eduard-Mihai Burtescu <edy.burt@gmail.com> | 2018-05-16 15:40:54 +0300 |
| commit | d1f117df0fd71d443742a455532e5f053f24a741 (patch) | |
| tree | dfe56fa208fde4bf95864fa9286e710ad31db66d | |
| parent | 22275f46b2b6a9efe50c5a4485ed766fce3ac10a (diff) | |
rustc_mir: allow promotion of promotable temps indexed at runtime.
| -rw-r--r-- | src/librustc_mir/transform/qualify_consts.rs | 21 | ||||
| -rw-r--r-- | src/test/mir-opt/match_false_edges.rs | 3 | ||||
| -rw-r--r-- | src/test/run-pass/issue-49955-2.rs | 26 | ||||
| -rw-r--r-- | src/test/run-pass/issue-49955.rs | 2 |
4 files changed, 42 insertions, 10 deletions
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 6f90794ed89..fd4ba1d7562 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -229,12 +229,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> { } /// Check if a Local with the current qualifications is promotable. - fn can_promote(&mut self) -> bool { + fn can_promote(&self, qualif: Qualif) -> bool { // References to statics are allowed, but only in other statics. if self.mode == Mode::Static || self.mode == Mode::StaticMut { - (self.qualif - Qualif::STATIC_REF).is_empty() + (qualif - Qualif::STATIC_REF).is_empty() } else { - self.qualif.is_empty() + qualif.is_empty() } } @@ -746,10 +746,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if forbidden_mut { self.add(Qualif::NOT_CONST); - } else if self.can_promote() { + } else { // We might have a candidate for promotion. let candidate = Candidate::Ref(location); - // We can only promote interior borrows of non-drop temps. + // We can only promote interior borrows of promotable temps. let mut place = place; while let Place::Projection(ref proj) = *place { if proj.elem == ProjectionElem::Deref { @@ -760,7 +760,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { if let Place::Local(local) = *place { if self.mir.local_kind(local) == LocalKind::Temp { if let Some(qualif) = self.temp_qualif[local] { - if !qualif.intersects(Qualif::NEEDS_DROP) { + // `forbidden_mut` is false, so we can safely ignore + // `MUTABLE_INTERIOR` from the local's qualifications. + // This allows borrowing fields which don't have + // `MUTABLE_INTERIOR`, from a type that does, e.g.: + // `let _: &'static _ = &(Cell::new(1), 2).1;` + if self.can_promote(qualif - Qualif::MUTABLE_INTERIOR) { self.promotion_candidates.push(candidate); } } @@ -920,7 +925,7 @@ This does not pose a problem by itself because they can't be accessed directly." } let candidate = Candidate::Argument { bb, index: i }; if is_shuffle && i == 2 { - if this.can_promote() { + if this.can_promote(this.qualif) { this.promotion_candidates.push(candidate); } else { span_err!(this.tcx.sess, this.span, E0526, @@ -936,7 +941,7 @@ This does not pose a problem by itself because they can't be accessed directly." if !constant_arguments.contains(&i) { return } - if this.can_promote() { + if this.can_promote(this.qualif) { this.promotion_candidates.push(candidate); } else { this.tcx.sess.span_err(this.span, diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs index a31298a0f51..c2a40399efe 100644 --- a/src/test/mir-opt/match_false_edges.rs +++ b/src/test/mir-opt/match_false_edges.rs @@ -88,7 +88,8 @@ fn main() { // } // bb9: { // binding1 and guard // StorageLive(_5); -// _5 = &((_2 as Some).0: i32); +// _11 = promoted[0]; +// _5 = &(((*_11) as Some).0: i32); // StorageLive(_8); // _8 = const guard() -> [return: bb10, unwind: bb1]; // } diff --git a/src/test/run-pass/issue-49955-2.rs b/src/test/run-pass/issue-49955-2.rs new file mode 100644 index 00000000000..17e1de95dd3 --- /dev/null +++ b/src/test/run-pass/issue-49955-2.rs @@ -0,0 +1,26 @@ +// Copyright 2018 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 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z borrowck=mir + +use std::cell::Cell; + +#[inline(never)] +fn tuple_field() -> &'static u32 { + // This test is MIR-borrowck-only because the old borrowck + // doesn't agree that borrows of "frozen" (i.e. without any + // interior mutability) fields of non-frozen temporaries, + // should be promoted, while MIR promotion does promote them. + &(Cell::new(5), 42).1 +} + +fn main() { + assert_eq!(tuple_field().to_string(), "42"); +} diff --git a/src/test/run-pass/issue-49955.rs b/src/test/run-pass/issue-49955.rs index 2d36806ef4f..57a1264aaee 100644 --- a/src/test/run-pass/issue-49955.rs +++ b/src/test/run-pass/issue-49955.rs @@ -26,5 +26,5 @@ fn tuple_field() -> &'static u32 { fn main() { assert_eq!(tuple_field().to_string(), "42"); - // assert_eq!(array(0).to_string(), "1"); + assert_eq!(array(0).to_string(), "1"); } |
