From a5eefdef3c6123ec4217d0f21ff78bffe9c5ccbd Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 15 Mar 2015 19:16:04 +0300 Subject: [PATCH] Fix binding unsized expressions to ref patterns --- src/librustc_trans/trans/_match.rs | 24 +++++++++++++++++------- src/librustc_trans/trans/expr.rs | 5 +++++ src/test/run-pass/match-ref-unsized.rs | 20 ++++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) create mode 100644 src/test/run-pass/match-ref-unsized.rs diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 2ab6f5b0f95..4816c7207e5 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -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, @@ -1000,9 +1000,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) => { @@ -1070,7 +1075,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| @@ -1677,8 +1681,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 } } diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index ecdc7c06bb1..9c5af9429cb 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -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. // When making a dtor, we need to do different things depending on the diff --git a/src/test/run-pass/match-ref-unsized.rs b/src/test/run-pass/match-ref-unsized.rs new file mode 100644 index 00000000000..4de028299df --- /dev/null +++ b/src/test/run-pass/match-ref-unsized.rs @@ -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 or the MIT license +// , 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") } + } +} -- GitLab