about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-12-12 11:01:12 +0000
committerbors <bors@rust-lang.org>2015-12-12 11:01:12 +0000
commite583ab628141fc750bbf3277085f4d4d6a0e207d (patch)
tree1d538edb73dbd7b6bb0a93730e32027235f2e71c
parent5e829412814a74c1459eb441faf8d963ebcd38a1 (diff)
parent93154dd29cf315d0e58e7da9888e02fd18815540 (diff)
Auto merge of #30279 - Aatch:dst-ref-binding, r=pnkfelix
We shouldn't load DSTs when recursing into the sub-pattern of `& ref ident`.

Fixes #30277
-rw-r--r--src/librustc_trans/trans/_match.rs24
-rw-r--r--src/test/run-pass/dst-irrefutable-bind.rs24
2 files changed, 44 insertions, 4 deletions
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index 0e09a15492a..0ad780fb0e4 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -1944,8 +1944,16 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         hir::PatBox(ref inner) => {
             let pat_ty = node_id_type(bcx, inner.id);
-            // Don't load DSTs, instead pass along a fat ptr
-            let val = if type_is_sized(tcx, pat_ty) {
+            // Pass along DSTs as fat pointers.
+            let val = if type_is_fat_ptr(tcx, pat_ty) {
+                // We need to check for this, as the pattern could be binding
+                // a fat pointer by-value.
+                if let hir::PatIdent(hir::BindByRef(_),_,_) = inner.node {
+                    val.val
+                } else {
+                    Load(bcx, val.val)
+                }
+            } else if type_is_sized(tcx, pat_ty) {
                 Load(bcx, val.val)
             } else {
                 val.val
@@ -1955,8 +1963,16 @@ pub fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         }
         hir::PatRegion(ref inner, _) => {
             let pat_ty = node_id_type(bcx, inner.id);
-            // Don't load DSTs, instead pass along a fat ptr
-            let val = if type_is_sized(tcx, pat_ty) {
+            // Pass along DSTs as fat pointers.
+            let val = if type_is_fat_ptr(tcx, pat_ty) {
+                // We need to check for this, as the pattern could be binding
+                // a fat pointer by-value.
+                if let hir::PatIdent(hir::BindByRef(_),_,_) = inner.node {
+                    val.val
+                } else {
+                    Load(bcx, val.val)
+                }
+            } else if type_is_sized(tcx, pat_ty) {
                 Load(bcx, val.val)
             } else {
                 val.val
diff --git a/src/test/run-pass/dst-irrefutable-bind.rs b/src/test/run-pass/dst-irrefutable-bind.rs
new file mode 100644
index 00000000000..9f8067f372a
--- /dev/null
+++ b/src/test/run-pass/dst-irrefutable-bind.rs
@@ -0,0 +1,24 @@
+// Copyright 2015 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.
+
+struct Test<T: ?Sized>(T);
+
+fn main() {
+    let x = Test([1,2,3]);
+    let x : &Test<[i32]> = &x;
+
+    let & ref _y = x;
+
+    // Make sure binding to a fat pointer behind a reference
+    // still works
+    let slice = &[1,2,3];
+    let x = Test(&slice);
+    let Test(&_slice) = x;
+}