about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/transform/promote_consts.rs25
-rw-r--r--src/librustc_trans/collector.rs1
-rw-r--r--src/test/run-pass/issue-38074.rs27
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);
+}