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:
bors 2017-01-08 15:51:49 +00:00
commit d2c795932b
3 changed files with 40 additions and 13 deletions

View File

@ -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;
}

View File

@ -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);
}
}

View 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);
}