Skip to content

Commit

Permalink
Auto merge of #23361 - petrochenkov:refdst, r=jakub-
Browse files Browse the repository at this point in the history
After this patch code like `let ref a = *"abcdef"` doesn't cause ICE anymore.
Required for #23121

There are still places in rustc_trans where pointers are always assumed to be thin. In particular, #19064 is not resolved by this patch.
  • Loading branch information
bors committed Mar 22, 2015
2 parents ecf8c64 + a5eefde commit b0aad7d
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 7 deletions.
24 changes: 17 additions & 7 deletions src/librustc_trans/trans/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ pub enum OptResult<'blk, 'tcx: 'blk> {
LowerBound(Result<'blk, 'tcx>)
}

#[derive(Clone, Copy)]
#[derive(Clone, Copy, PartialEq)]
pub enum TransBindingMode {
TrByCopy(/* llbinding */ ValueRef),
TrByMove,
Expand Down Expand Up @@ -1017,9 +1017,14 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
None => {
let data = &m[0].data;
for &(ref ident, ref value_ptr) in &m[0].bound_ptrs {
let llmatch = data.bindings_map[*ident].llmatch;
call_lifetime_start(bcx, llmatch);
Store(bcx, *value_ptr, llmatch);
let binfo = data.bindings_map[*ident];
call_lifetime_start(bcx, binfo.llmatch);
if binfo.trmode == TrByRef && type_is_fat_ptr(bcx.tcx(), binfo.ty) {
expr::copy_fat_ptr(bcx, *value_ptr, binfo.llmatch);
}
else {
Store(bcx, *value_ptr, binfo.llmatch);
}
}
match data.arm.guard {
Some(ref guard_expr) => {
Expand Down Expand Up @@ -1087,7 +1092,6 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
_ => None
}
};

match adt_vals {
Some(field_vals) => {
let pats = enter_match(bcx, dm, m, col, val, |pats|
Expand Down Expand Up @@ -1694,8 +1698,14 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,

ast::BindByRef(_) => {
// By ref binding: the value of the variable
// is the pointer `val` itself.
Store(bcx, val, llval);
// is the pointer `val` itself or fat pointer referenced by `val`
if type_is_fat_ptr(bcx.tcx(), ty) {
expr::copy_fat_ptr(bcx, val, llval);
}
else {
Store(bcx, val, llval);
}

bcx
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/librustc_trans/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ pub fn get_dataptr(bcx: Block, fat_ptr: ValueRef) -> ValueRef {
GEPi(bcx, fat_ptr, &[0, abi::FAT_PTR_ADDR])
}

pub fn copy_fat_ptr(bcx: Block, src_ptr: ValueRef, dst_ptr: ValueRef) {
Store(bcx, Load(bcx, get_dataptr(bcx, src_ptr)), get_dataptr(bcx, dst_ptr));
Store(bcx, Load(bcx, get_len(bcx, src_ptr)), get_len(bcx, dst_ptr));
}

// Retrieve the information we are losing (making dynamic) in an unsizing
// adjustment.
//
Expand Down
20 changes: 20 additions & 0 deletions src/test/run-pass/match-ref-unsized.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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.

// Binding unsized expressions to ref patterns

pub fn main() {
let ref a = *"abcdef";
assert_eq!(a, "abcdef");

match *"12345" {
ref b => { assert_eq!(b, "12345") }
}
}

0 comments on commit b0aad7d

Please sign in to comment.