Skip to content

Commit d2c7959

Browse files
committed
Auto merge of #38837 - eddyb:issue-38074, r=nikomatsakis
Allow projections to be promoted to constants in MIR. This employs the `LvalueContext` additions by @pcwalton to properly extend the MIR promotion of temporaries to allow projections (field accesses, indexing and dereferences) on said temporaries. It's needed both parity with the old constant qualification logic (for current borrowck) and it fixes #38074. The former is *required for soundness* if we accept the RFC for promoting rvalues to `'static` constants. That is, until we get MIR borrowck and the same source of truth will be used for both checks and codegen.
2 parents e350c44 + 8f84e95 commit d2c7959

File tree

3 files changed

+40
-13
lines changed

3 files changed

+40
-13
lines changed

src/librustc_mir/transform/promote_consts.rs

+12-13
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,8 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
9797
// Ignore drops, if the temp gets promoted,
9898
// then it's constant and thus drop is noop.
9999
// Storage live ranges are also irrelevant.
100-
match context {
101-
LvalueContext::Drop |
102-
LvalueContext::StorageLive |
103-
LvalueContext::StorageDead => return,
104-
_ => {}
100+
if context.is_drop() || context.is_storage_marker() {
101+
return;
105102
}
106103

107104
let temp = &mut self.temps[index];
@@ -118,15 +115,17 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
118115
_ => { /* mark as unpromotable below */ }
119116
}
120117
} else if let TempState::Defined { ref mut uses, .. } = *temp {
121-
match context {
122-
LvalueContext::Borrow {..} |
123-
LvalueContext::Consume |
124-
LvalueContext::Inspect => {
125-
*uses += 1;
126-
return;
127-
}
128-
_ => { /* mark as unpromotable below */ }
118+
// We always allow borrows, even mutable ones, as we need
119+
// to promote mutable borrows of some ZSTs e.g. `&mut []`.
120+
let allowed_use = match context {
121+
LvalueContext::Borrow {..} => true,
122+
_ => context.is_nonmutating_use()
123+
};
124+
if allowed_use {
125+
*uses += 1;
126+
return;
129127
}
128+
/* mark as unpromotable below */
130129
}
131130
*temp = TempState::Unpromotable;
132131
}

src/librustc_trans/collector.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1287,6 +1287,7 @@ fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
12871287

12881288
visitor.visit_mir(&mir);
12891289
for promoted in &mir.promoted {
1290+
visitor.mir = promoted;
12901291
visitor.visit_mir(promoted);
12911292
}
12921293
}

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

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright 2017 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+
#![feature(platform_intrinsics, repr_simd)]
12+
13+
extern "platform-intrinsic" {
14+
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
15+
}
16+
17+
#[repr(simd)]
18+
#[derive(Clone, Copy)]
19+
#[allow(non_camel_case_types)]
20+
struct u64x2(u64, u64);
21+
22+
fn main() {
23+
let a = u64x2(1, 2);
24+
let r: u64x2 = unsafe { simd_shuffle2(a, a, [0-0, 0-0]) };
25+
assert_eq!(r.0, 1);
26+
assert_eq!(r.1, 1);
27+
}

0 commit comments

Comments
 (0)