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();
None
}
}
- ty::ty_open(_) | ty::ty_infer(_) | ty::ty_err => None,
+ ty::ty_infer(_) | ty::ty_err => None,
}
}
t
}
- ty::ty_open(..) |
ty::ty_bool |
ty::ty_char |
ty::ty_int(..) |
ty::ty_closure(..) |
ty::ty_infer(..) |
- ty::ty_open(..) |
ty::ty_err => {
tcx.sess.bug(
&format!("ty_is_local invoked on unexpected type: {}",
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()))
}
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());
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
self.add_bounds(bounds);
}
- &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
+ &ty_uniq(tt) | &ty_vec(tt, _) => {
self.add_ty(tt)
}
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
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))),
}
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");
ty_vec(_, None) => {
false
}
- ty_uniq(typ) | ty_open(typ) => {
+ ty_uniq(typ) => {
type_requires(cx, seen, r_ty, typ)
}
ty_rptr(_, ref mt) => {
}
}
-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,
}
}
-// 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 {
}
}
ty_err => "type error".to_string(),
- ty_open(_) => "opened DST".to_string(),
}
}
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));
}
ty_projection(_) |
ty_param(_) |
ty_infer(_) |
- ty_open(_) |
ty_err => {
}
}
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))
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) => {
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;
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()
}
fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
- left_ty: Ty,
+ left_ty: Ty<'tcx>,
before: uint,
after: uint,
val: ValueRef)
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()
}
}
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
ty::type_is_sized(¶m_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, ..}) |
}
}
-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 {
(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 => {
// 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)))
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));
};
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))
-> 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| {
-> 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,
}
}
- 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)
}
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 \
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));
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));
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);
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));
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 => {
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);
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()
}
}
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)
}
}
// 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))
}
}
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;
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
// 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(),
// 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),
(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"),
}
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())
#![allow(non_camel_case_types)]
-pub use self::named_ty::*;
-
use middle::subst;
use trans::adt;
use trans::common::*;
}
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),
}
}
- 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);
}
}
-// 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,
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,
// 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);
// 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()
}
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)
// 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"),
_ => ()
}
- return llty;
+ llty
}
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)
}
}
// 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())));
- }
}
}
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;
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
}
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);
}
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"),
}
}