rollup merge of #18591 : nick29581/dst-bug-str
This commit is contained in:
commit
b747f70394
4 changed files with 44 additions and 27 deletions
|
@ -49,6 +49,7 @@ use std::num::Int;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
|
||||||
use llvm::{ValueRef, True, IntEQ, IntNE};
|
use llvm::{ValueRef, True, IntEQ, IntNE};
|
||||||
|
use back::abi::slice_elt_base;
|
||||||
use middle::subst;
|
use middle::subst;
|
||||||
use middle::subst::Subst;
|
use middle::subst::Subst;
|
||||||
use middle::trans::_match;
|
use middle::trans::_match;
|
||||||
|
@ -235,7 +236,7 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr {
|
||||||
if cases[1 - discr].is_zerolen(cx, t) {
|
if cases[1 - discr].is_zerolen(cx, t) {
|
||||||
let st = mk_struct(cx, cases[discr].tys.as_slice(),
|
let st = mk_struct(cx, cases[discr].tys.as_slice(),
|
||||||
false, t);
|
false, t);
|
||||||
match cases[discr].find_ptr() {
|
match cases[discr].find_ptr(cx) {
|
||||||
Some(ThinPointer(_)) if st.fields.len() == 1 => {
|
Some(ThinPointer(_)) if st.fields.len() == 1 => {
|
||||||
return RawNullablePointer {
|
return RawNullablePointer {
|
||||||
nndiscr: discr as Disr,
|
nndiscr: discr as Disr,
|
||||||
|
@ -290,7 +291,7 @@ struct Case {
|
||||||
#[deriving(Eq, PartialEq, Show)]
|
#[deriving(Eq, PartialEq, Show)]
|
||||||
pub enum PointerField {
|
pub enum PointerField {
|
||||||
ThinPointer(uint),
|
ThinPointer(uint),
|
||||||
FatPointer(uint, uint)
|
FatPointer(uint)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Case {
|
impl Case {
|
||||||
|
@ -298,31 +299,22 @@ impl Case {
|
||||||
mk_struct(cx, self.tys.as_slice(), false, scapegoat).size == 0
|
mk_struct(cx, self.tys.as_slice(), false, scapegoat).size == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_ptr(&self) -> Option<PointerField> {
|
fn find_ptr(&self, cx: &CrateContext) -> Option<PointerField> {
|
||||||
use back::abi::{fn_field_code, slice_elt_base, trt_field_box};
|
|
||||||
|
|
||||||
for (i, &ty) in self.tys.iter().enumerate() {
|
for (i, &ty) in self.tys.iter().enumerate() {
|
||||||
match ty::get(ty).sty {
|
match ty::get(ty).sty {
|
||||||
// &T/&mut T could either be a thin or fat pointer depending on T
|
// &T/&mut T/Box<T> could either be a thin or fat pointer depending on T
|
||||||
ty::ty_rptr(_, ty::mt { ty, .. }) => match ty::get(ty).sty {
|
ty::ty_rptr(_, ty::mt { ty, .. }) | ty::ty_uniq(ty) => match ty::get(ty).sty {
|
||||||
// &[T] and &str are a pointer and length pair
|
// &[T] and &str are a pointer and length pair
|
||||||
ty::ty_vec(_, None) | ty::ty_str => return Some(FatPointer(i, slice_elt_base)),
|
ty::ty_vec(_, None) | ty::ty_str => return Some(FatPointer(i)),
|
||||||
|
|
||||||
// &Trait/&mut Trait are a pair of pointers: the actual object and a vtable
|
// &Trait is a pair of pointers: the actual object and a vtable
|
||||||
ty::ty_trait(..) => return Some(FatPointer(i, trt_field_box)),
|
ty::ty_trait(..) => return Some(FatPointer(i)),
|
||||||
|
|
||||||
// Any other &T/&mut T is just a pointer
|
ty::ty_struct(..) if !ty::type_is_sized(cx.tcx(), ty) => {
|
||||||
_ => return Some(ThinPointer(i))
|
return Some(FatPointer(i))
|
||||||
},
|
}
|
||||||
|
|
||||||
// Box<T> could either be a thin or fat pointer depending on T
|
// Any other &T is just a pointer
|
||||||
ty::ty_uniq(t) => match ty::get(t).sty {
|
|
||||||
ty::ty_vec(_, None) => return Some(FatPointer(i, slice_elt_base)),
|
|
||||||
|
|
||||||
// Box<Trait> is a pair of pointers: the actual object and a vtable
|
|
||||||
ty::ty_trait(..) => return Some(FatPointer(i, trt_field_box)),
|
|
||||||
|
|
||||||
// Any other Box<T> is just a pointer
|
|
||||||
_ => return Some(ThinPointer(i))
|
_ => return Some(ThinPointer(i))
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -330,7 +322,7 @@ impl Case {
|
||||||
ty::ty_bare_fn(..) => return Some(ThinPointer(i)),
|
ty::ty_bare_fn(..) => return Some(ThinPointer(i)),
|
||||||
|
|
||||||
// Closures are a pair of pointers: the code and environment
|
// Closures are a pair of pointers: the code and environment
|
||||||
ty::ty_closure(..) => return Some(FatPointer(i, fn_field_code)),
|
ty::ty_closure(..) => return Some(FatPointer(i)),
|
||||||
|
|
||||||
// Anything else is not a pointer
|
// Anything else is not a pointer
|
||||||
_ => continue
|
_ => continue
|
||||||
|
@ -636,6 +628,7 @@ pub fn trans_get_discr(bcx: Block, r: &Repr, scrutinee: ValueRef, cast_to: Optio
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
let signed;
|
let signed;
|
||||||
let val;
|
let val;
|
||||||
|
debug!("trans_get_discr r: {}", r);
|
||||||
match *r {
|
match *r {
|
||||||
CEnum(ity, min, max) => {
|
CEnum(ity, min, max) => {
|
||||||
val = load_discr(bcx, ity, scrutinee, min, max);
|
val = load_discr(bcx, ity, scrutinee, min, max);
|
||||||
|
@ -671,7 +664,7 @@ fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, ptrfield: Pointer
|
||||||
scrutinee: ValueRef) -> ValueRef {
|
scrutinee: ValueRef) -> ValueRef {
|
||||||
let llptrptr = match ptrfield {
|
let llptrptr = match ptrfield {
|
||||||
ThinPointer(field) => GEPi(bcx, scrutinee, [0, field]),
|
ThinPointer(field) => GEPi(bcx, scrutinee, [0, field]),
|
||||||
FatPointer(field, pair) => GEPi(bcx, scrutinee, [0, field, pair])
|
FatPointer(field) => GEPi(bcx, scrutinee, [0, field, slice_elt_base])
|
||||||
};
|
};
|
||||||
let llptr = Load(bcx, llptrptr);
|
let llptr = Load(bcx, llptrptr);
|
||||||
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
|
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
|
||||||
|
@ -767,8 +760,8 @@ pub fn trans_set_discr(bcx: Block, r: &Repr, val: ValueRef, discr: Disr) {
|
||||||
ThinPointer(field) =>
|
ThinPointer(field) =>
|
||||||
(GEPi(bcx, val, [0, field]),
|
(GEPi(bcx, val, [0, field]),
|
||||||
type_of::type_of(bcx.ccx(), nonnull.fields[field])),
|
type_of::type_of(bcx.ccx(), nonnull.fields[field])),
|
||||||
FatPointer(field, pair) => {
|
FatPointer(field) => {
|
||||||
let v = GEPi(bcx, val, [0, field, pair]);
|
let v = GEPi(bcx, val, [0, field, slice_elt_base]);
|
||||||
(v, val_ty(v).element_type())
|
(v, val_ty(v).element_type())
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1102,7 +1095,7 @@ pub fn const_get_discrim(ccx: &CrateContext, r: &Repr, val: ValueRef)
|
||||||
StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
|
StructWrappedNullablePointer { nndiscr, ptrfield, .. } => {
|
||||||
let (idx, sub_idx) = match ptrfield {
|
let (idx, sub_idx) = match ptrfield {
|
||||||
ThinPointer(field) => (field, None),
|
ThinPointer(field) => (field, None),
|
||||||
FatPointer(field, pair) => (field, Some(pair))
|
FatPointer(field) => (field, Some(slice_elt_base))
|
||||||
};
|
};
|
||||||
if is_null(const_struct_field(ccx, val, idx, sub_idx)) {
|
if is_null(const_struct_field(ccx, val, idx, sub_idx)) {
|
||||||
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
|
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
|
||||||
|
|
|
@ -2255,7 +2255,7 @@ impl EnumMemberDescriptionFactory {
|
||||||
let null_variant_name = token::get_name((*self.variants)[null_variant_index].name);
|
let null_variant_name = token::get_name((*self.variants)[null_variant_index].name);
|
||||||
let discrfield = match ptrfield {
|
let discrfield = match ptrfield {
|
||||||
adt::ThinPointer(field) => format!("{}", field),
|
adt::ThinPointer(field) => format!("{}", field),
|
||||||
adt::FatPointer(field, pair) => format!("{}${}", field, pair)
|
adt::FatPointer(field) => format!("{}", field)
|
||||||
};
|
};
|
||||||
let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
|
let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
|
||||||
discrfield,
|
discrfield,
|
||||||
|
|
|
@ -14,6 +14,9 @@ pub const box_field_refcnt: uint = 0u;
|
||||||
pub const box_field_drop_glue: uint = 1u;
|
pub const box_field_drop_glue: uint = 1u;
|
||||||
pub const box_field_body: uint = 4u;
|
pub const box_field_body: uint = 4u;
|
||||||
|
|
||||||
|
// FIXME(18590) although we have three different layouts here, the compiler relies on
|
||||||
|
// them being the same. We should replace them with one set of constants.
|
||||||
|
|
||||||
// The two halves of a closure: code and environment.
|
// The two halves of a closure: code and environment.
|
||||||
pub const fn_field_code: uint = 0u;
|
pub const fn_field_code: uint = 0u;
|
||||||
pub const fn_field_box: uint = 1u;
|
pub const fn_field_box: uint = 1u;
|
||||||
|
|
21
src/test/run-pass/issue-18353.rs
Normal file
21
src/test/run-pass/issue-18353.rs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// Test that wrapping an unsized struct in an enum which gets optimised does
|
||||||
|
// not ICE.
|
||||||
|
|
||||||
|
struct Str {
|
||||||
|
f: [u8]
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let str: Option<&Str> = None;
|
||||||
|
str.is_some();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue