Remove ty_open and treat Unsized lvalues as *Unsized.

This commit is contained in:
Eduard Burtescu 2015-02-17 20:27:01 +02:00
parent 2890508d97
commit 7a8a5172a5
25 changed files with 159 additions and 303 deletions

View File

@ -153,9 +153,6 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
ty::ty_err => {
mywrite!(w, "e");
}
ty::ty_open(_) => {
cx.diag.handler().bug("unexpected type in enc_sty (ty_open)");
}
}
let end = w.tell().unwrap();

View File

@ -93,7 +93,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
None
}
}
ty::ty_open(_) | ty::ty_infer(_) | ty::ty_err => None,
ty::ty_infer(_) | ty::ty_err => None,
}
}

View File

@ -135,7 +135,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
t
}
ty::ty_open(..) |
ty::ty_bool |
ty::ty_char |
ty::ty_int(..) |

View File

@ -194,7 +194,6 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
ty::ty_closure(..) |
ty::ty_infer(..) |
ty::ty_open(..) |
ty::ty_err => {
tcx.sess.bug(
&format!("ty_is_local invoked on unexpected type: {}",

View File

@ -1626,25 +1626,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(AmbiguousBuiltin)
}
ty::ty_open(ty) => {
// these only crop up in trans, and represent an
// "opened" unsized/existential type (one that has
// been dereferenced)
match bound {
ty::BoundCopy => {
Ok(If(vec!(ty)))
}
ty::BoundSized => {
Err(Unimplemented)
}
ty::BoundSync |
ty::BoundSend => {
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
}
}
}
ty::ty_err => {
Ok(If(Vec::new()))
}

View File

@ -930,7 +930,7 @@ impl<'tcx> ctxt<'tcx> {
sty_debug_print!(
self,
ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_trait,
ty_struct, ty_closure, ty_tup, ty_param, ty_open, ty_infer, ty_projection);
ty_struct, ty_closure, ty_tup, ty_param, ty_infer, ty_projection);
println!("Substs interner: #{}", self.substs_interner.borrow().len());
println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
@ -1374,12 +1374,6 @@ pub enum sty<'tcx> {
ty_projection(ProjectionTy<'tcx>),
ty_param(ParamTy), // type parameter
ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value
// and its size. Only ever used in trans. It is not necessary
// earlier since we don't need to distinguish a DST with its
// size (e.g., in a deref) vs a DST with the size elsewhere (
// e.g., in a field).
ty_infer(InferTy), // something used only during inference/typeck
ty_err, // Also only used during inference/typeck, to represent
// the type of an erroneous expression (helps cut down
@ -2689,7 +2683,7 @@ impl FlagComputation {
self.add_bounds(bounds);
}
&ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
&ty_uniq(tt) | &ty_vec(tt, _) => {
self.add_ty(tt)
}
@ -2964,8 +2958,6 @@ pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'t
mk_param(cx, def.space, def.index, def.name)
}
pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) }
impl<'tcx> TyS<'tcx> {
/// Iterator that walks `self` and any types reachable from
/// `self`, in depth-first order. Note that just walks the types
@ -3164,7 +3156,6 @@ pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.sty {
ty_vec(ty, _) => ty,
ty_str => mk_mach_uint(cx, ast::TyU8),
ty_open(ty) => sequence_element_type(cx, ty),
_ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
ty_to_string(cx, ty))),
}
@ -3583,12 +3574,6 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
TC::All
}
ty_open(ty) => {
let result = tc_ty(cx, ty, cache);
assert!(!result.is_sized(cx));
result.unsafe_pointer() | TC::Nonsized
}
ty_infer(_) |
ty_err => {
cx.sess.bug("asked to compute contents of error type");
@ -3747,7 +3732,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
ty_vec(_, None) => {
false
}
ty_uniq(typ) | ty_open(typ) => {
ty_uniq(typ) => {
type_requires(cx, seen, r_ty, typ)
}
ty_rptr(_, ref mt) => {
@ -4106,14 +4091,6 @@ pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
}
}
pub fn close_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.sty {
ty_open(ty) => mk_rptr(cx, cx.mk_region(ReStatic), mt {ty: ty, mutbl:ast::MutImmutable}),
_ => cx.sess.bug(&format!("Trying to close a non-open type {}",
ty_to_string(cx, ty)))
}
}
pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.sty {
ty_uniq(ty) => ty,
@ -4122,14 +4099,6 @@ pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
}
}
// Extract the unsized type in an open type (or just return ty if it is not open).
pub fn unopen_type<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.sty {
ty_open(ty) => ty,
_ => ty
}
}
// Returns the type of ty[i]
pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
match ty.sty {
@ -4802,7 +4771,6 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
}
}
ty_err => "type error".to_string(),
ty_open(_) => "opened DST".to_string(),
}
}
@ -6328,16 +6296,15 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
hash!(p.idx);
hash!(token::get_name(p.name));
}
ty_open(_) => byte!(22),
ty_infer(_) => unreachable!(),
ty_err => byte!(23),
ty_err => byte!(21),
ty_closure(d, r, _) => {
byte!(24);
byte!(22);
did(state, d);
region(state, *r);
}
ty_projection(ref data) => {
byte!(25);
byte!(23);
did(state, data.trait_ref.def_id);
hash!(token::get_name(data.item_name));
}
@ -6666,7 +6633,6 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
ty_projection(_) |
ty_param(_) |
ty_infer(_) |
ty_open(_) |
ty_err => {
}
}

