Rollup merge of #33734 - luqmana:33387-mir_fat_ptr_coerce, r=arielb1
[MIR] Add PointerCast for Unsize casts of fat pointers. Fixes #33387. r? @eddyb
This commit is contained in:
commit
4913e88c00
4 changed files with 68 additions and 4 deletions
|
|
@ -617,7 +617,13 @@ pub fn coerce_unsized_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
|
|||
(&ty::TyRawPtr(..), &ty::TyRawPtr(..)) => {
|
||||
let (base, info) = if common::type_is_fat_ptr(bcx.tcx(), src_ty) {
|
||||
// fat-ptr to fat-ptr unsize preserves the vtable
|
||||
load_fat_ptr(bcx, src, src_ty)
|
||||
// i.e. &'a fmt::Debug+Send => &'a fmt::Debug
|
||||
// So we need to pointercast the base to ensure
|
||||
// the types match up.
|
||||
let (base, info) = load_fat_ptr(bcx, src, src_ty);
|
||||
let llcast_ty = type_of::fat_ptr_base_ty(bcx.ccx(), dst_ty);
|
||||
let base = PointerCast(bcx, base, llcast_ty);
|
||||
(base, info)
|
||||
} else {
|
||||
let base = load_ty(bcx, src, src_ty);
|
||||
unsize_thin_ptr(bcx, base, src_ty, dst_ty)
|
||||
|
|
|
|||
|
|
@ -262,14 +262,17 @@ impl<'bcx, 'tcx> MirContext<'bcx, 'tcx> {
|
|||
assert!(common::type_is_fat_ptr(bcx.tcx(), cast_ty));
|
||||
|
||||
match operand.val {
|
||||
OperandValue::FatPtr(..) => {
|
||||
OperandValue::FatPtr(lldata, llextra) => {
|
||||
// unsize from a fat pointer - this is a
|
||||
// "trait-object-to-supertrait" coercion, for
|
||||
// example,
|
||||
// &'a fmt::Debug+Send => &'a fmt::Debug,
|
||||
// and is a no-op at the LLVM level
|
||||
// So we need to pointercast the base to ensure
|
||||
// the types match up.
|
||||
self.set_operand_dropped(&bcx, source);
|
||||
operand.val
|
||||
let llcast_ty = type_of::fat_ptr_base_ty(bcx.ccx(), cast_ty);
|
||||
let lldata = bcx.pointercast(lldata, llcast_ty);
|
||||
OperandValue::FatPtr(lldata, llextra)
|
||||
}
|
||||
OperandValue::Immediate(lldata) => {
|
||||
// "standard" unsize
|
||||
|
|
|
|||
|
|
@ -157,6 +157,17 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
|
|||
llsizingty
|
||||
}
|
||||
|
||||
pub fn fat_ptr_base_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
|
||||
match ty.sty {
|
||||
ty::TyBox(t) |
|
||||
ty::TyRef(_, ty::TypeAndMut { ty: t, .. }) |
|
||||
ty::TyRawPtr(ty::TypeAndMut { ty: t, .. }) if !type_is_sized(ccx.tcx(), t) => {
|
||||
in_memory_type_of(ccx, t).ptr_to()
|
||||
}
|
||||
_ => bug!("expected fat ptr ty but got {:?}", ty)
|
||||
}
|
||||
}
|
||||
|
||||
fn unsized_info_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
|
||||
let unsized_part = ccx.tcx().struct_tail(ty);
|
||||
match unsized_part.sty {
|
||||
|
|
|
|||
44
src/test/run-pass/issue-33387.rs
Normal file
44
src/test/run-pass/issue-33387.rs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2016 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(rustc_attrs)]
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
trait Foo {
|
||||
fn get(&self) -> [u8; 2];
|
||||
}
|
||||
|
||||
impl Foo for [u8; 2] {
|
||||
fn get(&self) -> [u8; 2] {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
struct Bar<T: ?Sized>(T);
|
||||
|
||||
#[rustc_mir]
|
||||
fn unsize_fat_ptr<'a>(x: &'a Bar<Foo + Send + 'a>) -> &'a Bar<Foo + 'a> {
|
||||
x
|
||||
}
|
||||
|
||||
#[rustc_mir]
|
||||
fn unsize_nested_fat_ptr(x: Arc<Foo + Send>) -> Arc<Foo> {
|
||||
x
|
||||
}
|
||||
|
||||
#[rustc_mir]
|
||||
fn main() {
|
||||
let x: Box<Bar<Foo + Send>> = Box::new(Bar([1,2]));
|
||||
assert_eq!(unsize_fat_ptr(&*x).0.get(), [1, 2]);
|
||||
|
||||
let x: Arc<Foo + Send> = Arc::new([3, 4]);
|
||||
assert_eq!(unsize_nested_fat_ptr(x).get(), [3, 4]);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue