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 or the MIT license +// , 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(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); +}