diff options
| author | bors <bors@rust-lang.org> | 2017-01-08 15:51:49 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-01-08 15:51:49 +0000 |
| commit | d2c795932b58d910c179236d1070e04e8cb54faf (patch) | |
| tree | b6e09e957bea9b7fb87d1e467903f123e8542148 | |
| parent | e350c44e0c43d9c7981d502e27cf149287d924cb (diff) | |
| parent | 8f84e955e006dd9e116f69eaba6efbbcd2e3ca8a (diff) | |
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.
| -rw-r--r-- | src/librustc_mir/transform/promote_consts.rs | 25 | ||||
| -rw-r--r-- | src/librustc_trans/collector.rs | 1 | ||||
| -rw-r--r-- | src/test/run-pass/issue-38074.rs | 27 |
3 files changed, 40 insertions, 13 deletions
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 2a4b2b515cc..ec678339066 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -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; } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 094f293e5eb..ff8a14474e5 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -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); } } diff --git a/src/test/run-pass/issue-38074.rs b/src/test/run-pass/issue-38074.rs new file mode 100644 index 00000000000..5c9a63b8616 --- /dev/null +++ b/src/test/run-pass/issue-38074.rs @@ -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); +} |