View File

@ -626,9 +626,6 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
ty::ty_vec(typ, sz) => {
ty::ty_vec(typ.fold_with(this), sz)
}
ty::ty_open(typ) => {
ty::ty_open(typ.fold_with(this))
}
ty::ty_enum(tid, ref substs) => {
let substs = substs.fold_with(this);
ty::ty_enum(tid, this.tcx().mk_substs(substs))

View File

@ -28,7 +28,7 @@ impl<'tcx> TypeWalker<'tcx> {
ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => {
}
ty::ty_uniq(ty) | ty::ty_vec(ty, _) | ty::ty_open(ty) => {
ty::ty_uniq(ty) | ty::ty_vec(ty, _) => {
self.stack.push(ty);
}
ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {

View File

@ -20,7 +20,7 @@ use middle::ty::{ReSkolemized, ReVar, BrEnv};
use middle::ty::{mt, Ty, ParamTy};
use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum};
use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn};
use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup};
use middle::ty::{ty_closure};
use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
use middle::ty;
@ -369,8 +369,6 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
buf.push_str(&mt_to_string(cx, tm));
buf
}
ty_open(typ) =>
format!("opened<{}>", ty_to_string(cx, typ)),
ty_tup(ref elems) => {
let strs = elems
.iter()

View File

@ -678,7 +678,7 @@ fn bind_subslice_pat(bcx: Block,
}
fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
left_ty: Ty,
left_ty: Ty<'tcx>,
before: uint,
after: uint,
val: ValueRef)

View File

@ -699,7 +699,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty))
.map(|&ty| type_of::sizing_type_of(cx, ty)).collect()
} else {
st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect()
st.fields.iter().map(|&ty| type_of::in_memory_type_of(cx, ty)).collect()
}
}

View File

