mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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.
This commit is contained in:
commit
d2c795932b
@ -97,11 +97,8 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
|
||||
// Ignore drops, if the temp gets promoted,
|
||||
// then it's constant and thus drop is noop.
|
||||
// Storage live ranges are also irrelevant.
|
||||
match context {
|
||||
LvalueContext::Drop |
|
||||
LvalueContext::StorageLive |
|
||||
LvalueContext::StorageDead => return,
|
||||
_ => {}
|
||||
if context.is_drop() || context.is_storage_marker() {
|
||||
return;
|
||||
}
|
||||
|
||||
let temp = &mut self.temps[index];
|
||||
@ -118,15 +115,17 @@ impl<'tcx> Visitor<'tcx> for TempCollector<'tcx> {
|
||||
_ => { /* mark as unpromotable below */ }
|
||||
}
|
||||
} else if let TempState::Defined { ref mut uses, .. } = *temp {
|
||||
match context {
|
||||
LvalueContext::Borrow {..} |
|
||||
LvalueContext::Consume |
|
||||
LvalueContext::Inspect => {
|
||||
*uses += 1;
|
||||
return;
|
||||
}
|
||||
_ => { /* mark as unpromotable below */ }
|
||||
// We always allow borrows, even mutable ones, as we need
|
||||
// to promote mutable borrows of some ZSTs e.g. `&mut []`.
|
||||
let allowed_use = match context {
|
||||
LvalueContext::Borrow {..} => true,
|
||||
_ => context.is_nonmutating_use()
|
||||
};
|
||||
if allowed_use {
|
||||
*uses += 1;
|
||||
return;
|
||||
}
|
||||
/* mark as unpromotable below */
|
||||
}
|
||||
*temp = TempState::Unpromotable;
|
||||
}
|
||||
|
@ -1287,6 +1287,7 @@ fn collect_neighbours<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
|
||||
|
||||
visitor.visit_mir(&mir);
|
||||
for promoted in &mir.promoted {
|
||||
visitor.mir = promoted;
|
||||
visitor.visit_mir(promoted);
|
||||
}
|
||||
}
|
||||
|
27
src/test/run-pass/issue-38074.rs
Normal file
27
src/test/run-pass/issue-38074.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// 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 <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.
|
||||
|
||||
#![feature(platform_intrinsics, repr_simd)]
|
||||
|
||||
extern "platform-intrinsic" {
|
||||
fn simd_shuffle2<T, U>(x: T, y: T, idx: [u32; 2]) -> U;
|
||||
}
|
||||
|
||||
#[repr(simd)]
|
||||
#[derive(Clone, Copy)]
|
||||
#[allow(non_camel_case_types)]
|
||||
struct u64x2(u64, u64);
|
||||
|
||||
fn main() {
|
||||
let a = u64x2(1, 2);
|
||||
let r: u64x2 = unsafe { simd_shuffle2(a, a, [0-0, 0-0]) };
|
||||
assert_eq!(r.0, 1);
|
||||
assert_eq!(r.1, 1);
|
||||
}
|
Loading…
Reference in New Issue
Block a user