Skip to content

Commit d1f117d

Browse files
committed
rustc_mir: allow promotion of promotable temps indexed at runtime.
1 parent 22275f4 commit d1f117d

File tree

4 files changed

+42
-10
lines changed

4 files changed

+42
-10
lines changed

src/librustc_mir/transform/qualify_consts.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -229,12 +229,12 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
229229
}
230230

231231
/// Check if a Local with the current qualifications is promotable.
232-
fn can_promote(&mut self) -> bool {
232+
fn can_promote(&self, qualif: Qualif) -> bool {
233233
// References to statics are allowed, but only in other statics.
234234
if self.mode == Mode::Static || self.mode == Mode::StaticMut {
235-
(self.qualif - Qualif::STATIC_REF).is_empty()
235+
(qualif - Qualif::STATIC_REF).is_empty()
236236
} else {
237-
self.qualif.is_empty()
237+
qualif.is_empty()
238238
}
239239
}
240240

@@ -746,10 +746,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
746746

747747
if forbidden_mut {
748748
self.add(Qualif::NOT_CONST);
749-
} else if self.can_promote() {
749+
} else {
750750
// We might have a candidate for promotion.
751751
let candidate = Candidate::Ref(location);
752-
// We can only promote interior borrows of non-drop temps.
752+
// We can only promote interior borrows of promotable temps.
753753
let mut place = place;
754754
while let Place::Projection(ref proj) = *place {
755755
if proj.elem == ProjectionElem::Deref {
@@ -760,7 +760,12 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
760760
if let Place::Local(local) = *place {
761761
if self.mir.local_kind(local) == LocalKind::Temp {
762762
if let Some(qualif) = self.temp_qualif[local] {
763-
if !qualif.intersects(Qualif::NEEDS_DROP) {
763+
// `forbidden_mut` is false, so we can safely ignore
764+
// `MUTABLE_INTERIOR` from the local's qualifications.
765+
// This allows borrowing fields which don't have
766+
// `MUTABLE_INTERIOR`, from a type that does, e.g.:
767+
// `let _: &'static _ = &(Cell::new(1), 2).1;`
768+
if self.can_promote(qualif - Qualif::MUTABLE_INTERIOR) {
764769
self.promotion_candidates.push(candidate);
765770
}
766771
}
@@ -920,7 +925,7 @@ This does not pose a problem by itself because they can't be accessed directly."
920925
}
921926
let candidate = Candidate::Argument { bb, index: i };
922927
if is_shuffle && i == 2 {
923-
if this.can_promote() {
928+
if this.can_promote(this.qualif) {
924929
this.promotion_candidates.push(candidate);
925930
} else {
926931
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."
936941
if !constant_arguments.contains(&i) {
937942
return
938943
}
939-
if this.can_promote() {
944+
if this.can_promote(this.qualif) {
940945
this.promotion_candidates.push(candidate);
941946
} else {
942947
this.tcx.sess.span_err(this.span,

src/test/mir-opt/match_false_edges.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ fn main() {
8888
// }
8989
// bb9: { // binding1 and guard
9090
// StorageLive(_5);
91-
// _5 = &((_2 as Some).0: i32);
91+
// _11 = promoted[0];
92+
// _5 = &(((*_11) as Some).0: i32);
9293
// StorageLive(_8);
9394
// _8 = const guard() -> [return: bb10, unwind: bb1];
9495
// }

src/test/run-pass/issue-49955-2.rs

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// compile-flags: -Z borrowck=mir
12+
13+
use std::cell::Cell;
14+
15+
#[inline(never)]
16+
fn tuple_field() -> &'static u32 {
17+
// This test is MIR-borrowck-only because the old borrowck
18+
// doesn't agree that borrows of "frozen" (i.e. without any
19+
// interior mutability) fields of non-frozen temporaries,
20+
// should be promoted, while MIR promotion does promote them.
21+
&(Cell::new(5), 42).1
22+
}
23+
24+
fn main() {
25+
assert_eq!(tuple_field().to_string(), "42");
26+
}

src/test/run-pass/issue-49955.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ fn tuple_field() -> &'static u32 {
2626

2727
fn main() {
2828
assert_eq!(tuple_field().to_string(), "42");
29-
// assert_eq!(array(0).to_string(), "1");
29+
assert_eq!(array(0).to_string(), "1");
3030
}

0 commit comments

Comments
 (0)