@ -676,8 +676,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
let val = if common::type_is_sized(cx.tcx(), field_ty) {
llfld_a
} else {
let boxed_ty = ty::mk_open(cx.tcx(), field_ty);
let scratch = datum::rvalue_scratch_datum(cx, boxed_ty, "__fat_ptr_iter");
let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter");
Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
scratch.val

View File

@ -123,13 +123,6 @@ pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
ty::type_is_sized(&param_env, DUMMY_SP, ty)
}
pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::ty_open(_) => true,
_ => type_is_sized(cx, ty),
}
}
pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::ty_ptr(ty::mt{ty, ..}) |
@ -211,10 +204,15 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<
}
}
pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
ty: Ty<'tcx>)
-> bool {
ty::type_contents(cx, ty).needs_drop(cx)
pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
// Unsized types cannot be dropped automatically - these are lvalues pointing
// to alloca's containing the actual data pointer (and the unsizing info),
// which only be obtained by dereferencing a pointer from which moves are
// not allowed. Datum & friends could possibly be adjusted to avoid getting
// this far - maybe the (*data, info) aggregate could be an SSA value?
// Lvalues don't have to be pointers, just behave like a pointer, but there
// is no telling what other implicit assumptions are lurking around.
ty::type_contents(cx, ty).needs_drop(cx) && type_is_sized(cx, ty)
}
fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {

View File

@ -146,8 +146,8 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
(const_deref_ptr(cx, v), mt.ty)
} else {
// Derefing a fat pointer does not change the representation,
// just the type to ty_open.
(v, ty::mk_open(cx.tcx(), mt.ty))
// just the type to the unsized contents.
(v, mt.ty)
}
}
None => {
@ -290,15 +290,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// an optimisation, it is necessary for mutable vectors to
// work properly.
ty = match ty::deref(ty, true) {
Some(mt) => {
if type_is_sized(cx.tcx(), mt.ty) {
mt.ty
} else {
// Derefing a fat pointer does not change the representation,
// just the type to ty_open.
ty::mk_open(cx.tcx(), mt.ty)
}
}
Some(mt) => mt.ty,
None => {
cx.sess().bug(&format!("unexpected dereferenceable type {}",
ty_to_string(cx.tcx(), ty)))
@ -319,11 +311,12 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
llconst = addr_of(cx, llconst, "autoref", e.id);
}
Some(box ty::AutoUnsize(ref k)) => {
let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
let info = expr::unsized_info(cx, k, e.id, ty, param_substs,
|t| ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), t));
let base = ptrcast(llconst, type_of::type_of(cx, unsized_ty).ptr_to());
let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
let base = ptrcast(llconst, ptr_ty);
let prev_const = cx.const_unsized().borrow_mut()
.insert(base, llconst);
assert!(prev_const.is_none() || prev_const == Some(llconst));
@ -477,16 +470,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
};
let (arr, len) = match bt.sty {
ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
ty::ty_open(ty) => match ty.sty {
ty::ty_vec(_, None) | ty::ty_str => {
let e1 = const_get_elt(cx, bv, &[0]);
(const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
},
_ => cx.sess().span_bug(base.span,
&format!("index-expr base must be a vector \
or string type, found {}",
ty_to_string(cx.tcx(), bt)))
},
ty::ty_vec(_, None) | ty::ty_str => {
let e1 = const_get_elt(cx, bv, &[0]);
(const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
}
ty::ty_rptr(_, mt) => match mt.ty.sty {
ty::ty_vec(_, Some(u)) => {
(const_deref_ptr(cx, bv), C_uint(cx, u))

View File

@ -492,8 +492,6 @@ impl<'tcx> Datum<'tcx, Expr> {
-> DatumBlock<'blk, 'tcx, Lvalue> {
debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx()));
assert!(lltype_is_sized(bcx.tcx(), self.ty),
"Trying to convert unsized value to lval");
self.match_kind(
|l| DatumBlock::new(bcx, l),
|r| {
@ -549,15 +547,10 @@ impl<'tcx> Datum<'tcx, Lvalue> {
-> Datum<'tcx, Lvalue> where
F: FnOnce(ValueRef) -> ValueRef,
{
let val = match self.ty.sty {
_ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val),
ty::ty_open(_) => {
let base = Load(bcx, expr::get_dataptr(bcx, self.val));
gep(base)
}
_ => bcx.tcx().sess.bug(
&format!("Unexpected unsized type in get_element: {}",
bcx.ty_to_string(self.ty)))
let val = if type_is_sized(bcx.tcx(), self.ty) {
gep(self.val)
} else {
gep(Load(bcx, expr::get_dataptr(bcx, self.val)))
};
Datum {
val: val,
@ -566,7 +559,8 @@ impl<'tcx> Datum<'tcx, Lvalue> {
}
}
pub fn get_vec_base_and_len(&self, bcx: Block) -> (ValueRef, ValueRef) {
pub fn get_vec_base_and_len<'blk>(&self, bcx: Block<'blk, 'tcx>)
-> (ValueRef, ValueRef) {
//! Converts a vector into the slice pair.
tvec::get_base_and_len(bcx, self.val, self.ty)

View File

@ -3828,7 +3828,6 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
ty::ty_err |
ty::ty_infer(_) |
ty::ty_open(_) |
ty::ty_projection(..) |
ty::ty_param(_) => {
cx.sess().bug(&format!("debuginfo: Trying to create type name for \

View File

@ -451,8 +451,6 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let datum_ty = datum.ty;
let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span);
debug!("unsized_ty={}", unsized_ty.repr(bcx.tcx()));
let dest_ty = ty::mk_open(tcx, unsized_ty);
debug!("dest_ty={}", unsized_ty.repr(bcx.tcx()));
let info = unsized_info(bcx.ccx(), k, expr.id, datum_ty, bcx.fcx.param_substs,
|t| ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), t));
@ -462,16 +460,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id));
// Compute the base pointer. This doesn't change the pointer value,
// but merely its type.
let base = match *k {
ty::UnsizeStruct(..) | ty::UnsizeVtable(..) => {
PointerCast(bcx, lval.val, type_of::type_of(bcx.ccx(), unsized_ty).ptr_to())
}
ty::UnsizeLength(..) => {
GEPi(bcx, lval.val, &[0, 0])
}
};
let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), unsized_ty).ptr_to();
let base = PointerCast(bcx, lval.val, ptr_ty);
let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
let scratch = rvalue_scratch_datum(bcx, unsized_ty, "__fat_ptr");
Store(bcx, base, get_dataptr(bcx, scratch.val));
Store(bcx, info, get_len(bcx, scratch.val));
@ -711,7 +703,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("trans_rec_field");
let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
let bare_ty = ty::unopen_type(base_datum.ty);
let bare_ty = base_datum.ty;
let repr = adt::represent_type(bcx.ccx(), bare_ty);
with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| {
let ix = get_idx(bcx.tcx(), field_tys);
@ -723,7 +715,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
if type_is_sized(bcx.tcx(), d.ty) {
DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
} else {
let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), "");
let scratch = rvalue_scratch_datum(bcx, d.ty, "");
Store(bcx, d.val, get_dataptr(bcx, scratch.val));
let info = Load(bcx, get_len(bcx, base_datum.val));
Store(bcx, info, get_len(bcx, scratch.val));
@ -809,7 +801,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
if type_is_sized(bcx.tcx(), elt_ty) {
Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr)
} else {
Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr)
Datum::new(datum.val, elt_ty, LvalueExpr)
}
}
None => {
@ -1671,7 +1663,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
lval: Datum<'tcx, Lvalue>)
-> DatumBlock<'blk, 'tcx, Expr> {
let dest_ty = ty::close_type(bcx.tcx(), lval.ty);
let dest_ty = ty::mk_imm_rptr(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), lval.ty);
let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
memcpy_ty(bcx, scratch.val, lval.val, scratch.ty);
@ -1685,16 +1677,13 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("trans_addr_of");
let mut bcx = bcx;
let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of"));
match sub_datum.ty.sty {
ty::ty_open(_) => {
// Opened DST value, close to a fat pointer
ref_fat_ptr(bcx, sub_datum)
}
_ => {
// Sized value, ref to a thin pointer
let ty = expr_ty(bcx, expr);
immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
}
if !type_is_sized(bcx.tcx(), sub_datum.ty) {
// DST lvalue, close to a fat pointer
ref_fat_ptr(bcx, sub_datum)
} else {
// Sized value, ref to a thin pointer
let ty = expr_ty(bcx, expr);
immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
}
}
@ -2234,16 +2223,15 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
if type_is_sized(bcx.tcx(), content_ty) {
deref_owned_pointer(bcx, expr, datum, content_ty)
} else {
// A fat pointer and an opened DST value have the same
// representation just different types. Since there is no
// temporary for `*e` here (because it is unsized), we cannot
// emulate the sized object code path for running drop glue and
// free. Instead, we schedule cleanup for `e`, turning it into
// an lvalue.
// A fat pointer and a DST lvalue have the same representation
// just different types. Since there is no temporary for `*e`
// here (because it is unsized), we cannot emulate the sized
// object code path for running drop glue and free. Instead,
// we schedule cleanup for `e`, turning it into an lvalue.
let datum = unpack_datum!(
bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
let datum = Datum::new(datum.val, ty::mk_open(bcx.tcx(), content_ty), LvalueExpr);
let datum = Datum::new(datum.val, content_ty, LvalueExpr);
DatumBlock::new(bcx, datum)
}
}
@ -2260,11 +2248,9 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// owner (or, in the case of *T, by the user).
DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
} else {
// A fat pointer and an opened DST value have the same representation
// A fat pointer and a DST lvalue have the same representation
// just different types.
DatumBlock::new(bcx, Datum::new(datum.val,
ty::mk_open(bcx.tcx(), content_ty),
LvalueExpr))
DatumBlock::new(bcx, Datum::new(datum.val, content_ty, LvalueExpr))
}
}

View File

@ -34,7 +34,7 @@ use trans::expr;
use trans::machine::*;
use trans::tvec;
use trans::type_::Type;
use trans::type_of::{type_of, sizing_type_of, align_of};
use trans::type_of::{self, type_of, sizing_type_of, align_of};
use middle::ty::{self, Ty};
use util::ppaux::{ty_to_short_str, Repr};
use util::ppaux;
@ -265,8 +265,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
assert_eq!(params.len(), 1);
let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) {
// The dtor expects a fat pointer, so make one, even if we have to fake it.
let boxed_ty = ty::mk_open(bcx.tcx(), t);
let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self");
let scratch = datum::rvalue_scratch_datum(bcx, t, "__fat_ptr_drop_self");
Store(bcx, value, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
Store(bcx,
// If we just had a thin pointer, make a fat pointer by sticking
@ -284,20 +283,18 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// Add all the fields as a value which needs to be cleaned at the end of
// this scope. Iterate in reverse order so a Drop impl doesn't reverse
// the order in which fields get dropped.
for (i, ty) in st.fields.iter().enumerate().rev() {
for (i, &ty) in st.fields.iter().enumerate().rev() {
let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false);
let val = if type_is_sized(bcx.tcx(), *ty) {
let val = if type_is_sized(bcx.tcx(), ty) {
llfld_a
} else {
let boxed_ty = ty::mk_open(bcx.tcx(), *ty);
let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_field");
let scratch = datum::rvalue_scratch_datum(bcx, ty, "__fat_ptr_drop_field");
Store(bcx, llfld_a, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
Store(bcx, info.unwrap(), GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
scratch.val
};
variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
val, *ty);
variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), val, ty);
}
let dtor_ty = ty::mk_ctor_fn(bcx.tcx(),
@ -502,7 +499,10 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
// tydescs.
assert!(!ccx.finished_tydescs().get());
let llty = type_of(ccx, t);
// This really shouldn't be like this, size/align will be wrong for
// unsized types (i.e. [T] will have the size/align of T).
// But we need it until we split this out into a "type name" intrinsic.
let llty = type_of::in_memory_type_of(ccx, t);
if ccx.sess().count_type_sizes() {
println!("{}\t{}", llsize_of_real(ccx, llty),

View File

@ -372,38 +372,31 @@ pub fn get_fixed_base_and_len(bcx: Block,
(base, len)
}
fn get_slice_base_and_len(bcx: Block,
llval: ValueRef)
-> (ValueRef, ValueRef) {
let base = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR]));
let len = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA]));
(base, len)
}
/// Converts a vector into the slice pair. The vector should be stored in `llval` which should be
/// by-reference. If you have a datum, you would probably prefer to call
/// `Datum::get_base_and_len()` which will handle any conversions for you.
pub fn get_base_and_len(bcx: Block,
llval: ValueRef,
vec_ty: Ty)
-> (ValueRef, ValueRef) {
pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
llval: ValueRef,
vec_ty: Ty<'tcx>)
-> (ValueRef, ValueRef) {
let ccx = bcx.ccx();
match vec_ty.sty {
ty::ty_vec(_, Some(n)) => get_fixed_base_and_len(bcx, llval, n),
ty::ty_open(ty) => match ty.sty {
ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
_ => ccx.sess().bug("unexpected type in get_base_and_len")
},
ty::ty_vec(_, None) | ty::ty_str => {
let base = Load(bcx, expr::get_dataptr(bcx, llval));
let len = Load(bcx, expr::get_len(bcx, llval));
(base, len)
}
// Only used for pattern matching.
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty {
ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
ty::ty_vec(_, Some(n)) => {
let base = GEPi(bcx, Load(bcx, llval), &[0, 0]);
(base, C_uint(ccx, n))
}
_ => ccx.sess().bug("unexpected type in get_base_and_len"),
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
let inner = if type_is_sized(bcx.tcx(), ty) {
Load(bcx, llval)
} else {
llval
};
get_base_and_len(bcx, inner, ty)
},
_ => ccx.sess().bug("unexpected type in get_base_and_len"),
}

View File

@ -232,14 +232,6 @@ impl Type {
Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to()
}
pub fn opaque_trait(ccx: &CrateContext) -> Type {
Type::struct_(ccx, &[Type::opaque_trait_data(ccx).ptr_to(), Type::vtable_ptr(ccx)], false)
}
pub fn opaque_trait_data(ccx: &CrateContext) -> Type {
Type::i8(ccx)
}
pub fn kind(&self) -> TypeKind {
unsafe {
llvm::LLVMGetTypeKind(self.to_ref())

View File

@ -10,8 +10,6 @@
#![allow(non_camel_case_types)]
pub use self::named_ty::*;
use middle::subst;
use trans::adt;
use trans::common::*;
@ -183,9 +181,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
}
let llsizingty = match t.sty {
_ if !lltype_is_sized(cx.tcx(), t) => {
cx.sess().bug(&format!("trying to take the sizing type of {}, an unsized type",
ppaux::ty_to_string(cx.tcx(), t)))
_ if !type_is_sized(cx.tcx(), t) => {
Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
}
ty::ty_bool => Type::bool(cx),
@ -232,15 +229,11 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
}
}
ty::ty_open(_) => {
Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
}
ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
cx.sess().bug(&format!("fictitious type {} in sizing_type_of()",
ppaux::ty_to_string(cx.tcx(), t)))
}
ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => panic!("unreachable")
ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => unreachable!()
};
cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
@ -270,25 +263,37 @@ pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
}
}
// NB: If you update this, be sure to update `sizing_type_of()` as well.
pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// It is possible to end up here with a sized type. This happens with a
// struct which might be unsized, but is monomorphised to a sized type.
// In this case we'll fake a fat pointer with no unsize info (we use 0).
// However, its still a fat pointer, so we need some type use.
if type_is_sized(cx.tcx(), t) {
return Type::i8p(cx);
}
match unsized_part_of_type(cx.tcx(), t).sty {
ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyUs(false)),
ty::ty_trait(_) => Type::vtable_ptr(cx),
_ => panic!("Unexpected type returned from unsized_part_of_type : {}",
t.repr(cx.tcx()))
}
}
/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
/// This is the right LLVM type for an alloca containg a value of that type,
/// and the pointee of an Lvalue Datum (which is always a LLVM pointer).
/// For unsized types, the returned type is a fat pointer, thus the resulting
/// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double
/// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.
/// This is needed due to the treatment of immediate values, as a fat pointer
/// is too large for it to be placed in SSA value (by our rules).
/// For the raw type without far pointer indirection, see `in_memory_type_of`.
pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
let ty = if !type_is_sized(cx.tcx(), ty) {
ty::mk_imm_ptr(cx.tcx(), ty)
} else {
ty
};
in_memory_type_of(cx, ty)
}
/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
/// This is the right LLVM type for a field/array element of that type,
/// and is the same as `type_of` for all Sized types.
/// Unsized types, however, are represented by a "minimal unit", e.g.
/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
/// If the type is an unsized struct, the regular layout is generated,
/// with the inner-most trailing unsized field using the "minimal unit"
/// of that field's type - this is useful for taking the address of
/// that field and ensuring the struct has the right alignment.
/// For the LLVM type of a value as a whole, see `type_of`.
/// NB: If you update this, be sure to update `sizing_type_of()` as well.
pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// Check the cache.
match cx.lltypes().borrow().get(&t) {
Some(&llty) => return llty,
@ -307,7 +312,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
let t_norm = erase_regions(cx.tcx(), &t);
if t != t_norm {
let llty = type_of(cx, t_norm);
let llty = in_memory_type_of(cx, t_norm);
debug!("--> normalized {} {:?} to {} {:?} llty={}",
t.repr(cx.tcx()),
t,
@ -331,10 +336,10 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// of the enum's variants refers to the enum itself.
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, an_enum, did, tps);
let name = llvm_type_name(cx, did, tps);
adt::incomplete_type_of(cx, &*repr, &name[..])
}
ty::ty_closure(did, _, ref substs) => {
ty::ty_closure(..) => {
// Only create the named struct, but don't fill it in. We
// fill it in *after* placing it into the type cache.
let repr = adt::represent_type(cx, t);
@ -342,41 +347,47 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// inherited from their environment, so we use entire
// contents of the VecPerParamSpace to to construct the llvm
// name
let name = llvm_type_name(cx, a_closure, did, substs.types.as_slice());
adt::incomplete_type_of(cx, &*repr, &name[..])
adt::incomplete_type_of(cx, &*repr, "closure")
}
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
match ty.sty {
ty::ty_str => {
if !type_is_sized(cx.tcx(), ty) {
if let ty::ty_str = ty.sty {
// This means we get a nicer name in the output (str is always
// unsized).
cx.tn().find_type("str_slice").unwrap()
} else {
let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
let unsized_part = unsized_part_of_type(cx.tcx(), ty);
let info_ty = match unsized_part.sty {
ty::ty_str | ty::ty_vec(..) => {
Type::uint_from_ty(cx, ast::TyUs(false))
}
ty::ty_trait(_) => Type::vtable_ptr(cx),
_ => panic!("Unexpected type returned from \
unsized_part_of_type: {} for ty={}",
unsized_part.repr(cx.tcx()), ty.repr(cx.tcx()))
};
Type::struct_(cx, &[ptr_ty, info_ty], false)
}
ty::ty_trait(..) => Type::opaque_trait(cx),
_ if !type_is_sized(cx.tcx(), ty) => {
let p_ty = type_of(cx, ty).ptr_to();
Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false)
}
_ => type_of(cx, ty).ptr_to(),
} else {
in_memory_type_of(cx, ty).ptr_to()
}
}
ty::ty_vec(ty, Some(size)) => {
let size = size as u64;
let llty = type_of(cx, ty);
let llty = in_memory_type_of(cx, ty);
ensure_array_fits_in_address_space(cx, llty, size, t);
Type::array(&llty, size)
}
ty::ty_vec(ty, None) => {
type_of(cx, ty)
}
ty::ty_trait(..) => {
Type::opaque_trait_data(cx)
}
ty::ty_str => Type::i8(cx),
// Unsized slice types (and str) have the type of their element, and
// traits have the type of u8. This is so that the data pointer inside
// fat pointers is of the right type (e.g. for array accesses), even
// when taking the address of an unsized field in a struct.
ty::ty_vec(ty, None) => in_memory_type_of(cx, ty),
ty::ty_str | ty::ty_trait(..) => Type::i8(cx),
ty::ty_bare_fn(..) => {
type_of_fn_from_ty(cx, t).ptr_to()
@ -388,7 +399,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
}
ty::ty_struct(did, ref substs) => {
if ty::type_is_simd(cx.tcx(), t) {
let llet = type_of(cx, ty::simd_type(cx.tcx(), t));
let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t));
let n = ty::simd_size(cx.tcx(), t) as u64;
ensure_array_fits_in_address_space(cx, llet, n, t);
Type::vector(&llet, n)
@ -398,29 +409,11 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// infinite recursion with recursive struct types.
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, a_struct, did, tps);
let name = llvm_type_name(cx, did, tps);
adt::incomplete_type_of(cx, &*repr, &name[..])
}
}
ty::ty_open(t) => match t.sty {
ty::ty_struct(..) => {
let p_ty = type_of(cx, t).ptr_to();
Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
}
ty::ty_vec(ty, None) => {
let p_ty = type_of(cx, ty).ptr_to();
Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
}
ty::ty_str => {
let p_ty = Type::i8p(cx);
Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
}
ty::ty_trait(..) => Type::opaque_trait(cx),
_ => cx.sess().bug(&format!("ty_open with sized type: {}",
ppaux::ty_to_string(cx.tcx(), t)))
},
ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"),
ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
@ -444,7 +437,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
_ => ()
}
return llty;
llty
}
pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
@ -453,37 +446,22 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
machine::llalign_of_min(cx, llty)
}
// Want refinements! (Or case classes, I guess
#[derive(Copy)]
pub enum named_ty {
a_struct,
an_enum,
a_closure,
}
pub fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
what: named_ty,
did: ast::DefId,
tps: &[Ty<'tcx>])
-> String {
let name = match what {
a_struct => "struct",
an_enum => "enum",
a_closure => return "closure".to_string(),
};
fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
did: ast::DefId,
tps: &[Ty<'tcx>])
-> String {
let base = ty::item_path_str(cx.tcx(), did);
let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect();
let tstr = if strings.is_empty() {
base
} else {
format!("{}<{:?}>", base, strings)
format!("{}<{}>", base, strings.connect(", "))
};
if did.krate == 0 {
format!("{}.{}", name, tstr)
tstr
} else {
format!("{}.{}[{}{}]", name, tstr, "#", did.krate)
format!("{}.{}", did.krate, tstr)
}
}

View File

@ -161,12 +161,6 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
// entering the fn check. We should do this after
// the fn check, then we can call this case a bug().
}
ty::ty_open(_) => {
self.tcx().sess.bug(
&format!("Unexpected type encountered while doing wf check: {}",
ty.repr(self.tcx())));
}
}
}

View File

@ -25,7 +25,7 @@ use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type};
use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err};
use middle::ty::{ty_param, TypeScheme, ty_ptr};
use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open};
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int};
use middle::ty::{ty_uint, ty_closure, ty_uniq, ty_bare_fn};
use middle::ty::{ty_projection};
use middle::ty;
@ -75,7 +75,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_tup(..) |
ty_param(..) | ty_err | ty_open(..) |
ty_param(..) | ty_err |
ty_ptr(_) | ty_rptr(_, _) | ty_projection(..) => {
None
}

View File

@ -849,7 +849,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_mt(generics, mt, variance);
}
ty::ty_uniq(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => {
ty::ty_uniq(typ) | ty::ty_vec(typ, _) => {
self.add_constraints_from_ty(generics, typ, variance);
}

View File

@ -1619,7 +1619,6 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
ty::ty_closure(..) => Tuple(vec![]), // FIXME(pcwalton)
ty::ty_infer(..) => panic!("ty_infer"),
ty::ty_open(..) => panic!("ty_open"),
ty::ty_err => panic!("ty_err"),
}
}