Refactores all uses of ty_vec and associated things to remove the vstore abstraction (still used for strings, for now). Pointers to vectors are stored as ty_rptr or ty_uniq wrapped around a ty_vec. There are no user-facing changes. Existing behaviour is preserved by special-casing many instances of pointers containing vectors. Hopefully with DST most of these hacks will go away. For now it is useful to leave them hanging around rather than abstracting them into a method or something.
Closes #13554.
parse_substs(&mut st, conv)
}
-fn parse_vstore<M>(st: &mut PState, conv: conv_did,
- parse_mut: |&mut PState| -> M) -> ty::Vstore<M> {
+fn parse_vstore(st: &mut PState, conv: conv_did) -> ty::Vstore {
assert_eq!(next(st), '/');
let c = peek(st);
match next(st) {
'~' => ty::VstoreUniq,
- '&' => ty::VstoreSlice(parse_region(st, conv), parse_mut(st)),
+ '&' => ty::VstoreSlice(parse_region(st, conv)),
c => st.tcx.sess.bug(format!("parse_vstore(): bad input '{}'", c))
}
}
+fn parse_size(st: &mut PState) -> Option<uint> {
+ assert_eq!(next(st), '/');
+
+ if peek(st) == '|' {
+ assert_eq!(next(st), '|');
+ None
+ } else {
+ let n = parse_uint(st);
+ assert_eq!(next(st), '|');
+ Some(n)
+ }
+}
+
fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore {
match next(st) {
'~' => ty::UniqTraitStore,
return ty::mk_rptr(st.tcx, r, mt);
}
'V' => {
- let ty = parse_ty(st, |x,y| conv(x,y));
- let v = parse_vstore(st, |x,y| conv(x,y), parse_mutability);
- return ty::mk_vec(st.tcx, ty, v);
+ let mt = parse_mt(st, |x,y| conv(x,y));
+ let sz = parse_size(st);
+ return ty::mk_vec(st.tcx, mt, sz);
}
'v' => {
- let v = parse_vstore(st, |x,y| conv(x,y), |_| ());
+ let v = parse_vstore(st, |x,y| conv(x,y));
return ty::mk_str(st.tcx, v);
}
'T' => {
assert_eq!(next(st), ']');
return ty::mk_struct(st.tcx, did, substs);
}
- c => { error!("unexpected char in type string: {}", c); fail!();}
+ c => { fail!("unexpected char in type string: {}", c);}
}
}
}
}
-pub fn enc_vstore<M>(w: &mut MemWriter, cx: &ctxt,
- v: ty::Vstore<M>,
- enc_mut: |&mut MemWriter, M|) {
+pub fn enc_vstore(w: &mut MemWriter, cx: &ctxt,
+ v: ty::Vstore,
+ enc_mut: |&mut MemWriter|) {
mywrite!(w, "/");
match v {
ty::VstoreFixed(u) => mywrite!(w, "{}|", u),
ty::VstoreUniq => mywrite!(w, "~"),
- ty::VstoreSlice(r, m) => {
+ ty::VstoreSlice(r) => {
mywrite!(w, "&");
enc_region(w, cx, r);
- enc_mut(w, m);
+ enc_mut(w);
}
}
}
enc_region(w, cx, r);
enc_mt(w, cx, mt);
}
- ty::ty_vec(ty, v) => {
+ ty::ty_vec(mt, sz) => {
mywrite!(w, "V");
- enc_ty(w, cx, ty);
- enc_vstore(w, cx, v, enc_mutability);
+ enc_mt(w, cx, mt);
+ mywrite!(w, "/");
+ match sz {
+ Some(n) => mywrite!(w, "{}|", n),
+ None => mywrite!(w, "|"),
+ }
}
ty::ty_str(v) => {
mywrite!(w, "v");
- enc_vstore(w, cx, v, |_, ()| {});
+ enc_vstore(w, cx, v, |_| {});
}
ty::ty_closure(ref f) => {
mywrite!(w, "f");
}
}
}
- ty::ty_vec(..) => {
+ ty::ty_vec(..) | ty::ty_rptr(..) => {
match *ctor {
vec(n) => Some(format!("vectors of length {}", n)),
_ => None
None => {
match ty::get(left_ty).sty {
ty::ty_bool => {
- match is_useful_specialized(cx, m, v,
- val(const_bool(true)),
- 0u, left_ty){
- not_useful => {
- is_useful_specialized(cx, m, v,
- val(const_bool(false)),
- 0u, left_ty)
+ match is_useful_specialized(cx, m, v,
+ val(const_bool(true)),
+ 0u, left_ty){
+ not_useful => {
+ is_useful_specialized(cx, m, v,
+ val(const_bool(false)),
+ 0u, left_ty)
+ }
+ ref u => (*u).clone(),
}
- ref u => (*u).clone(),
- }
}
ty::ty_enum(eid, _) => {
- for va in (*ty::enum_variants(cx.tcx, eid)).iter() {
- match is_useful_specialized(cx, m, v, variant(va.id),
- va.args.len(), left_ty) {
- not_useful => (),
- ref u => return (*u).clone(),
- }
- }
- not_useful
+ for va in (*ty::enum_variants(cx.tcx, eid)).iter() {
+ match is_useful_specialized(cx, m, v, variant(va.id),
+ va.args.len(), left_ty) {
+ not_useful => (),
+ ref u => return (*u).clone(),
+ }
+ }
+ not_useful
}
- ty::ty_vec(_, ty::VstoreFixed(n)) => {
- is_useful_specialized(cx, m, v, vec(n), n, left_ty)
+ ty::ty_vec(_, Some(n)) => {
+ is_useful_specialized(cx, m, v, vec(n), n, left_ty)
}
- ty::ty_vec(..) => {
- let max_len = m.iter().rev().fold(0, |max_len, r| {
- match r.get(0).node {
- PatVec(ref before, _, ref after) => {
- cmp::max(before.len() + after.len(), max_len)
- }
- _ => max_len
+ ty::ty_vec(..) => fail!("impossible case"),
+ ty::ty_rptr(_, ty::mt{ty: ty, ..}) | ty::ty_uniq(ty) => match ty::get(ty).sty {
+ ty::ty_vec(_, None) => {
+ let max_len = m.iter().rev().fold(0, |max_len, r| {
+ match r.get(0).node {
+ PatVec(ref before, _, ref after) => {
+ cmp::max(before.len() + after.len(), max_len)
+ }
+ _ => max_len
+ }
+ });
+ for n in iter::range(0u, max_len + 1) {
+ match is_useful_specialized(cx, m, v, vec(n), n, left_ty) {
+ not_useful => (),
+ ref u => return (*u).clone(),
+ }
+ }
+ not_useful
}
- });
- for n in iter::range(0u, max_len + 1) {
- match is_useful_specialized(cx, m, v, vec(n), n, left_ty) {
- not_useful => (),
- ref u => return (*u).clone(),
+ _ => {
+ let arity = ctor_arity(cx, &single, left_ty);
+ is_useful_specialized(cx, m, v, single, arity, left_ty)
}
- }
- not_useful
- }
+ },
_ => {
- let arity = ctor_arity(cx, &single, left_ty);
- is_useful_specialized(cx, m, v, single, arity, left_ty)
+ let arity = ctor_arity(cx, &single, left_ty);
+ is_useful_specialized(cx, m, v, single, arity, left_ty)
}
}
}
}
fn missing_ctor(cx: &MatchCheckCtxt,
- m: &matrix,
- left_ty: ty::t)
- -> Option<ctor> {
- match ty::get(left_ty).sty {
- ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(..) | ty::ty_tup(_) |
- ty::ty_struct(..) => {
- for r in m.iter() {
- if !is_wild(cx, *r.get(0)) { return None; }
- }
- return Some(single);
- }
+ m: &matrix,
+ left_ty: ty::t)
+ -> Option<ctor> {
+ return match ty::get(left_ty).sty {
+ ty::ty_box(_) | ty::ty_tup(_) |
+ ty::ty_struct(..) => check_matrix_for_wild(cx, m),
+ ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty: ty, ..}) => match ty::get(ty).sty {
+ ty::ty_vec(_, None) => ctor_for_slice(m),
+ _ => check_matrix_for_wild(cx, m),
+ },
ty::ty_enum(eid, _) => {
let mut found = Vec::new();
for r in m.iter() {
else if true_found { Some(val(const_bool(false))) }
else { Some(val(const_bool(true))) }
}
- ty::ty_vec(_, ty::VstoreFixed(n)) => {
+ ty::ty_vec(_, Some(n)) => {
let mut missing = true;
let mut wrong = false;
for r in m.iter() {
_ => None
}
}
- ty::ty_vec(..) => {
+ ty::ty_vec(..) => fail!("impossible case"),
+ _ => Some(single)
+ };
+
+ fn check_matrix_for_wild(cx: &MatchCheckCtxt, m: &matrix) -> Option<ctor> {
+ for r in m.iter() {
+ if !is_wild(cx, *r.get(0)) { return None; }
+ }
+ return Some(single);
+ }
+ // For slice and ~[T].
+ fn ctor_for_slice(m: &matrix) -> Option<ctor> {
// Find the lengths and slices of all vector patterns.
let mut vec_pat_lens = m.iter().filter_map(|r| {
match r.get(0).node {
Some(k) => Some(vec(k)),
None => None
}
- }
- _ => Some(single)
}
}
fn ctor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
- match ty::get(ty).sty {
- ty::ty_tup(ref fs) => fs.len(),
- ty::ty_box(_) | ty::ty_uniq(_) | ty::ty_rptr(..) => 1u,
- ty::ty_enum(eid, _) => {
- let id = match *ctor { variant(id) => id,
- _ => fail!("impossible case") };
- match ty::enum_variants(cx.tcx, eid).iter().find(|v| v.id == id ) {
- Some(v) => v.args.len(),
- None => fail!("impossible case")
- }
- }
- ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
- ty::ty_vec(..) => {
+ fn vec_ctor_arity(ctor: &ctor) -> uint {
match *ctor {
- vec(n) => n,
- _ => 0u
+ vec(n) => n,
+ _ => 0u
}
- }
- _ => 0u
+ }
+
+ match ty::get(ty).sty {
+ ty::ty_tup(ref fs) => fs.len(),
+ ty::ty_box(_) => 1u,
+ ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty: ty, ..}) => match ty::get(ty).sty {
+ ty::ty_vec(_, None) => vec_ctor_arity(ctor),
+ _ => 1u,
+ },
+ ty::ty_enum(eid, _) => {
+ let id = match *ctor {
+ variant(id) => id,
+ _ => fail!("impossible case")
+ };
+ match ty::enum_variants(cx.tcx, eid).iter().find(|v| v.id == id ) {
+ Some(v) => v.args.len(),
+ None => fail!("impossible case")
+ }
+ }
+ ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
+ ty::ty_vec(_, Some(_)) => vec_ctor_arity(ctor),
+ _ => 0u
}
}
n_box += 1;
}
ty::ty_uniq(_) | ty::ty_str(ty::VstoreUniq) |
- ty::ty_vec(_, ty::VstoreUniq) |
ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) |
ty::ty_closure(~ty::ClosureTy { store: ty::UniqTraitStore, .. }) => {
n_uniq += 1;
fn check_deprecated_owned_vector(cx: &Context, e: &ast::Expr) {
let t = ty::expr_ty(cx.tcx, e);
match ty::get(t).sty {
- ty::ty_vec(_, ty::VstoreUniq) => {
- cx.span_lint(DeprecatedOwnedVector, e.span,
- "use of deprecated `~[]` vector; replaced by `std::vec::Vec`")
- }
+ ty::ty_uniq(t) => match ty::get(t).sty {
+ ty::ty_vec(_, None) => {
+ cx.span_lint(DeprecatedOwnedVector, e.span,
+ "use of deprecated `~[]` vector; replaced by `std::vec::Vec`")
+ }
+ _ => {}
+ },
_ => {}
}
}
match ty::get(t).sty {
ty::ty_uniq(_) |
ty::ty_trait(~ty::TyTrait { store: ty::UniqTraitStore, .. }) |
- ty::ty_vec(_, ty::VstoreUniq) |
ty::ty_str(ty::VstoreUniq) |
ty::ty_closure(~ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
Some(deref_ptr(OwnedPtr))
let kind = ty::BorrowKind::from_mutbl(mt.mutbl);
Some(deref_ptr(BorrowedPtr(kind, r)))
}
- ty::ty_vec(_, ty::VstoreSlice(r, mutbl)) |
ty::ty_trait(~ty::TyTrait { store: ty::RegionTraitStore(r, mutbl), .. }) => {
let kind = ty::BorrowKind::from_mutbl(mutbl);
Some(deref_ptr(BorrowedPtr(kind, r)))
}
- ty::ty_str(ty::VstoreSlice(r, ())) |
+ ty::ty_str(ty::VstoreSlice(r)) |
ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(r, _), ..}) => {
Some(deref_ptr(BorrowedPtr(ty::ImmBorrow, r)))
}
Some(deref_interior(InteriorField(PositionalField(0))))
}
- ty::ty_vec(_, ty::VstoreFixed(_)) |
+ ty::ty_vec(_, Some(_)) |
ty::ty_str(ty::VstoreFixed(_)) => {
Some(deref_interior(InteriorElement(element_kind(t))))
}
expr_ty: ty::t,
def: ast::Def)
-> McResult<cmt> {
- debug!("cat_def: id={} expr={}",
- id, expr_ty.repr(self.tcx()));
+ debug!("cat_def: id={} expr={} def={:?}",
+ id, expr_ty.repr(self.tcx()), def);
match def {
ast::DefStruct(..) | ast::DefVariant(..) => {
//! the implicit index deref, if any (see above)
let element_ty = match ty::index(base_cmt.ty) {
- Some(ty) => ty,
+ Some(ref mt) => mt.ty,
None => {
self.tcx().sess.span_bug(
elt.span(),
*/
match ty::get(slice_ty).sty {
- ty::ty_vec(_, ty::VstoreSlice(slice_r, mutbl)) => {
- (mutbl, slice_r)
- }
-
- ty::ty_rptr(_, ref mt) => {
- vec_slice_info(tcx, pat, mt.ty)
- }
+ ty::ty_rptr(r, ref mt) => match ty::get(mt.ty).sty {
+ ty::ty_vec(slice_mt, None) => (slice_mt.mutbl, r),
+ _ => vec_slice_info(tcx, pat, mt.ty),
+ },
_ => {
tcx.sess.span_bug(
fn element_kind(t: ty::t) -> ElementKind {
match ty::get(t).sty {
+ ty::ty_rptr(_, ty::mt{ty:ty, ..}) |
+ ty::ty_uniq(ty) => match ty::get(ty).sty {
+ ty::ty_vec(_, None) => VecElement,
+ _ => OtherElement
+ },
ty::ty_vec(..) => VecElement,
ty::ty_str(..) => StrElement,
_ => OtherElement
struct Match<'a,'b> {
pats: Vec<@ast::Pat> ,
data: ArmData<'a,'b>,
- bound_ptrs: Vec<(Ident, ValueRef)> }
+ bound_ptrs: Vec<(Ident, ValueRef)>
+}
impl<'a,'b> Repr for Match<'a,'b> {
fn repr(&self, tcx: &ty::ctxt) -> ~str {
let slice_begin = tvec::pointer_add_byte(bcx, base, slice_byte_offset);
let slice_len_offset = C_uint(bcx.ccx(), elem_count - 1u);
let slice_len = Sub(bcx, len, slice_len_offset);
- let slice_ty = ty::mk_vec(bcx.tcx(), vt.unit_ty,
- ty::VstoreSlice(ty::ReStatic, ast::MutImmutable));
+ let slice_ty = ty::mk_slice(bcx.tcx(),
+ ty::ReStatic,
+ ty::mt {ty: vt.unit_ty, mutbl: ast::MutImmutable});
let scratch = rvalue_scratch_datum(bcx, slice_ty, "");
Store(bcx, slice_begin,
GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
// FIXME #6750 ~Trait cannot be directly marked as
// noalias because the actual object pointer is nested.
ty::ty_uniq(..) | // ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
- ty::ty_vec(_, ty::VstoreUniq) | ty::ty_str(ty::VstoreUniq) => {
+ ty::ty_str(ty::VstoreUniq) => {
unsafe {
llvm::LLVMAddReturnAttribute(llfn, lib::llvm::NoAliasAttribute as c_uint);
}
// FIXME #6750 ~Trait cannot be directly marked as
// noalias because the actual object pointer is nested.
ty::ty_uniq(..) | // ty::ty_trait(_, _, ty::UniqTraitStore, _, _) |
- ty::ty_vec(_, ty::VstoreUniq) | ty::ty_str(ty::VstoreUniq) |
+ ty::ty_str(ty::VstoreUniq) |
ty::ty_closure(~ty::ClosureTy {store: ty::UniqTraitStore, ..}) => {
unsafe {
llvm::LLVMAddAttribute(llarg, lib::llvm::NoAliasAttribute as c_uint);
}
})
}
- ty::ty_str(ty::VstoreFixed(n)) |
- ty::ty_vec(_, ty::VstoreFixed(n)) => {
+ ty::ty_str(ty::VstoreFixed(n)) => {
+ let unit_ty = ty::sequence_element_type(cx.tcx(), t);
+ let (base, len) = tvec::get_fixed_base_and_byte_len(cx, av, unit_ty, n);
+ cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
+ }
+ ty::ty_vec(_, Some(n)) => {
let unit_ty = ty::sequence_element_type(cx.tcx(), t);
let (base, len) = tvec::get_fixed_base_and_byte_len(cx, av, unit_ty, n);
cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
match ty::get(ret_ty).sty {
// `~` pointer return values never alias because ownership
// is transferred
- ty::ty_uniq(..) | ty::ty_vec(_, ty::VstoreUniq) => {
+ ty::ty_uniq(..) => {
attrs.push((0, NoAliasAttribute));
}
_ => {}
pub fn mono_data_classify(t: ty::t) -> MonoDataClass {
match ty::get(t).sty {
ty::ty_float(_) => MonoFloat,
- ty::ty_rptr(..) | ty::ty_uniq(..) | ty::ty_box(..) |
- ty::ty_str(ty::VstoreUniq) | ty::ty_vec(_, ty::VstoreUniq) |
+ ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
+ ty::ty_vec(_, None) => MonoBits,
+ _ => MonoNonNull,
+ },
+ ty::ty_uniq(..) | ty::ty_box(..) |
+ ty::ty_str(ty::VstoreUniq) |
ty::ty_bare_fn(..) => MonoNonNull,
// Is that everything? Would closures or slices qualify?
_ => MonoBits
Some(ref mt) => {
assert!(mt.mutbl != ast::MutMutable);
let dv = match ty::get(t).sty {
- ty::ty_ptr(..) | ty::ty_rptr(..) => {
- const_deref_ptr(cx, v)
+ ty::ty_ptr(mt) | ty::ty_rptr(_, mt) => {
+ match ty::get(mt.ty).sty {
+ ty::ty_vec(_, None) => cx.sess().bug("unexpected slice"),
+ _ => const_deref_ptr(cx, v),
+ }
}
ty::ty_enum(..) | ty::ty_struct(..) => {
const_deref_newtype(cx, v, t)
assert_eq!(abi::slice_elt_base, 0);
assert_eq!(abi::slice_elt_len, 1);
match ty::get(ty).sty {
- ty::ty_vec(_, ty::VstoreFixed(len)) => {
+ ty::ty_vec(_, Some(len)) => {
llconst = C_struct(cx, [
llptr,
C_uint(cx, len)
"index is not an integer-constant expression")
};
let (arr, len) = match ty::get(bt).sty {
- ty::ty_vec(_, ty::VstoreFixed(u)) => (bv, C_uint(cx, u)),
- ty::ty_vec(_, ty::VstoreSlice(..)) |
ty::ty_str(ty::VstoreSlice(..)) => {
let e1 = const_get_elt(cx, bv, [0]);
(const_deref_ptr(cx, e1), const_get_elt(cx, bv, [1]))
},
+ ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
+ ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
+ ty::ty_vec(_, None) => {
+ 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,
+ "index-expr base must be a vector or string type")
+ },
_ => cx.sess().span_bug(base.span,
- "index-expr base must be a fixed-size vector or a slice")
+ "index-expr base must be a vector or string type")
};
let len = llvm::LLVMConstIntGetZExtValue(len) as u64;
ty::ty_box(typ) => {
create_pointer_to_box_metadata(cx, t, typ)
},
- ty::ty_vec(ty, ref vstore) => {
- match *vstore {
- ty::VstoreFixed(len) => {
- fixed_vec_metadata(cx, ty, len, usage_site_span)
- }
- ty::VstoreUniq => {
- let vec_metadata = vec_metadata(cx, ty, usage_site_span);
+ ty::ty_vec(ref mt, Some(len)) => fixed_vec_metadata(cx, mt.ty, len, usage_site_span),
+ ty::ty_uniq(typ) => {
+ match ty::get(typ).sty {
+ ty::ty_vec(ref mt, None) => {
+ let vec_metadata = vec_metadata(cx, mt.ty, usage_site_span);
pointer_type_metadata(cx, t, vec_metadata)
}
- ty::VstoreSlice(..) => {
- vec_slice_metadata(cx, t, ty, usage_site_span)
+ _ => {
+ let pointee = type_metadata(cx, typ, usage_site_span);
+ pointer_type_metadata(cx, t, pointee)
}
}
- },
- ty::ty_uniq(typ) => {
- let pointee = type_metadata(cx, typ, usage_site_span);
- pointer_type_metadata(cx, t, pointee)
}
ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
- let pointee = type_metadata(cx, mt.ty, usage_site_span);
- pointer_type_metadata(cx, t, pointee)
+ match ty::get(mt.ty).sty {
+ ty::ty_vec(ref mt, None) => vec_slice_metadata(cx, t, mt.ty, usage_site_span),
+ _ => {
+ let pointee = type_metadata(cx, mt.ty, usage_site_span);
+ pointer_type_metadata(cx, t, pointee)
+ }
+ }
},
ty::ty_bare_fn(ref barefnty) => {
subroutine_type_metadata(cx, &barefnty.sig, usage_site_span)
// this type may have a different region/mutability than the
// real one, but it will have the same runtime representation
- let slice_ty = ty::mk_vec(tcx, unit_ty,
- ty::VstoreSlice(ty::ReStatic, ast::MutImmutable));
+ let slice_ty = ty::mk_slice(tcx, ty::ReStatic,
+ ty::mt { ty: unit_ty, mutbl: ast::MutImmutable });
let scratch = rvalue_scratch_datum(bcx, slice_ty, "__adjust");
Store(bcx, base, GEPi(bcx, scratch.val, [0u, abi::slice_elt_base]));
pub fn cast_type_kind(t: ty::t) -> cast_kind {
match ty::get(t).sty {
- ty::ty_char => cast_integral,
+ ty::ty_char => cast_integral,
ty::ty_float(..) => cast_float,
ty::ty_ptr(..) => cast_pointer,
- ty::ty_rptr(..) => cast_pointer,
+ ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty{
+ ty::ty_vec(_, None) => cast_other,
+ _ => cast_pointer,
+ },
ty::ty_bare_fn(..) => cast_pointer,
ty::ty_int(..) => cast_integral,
ty::ty_uint(..) => cast_integral,
- ty::ty_bool => cast_integral,
+ ty::ty_bool => cast_integral,
ty::ty_enum(..) => cast_enum,
- _ => cast_other
+ _ => cast_other
}
}
let r = match ty::get(datum.ty).sty {
ty::ty_uniq(content_ty) => {
- deref_owned_pointer(bcx, expr, datum, content_ty)
+ match ty::get(content_ty).sty {
+ ty::ty_vec(_, None) => bcx.tcx().sess.span_bug(expr.span, "unexpected ~[T]"),
+ _ => deref_owned_pointer(bcx, expr, datum, content_ty),
+ }
}
ty::ty_box(content_ty) => {
ty::ty_ptr(ty::mt { ty: content_ty, .. }) |
ty::ty_rptr(_, ty::mt { ty: content_ty, .. }) => {
- assert!(!ty::type_needs_drop(bcx.tcx(), datum.ty));
+ match ty::get(content_ty).sty {
+ ty::ty_vec(_, None) => bcx.tcx().sess.span_bug(expr.span, "unexpected &[T]"),
+ _ => {
+ assert!(!ty::type_needs_drop(bcx.tcx(), datum.ty));
- let ptr = datum.to_llscalarish(bcx);
+ let ptr = datum.to_llscalarish(bcx);
- // Always generate an lvalue datum, even if datum.mode is
- // an rvalue. This is because datum.mode is only an
- // rvalue for non-owning pointers like &T or *T, in which
- // case cleanup *is* scheduled elsewhere, by the true
- // owner (or, in the case of *T, by the user).
- DatumBlock(bcx, Datum(ptr, content_ty, LvalueExpr))
+ // Always generate an lvalue datum, even if datum.mode is
+ // an rvalue. This is because datum.mode is only an
+ // rvalue for non-owning pointers like &T or *T, in which
+ // case cleanup *is* scheduled elsewhere, by the true
+ // owner (or, in the case of *T, by the user).
+ DatumBlock(bcx, Datum(ptr, content_ty, LvalueExpr))
+ }
+ }
}
_ => {
ty::mk_box(tcx, ty::mk_i8()),
ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ) => {
- let llty = sizing_type_of(ccx, typ);
- // Unique boxes do not allocate for zero-size types. The standard library may assume
- // that `free` is never called on the pointer returned for `~ZeroSizeType`.
- if llsize_of_alloc(ccx, llty) == 0 {
- ty::mk_i8()
- } else {
- ty::mk_uniq(tcx, ty::mk_i8())
- }
- }
-
- ty::ty_vec(ty, ty::VstoreUniq) if !ty::type_needs_drop(tcx, ty) =>
- ty::mk_uniq(tcx, ty::mk_i8()),
-
+ match ty::get(typ).sty {
+ ty::ty_vec(_, None) => t,
+ _ => {
+ let llty = sizing_type_of(ccx, typ);
+ // Unique boxes do not allocate for zero-size types. The standard
+ // library may assume that `free` is never called on the pointer
+ // returned for `~ZeroSizeType`.
+ if llsize_of_alloc(ccx, llty) == 0 {
+ ty::mk_i8()
+ } else {
+ ty::mk_uniq(tcx, ty::mk_i8())
+ }
+ }
+ }
+ }
_ => t
}
}
ty::ty_uniq(content_ty) => {
let llbox = Load(bcx, v0);
let not_null = IsNotNull(bcx, llbox);
- with_cond(bcx, not_null, |bcx| {
- let bcx = drop_ty(bcx, llbox, content_ty);
- trans_exchange_free(bcx, llbox)
- })
+ match ty::get(content_ty).sty {
+ ty::ty_vec(mt, None) => {
+ with_cond(bcx, not_null, |bcx| {
+ let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, mt.ty);
+ trans_exchange_free(bcx, llbox)
+ })
+ }
+ _ => {
+ with_cond(bcx, not_null, |bcx| {
+ let bcx = drop_ty(bcx, llbox, content_ty);
+ trans_exchange_free(bcx, llbox)
+ })
+ }
+ }
}
- ty::ty_vec(_, ty::VstoreUniq) | ty::ty_str(ty::VstoreUniq) => {
+ ty::ty_str(ty::VstoreUniq) => {
let llbox = Load(bcx, v0);
let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
// We're careful to not use first class aggregates here because that
// will kick us off fast isel. (Issue #4352.)
let bcx = self.bcx;
- let str_vstore = ty::VstoreSlice(ty::ReStatic, ());
+ let str_vstore = ty::VstoreSlice(ty::ReStatic);
let str_ty = ty::mk_str(bcx.tcx(), str_vstore);
let scratch = rvalue_scratch_datum(bcx, str_ty, "");
let len = C_uint(bcx.ccx(), s.get().len());
self.visit("leave_" + bracket_name, extra);
}
- pub fn vstore_name_and_extra<M>(&mut self,
- t: ty::t,
- vstore: ty::Vstore<M>)
- -> (~str, Vec<ValueRef> ) {
+ pub fn vstore_name_and_extra(&mut self,
+ t: ty::t,
+ vstore: ty::Vstore)
+ -> (~str, Vec<ValueRef> ) {
match vstore {
ty::VstoreFixed(n) => {
let extra = (vec!(self.c_uint(n))).append(self.c_size_and_align(t).as_slice());
let (name, extra) = self.vstore_name_and_extra(t, vst);
self.visit("estr_".to_owned() + name, extra.as_slice())
}
- ty::ty_vec(ty, vst) => {
- let (name, extra) = self.vstore_name_and_extra(t, vst);
- let extra = extra.append(self.c_mt(&ty::mt {
- ty: ty,
- mutbl: match vst {
- ty::VstoreSlice(_, m) => m,
- _ => ast::MutImmutable
- }
- }).as_slice());
- self.visit("evec_".to_owned() + name, extra.as_slice())
+ ty::ty_vec(ref mt, Some(sz)) => {
+ let extra = (vec!(self.c_uint(sz))).append(self.c_size_and_align(t).as_slice());
+ let extra = extra.append(self.c_mt(mt).as_slice());
+ self.visit("evec_fixed".to_owned(), extra.as_slice())
}
+ ty::ty_vec(..) => fail!("unexpected unsized vec"),
// Should remove mt from box and uniq.
ty::ty_box(typ) => {
let extra = self.c_mt(&ty::mt {
self.visit("box", extra.as_slice())
}
ty::ty_uniq(typ) => {
- let extra = self.c_mt(&ty::mt {
- ty: typ,
- mutbl: ast::MutImmutable,
- });
- self.visit("uniq", extra.as_slice())
+ match ty::get(typ).sty {
+ ty::ty_vec(ref mt, None) => {
+ let (name, extra) = (~"uniq", Vec::new());
+ let extra = extra.append(self.c_mt(mt).as_slice());
+ self.visit(~"evec_" + name, extra.as_slice())
+ }
+ _ => {
+ let extra = self.c_mt(&ty::mt {
+ ty: typ,
+ mutbl: ast::MutImmutable,
+ });
+ self.visit("uniq", extra.as_slice())
+ }
+ }
}
ty::ty_ptr(ref mt) => {
let extra = self.c_mt(mt);
self.visit("ptr", extra.as_slice())
}
ty::ty_rptr(_, ref mt) => {
- let extra = self.c_mt(mt);
- self.visit("rptr", extra.as_slice())
+ match ty::get(mt.ty).sty {
+ ty::ty_vec(ref mt, None) => {
+ let (name, extra) = (~"slice", Vec::new());
+ let extra = extra.append(self.c_mt(mt).as_slice());
+ self.visit(~"evec_" + name, extra.as_slice())
+ }
+ _ => {
+ let extra = self.c_mt(mt);
+ self.visit("rptr", extra.as_slice())
+ }
+ }
}
ty::ty_tup(ref tys) => {
llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
// Arrange for the backing array to be cleaned up.
- let fixed_ty = ty::mk_vec(bcx.tcx(), vt.unit_ty,
- ty::VstoreFixed(count));
+ let fixed_ty = ty::mk_vec(bcx.tcx(),
+ ty::mt {ty: vt.unit_ty,
+ mutbl: ast::MutMutable},
+ Some(count));
let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
let llfixed_casted = BitCast(bcx, llfixed, llfixed_ty);
let cleanup_scope = cleanup::temporary_scope(bcx.tcx(), content_expr.id);
(base, len)
}
+pub fn get_base_and_byte_len_for_vec(bcx: &Block,
+ llval: ValueRef,
+ vec_ty: ty::t)
+ -> (ValueRef, ValueRef) {
+ /*!
+ * Converts a vector into the slice pair. The vector should be
+ * stored in `llval` which should be by ref. If you have a datum,
+ * you would probably prefer to call
+ * `Datum::get_base_and_byte_len()`.
+ */
+
+ let ccx = bcx.ccx();
+ let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
+
+ let size = match ty::get(vec_ty).sty {
+ ty::ty_vec(_, size) => size,
+ _ => ccx.sess().bug("non-vector in get_base_and_byte_len_for_vec"),
+ };
+
+ match size {
+ Some(n) => {
+ let base = GEPi(bcx, llval, [0u, 0u]);
+ let len = Mul(bcx, C_uint(ccx, n), vt.llunit_size);
+ (base, len)
+ }
+ None => ccx.sess().bug("unsized vector in get_base_and_byte_len_for_vec")
+ }
+}
+
pub fn get_base_and_len(bcx: &Block,
llval: ValueRef,
vec_ty: ty::t)
let vt = vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty));
let vstore = match ty::get(vec_ty).sty {
- ty::ty_vec(_, vst) => vst,
- ty::ty_str(vst) => {
- // Convert from immutable-only-Vstore to Vstore.
- match vst {
- ty::VstoreFixed(n) => ty::VstoreFixed(n),
- ty::VstoreSlice(r, ()) => ty::VstoreSlice(r, ast::MutImmutable),
- ty::VstoreUniq => ty::VstoreUniq
- }
- }
- _ => ty::VstoreUniq
+ ty::ty_str(vst) => vst,
+ ty::ty_vec(_, Some(n)) => ty::VstoreFixed(n),
+ ty::ty_rptr(r, mt) => match ty::get(mt.ty).sty {
+ ty::ty_vec(_, None) => ty::VstoreSlice(r),
+ _ => ccx.sess().bug("unexpected type (ty_rptr) in get_base_and_len"),
+ },
+ ty::ty_uniq(t) => match ty::get(t).sty {
+ ty::ty_vec(_, None) => ty::VstoreUniq,
+ _ => ccx.sess().bug("unexpected type (ty_uniq) in get_base_and_len"),
+ },
+ _ => ccx.sess().bug("unexpected type in get_base_and_len"),
};
match vstore {
ty::ty_float(t) => Type::float_from_ty(cx, t),
ty::ty_str(ty::VstoreUniq) |
- ty::ty_vec(_, ty::VstoreUniq) |
ty::ty_box(..) |
ty::ty_uniq(..) |
- ty::ty_ptr(..) |
- ty::ty_rptr(..) => Type::i8p(cx),
+ ty::ty_ptr(..) => Type::i8p(cx),
+ ty::ty_rptr(_, mt) => {
+ match ty::get(mt.ty).sty {
+ ty::ty_vec(_, None) => Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false),
+ _ => Type::i8p(cx),
+ }
+ }
- ty::ty_str(ty::VstoreSlice(..)) |
- ty::ty_vec(_, ty::VstoreSlice(..)) => {
+ ty::ty_str(ty::VstoreSlice(..)) => {
Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false)
}
ty::ty_trait(..) => Type::opaque_trait(cx),
ty::ty_str(ty::VstoreFixed(size)) => Type::array(&Type::i8(cx), size as u64),
- ty::ty_vec(ty, ty::VstoreFixed(size)) => {
- Type::array(&sizing_type_of(cx, ty), size as u64)
+ ty::ty_vec(mt, Some(size)) => {
+ Type::array(&sizing_type_of(cx, mt.ty), size as u64)
}
ty::ty_tup(..) | ty::ty_enum(..) => {
}
}
- ty::ty_self(_) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
+ ty::ty_self(_) | ty::ty_infer(..) | ty::ty_param(..) |
+ ty::ty_err(..) | ty::ty_vec(_, None) => {
cx.sess().bug(format!("fictitious type {:?} in sizing_type_of()",
ty::get(t).sty))
}
Type::at_box(cx, type_of(cx, typ)).ptr_to()
}
ty::ty_uniq(typ) => {
- type_of(cx, typ).ptr_to()
- }
- ty::ty_vec(ty, ty::VstoreUniq) => {
- Type::vec(cx, &type_of(cx, ty)).ptr_to()
+ match ty::get(typ).sty {
+ ty::ty_vec(mt, None) => Type::vec(cx, &type_of(cx, mt.ty)).ptr_to(),
+ _ => type_of(cx, typ).ptr_to(),
+ }
}
ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
- ty::ty_rptr(_, ref mt) => type_of(cx, mt.ty).ptr_to(),
-
- ty::ty_vec(ty, ty::VstoreSlice(..)) => {
- let p_ty = type_of(cx, ty).ptr_to();
- let u_ty = Type::uint_from_ty(cx, ast::TyU);
- Type::struct_(cx, [p_ty, u_ty], false)
+ ty::ty_rptr(_, ref mt) => {
+ match ty::get(mt.ty).sty {
+ ty::ty_vec(mt, None) => {
+ let p_ty = type_of(cx, mt.ty).ptr_to();
+ let u_ty = Type::uint_from_ty(cx, ast::TyU);
+ Type::struct_(cx, [p_ty, u_ty], false)
+ }
+ _ => type_of(cx, mt.ty).ptr_to(),
+ }
}
ty::ty_str(ty::VstoreSlice(..)) => {
Type::array(&Type::i8(cx), (n + 1u) as u64)
}
- ty::ty_vec(ty, ty::VstoreFixed(n)) => {
- Type::array(&type_of(cx, ty), n as u64)
+ ty::ty_vec(ref mt, Some(n)) => {
+ Type::array(&type_of(cx, mt.ty), n as u64)
}
ty::ty_bare_fn(_) => {
adt::incomplete_type_of(cx, repr, name)
}
}
- ty::ty_self(..) => cx.sess().unimpl("type_of: ty_self"),
+
+ ty::ty_vec(_, None) => cx.sess().bug("type_of with unszied ty_vec"),
+ ty::ty_self(..) => cx.sess().unimpl("type_of with ty_self"),
ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
ty::ty_err(..) => cx.sess().bug("type_of with ty_err")
}
#[deriving(Clone, Eq, TotalEq, Encodable, Decodable, Hash, Show)]
-/// Describes the "storage mode" of a `[]`, whether it's fixed length or a slice.
-///
-/// Set M to () to disable mutable slices.
-pub enum Vstore<M = ast::Mutability> {
+/// Describes the "storage mode" of a str, whether it's fixed length or a slice.
+pub enum Vstore {
/// [T, ..N]
VstoreFixed(uint),
/// ~[T]
VstoreUniq,
/// &[T] and &mut [T]
- VstoreSlice(Region, M)
+ VstoreSlice(Region)
}
#[deriving(Clone, Eq, TotalEq, Hash, Encodable, Decodable, Show)]
ty_enum(DefId, substs),
ty_box(t),
ty_uniq(t),
- ty_str(Vstore<()>),
- ty_vec(t, Vstore),
+ ty_str(Vstore),
+ ty_vec(mt, Option<uint>),
ty_ptr(mt),
ty_rptr(Region, mt),
ty_bare_fn(BareFnTy),
terr_regions_no_overlap(Region, Region),
terr_regions_insufficiently_polymorphic(BoundRegion, Region),
terr_regions_overly_polymorphic(BoundRegion, Region),
- terr_vstores_differ(terr_vstore_kind, expected_found<Vstore<()>>),
+ terr_vstores_differ(terr_vstore_kind, expected_found<Vstore>),
terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
terr_in_field(@type_err, ast::Ident),
terr_sorts(expected_found<t>),
return f;
}
match &st {
- &ty_str(VstoreSlice(r, ())) => {
- flags |= rflags(r);
- }
- &ty_vec(ty, VstoreSlice(r, _)) => {
+ &ty_str(VstoreSlice(r)) => {
flags |= rflags(r);
- flags |= get(ty).flags;
}
&ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
&ty_str(_) => {}
_ => {}
}
}
- &ty_box(tt) | &ty_uniq(tt) | &ty_vec(tt, _) => {
+ &ty_box(tt) | &ty_uniq(tt) => {
flags |= get(tt).flags
}
- &ty_ptr(ref m) => {
+ &ty_ptr(ref m) | &ty_vec(ref m, _) => {
flags |= get(m.ty).flags;
}
&ty_rptr(r, ref m) => {
#[inline]
pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) }
-pub fn mk_str(cx: &ctxt, v: Vstore<()>) -> t {
+pub fn mk_str(cx: &ctxt, v: Vstore) -> t {
mk_t(cx, ty_str(v))
}
mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::MutImmutable})
}
-pub fn mk_vec(cx: &ctxt, ty: t, v: Vstore) -> t {
- mk_t(cx, ty_vec(ty, v))
+pub fn mk_vec(cx: &ctxt, tm: mt, sz: Option<uint>) -> t {
+ mk_t(cx, ty_vec(tm, sz))
+}
+
+pub fn mk_slice(cx: &ctxt, r: Region, tm: mt) -> t {
+ mk_rptr(cx, r,
+ mt {
+ ty: mk_vec(cx, tm, None),
+ mutbl: tm.mutbl
+ })
}
pub fn mk_tup(cx: &ctxt, ts: Vec<t>) -> t { mk_t(cx, ty_tup(ts)) }
ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_str(_) | ty_self(_) |
ty_infer(_) | ty_param(_) | ty_err => {}
- ty_box(ty) | ty_uniq(ty) | ty_vec(ty, _) => maybe_walk_ty(ty, f),
- ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
+ ty_box(ty) | ty_uniq(ty) => maybe_walk_ty(ty, f),
+ ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_vec(ref tm, _) => {
maybe_walk_ty(tm.ty, f);
}
ty_enum(_, ref substs) | ty_struct(_, ref substs) |
}
}
+fn type_is_slice(ty:t) -> bool {
+ match get(ty).sty {
+ ty_rptr(_, mt) => match get(mt.ty).sty {
+ ty_vec(_, None) => true,
+ _ => false,
+ },
+ _ => false
+ }
+}
+
pub fn type_is_structural(ty: t) -> bool {
match get(ty).sty {
ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) | ty_trait(..) |
- ty_vec(_, VstoreFixed(_)) | ty_str(VstoreFixed(_)) |
- ty_vec(_, VstoreSlice(..)) | ty_str(VstoreSlice(..))
+ ty_vec(_, Some(_)) |
+ ty_str(VstoreFixed(_)) | ty_str(VstoreSlice(_))
=> true,
- _ => false
+ _ => type_is_slice(ty)
}
}
pub fn sequence_element_type(cx: &ctxt, ty: t) -> t {
match get(ty).sty {
ty_str(_) => mk_mach_uint(ast::TyU8),
- ty_vec(ty, _) => ty,
+ ty_vec(mt, _) => mt.ty,
+ ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
+ ty_box(t) | ty_uniq(t) => match get(t).sty {
+ ty_vec(mt, None) => mt.ty,
+ _ => cx.sess.bug("sequence_element_type called on non-sequence value"),
+ },
_ => cx.sess.bug("sequence_element_type called on non-sequence value"),
}
}
pub fn type_is_region_ptr(ty: t) -> bool {
match get(ty).sty {
- ty_rptr(_, _) => true,
- _ => false
+ ty_rptr(_, mt) => match get(mt.ty).sty {
+ // FIXME(nrc, DST) slices weren't regarded as rptrs, so we preserve this
+ // odd behaviour for now. (But ~[] were unique. I have no idea why).
+ ty_vec(_, None) => false,
+ _ => true
+ },
+ _ => false
}
}
pub fn type_is_unique(ty: t) -> bool {
match get(ty).sty {
- ty_uniq(_) | ty_vec(_, VstoreUniq) | ty_str(VstoreUniq) => true,
+ ty_uniq(_) | ty_str(VstoreUniq) => true,
_ => false
}
}
!needs_unwind_cleanup
}
ty_uniq(_) |
- ty_str(VstoreUniq) |
- ty_vec(_, VstoreUniq) => {
+ ty_str(VstoreUniq) => {
// Once we're inside a box, the annihilator will find
// it and destroy it.
if !encountered_box {
borrowed_contents(r, mt.mutbl))
}
- ty_vec(ty, VstoreUniq) => {
- tc_ty(cx, ty, cache).owned_pointer()
- }
-
- ty_vec(ty, VstoreSlice(r, mutbl)) => {
- tc_ty(cx, ty, cache).reference(borrowed_contents(r, mutbl))
- }
-
- ty_vec(ty, VstoreFixed(_)) => {
- tc_ty(cx, ty, cache)
+ ty_vec(mt, _) => {
+ tc_mt(cx, mt, cache)
}
- ty_str(VstoreSlice(r, ())) => {
+ ty_str(VstoreSlice(r)) => {
borrowed_contents(r, ast::MutImmutable)
}
// fixed length vectors need special treatment compared to
// normal vectors, since they don't necessarily have the
// possibilty to have length zero.
- ty_vec(_, VstoreFixed(0)) => false, // don't need no contents
- ty_vec(ty, VstoreFixed(_)) => type_requires(cx, seen, r_ty, ty),
+ ty_vec(_, Some(0)) => false, // don't need no contents
+ ty_vec(mt, Some(_)) => type_requires(cx, seen, r_ty, mt.ty),
ty_nil |
ty_bot |
ty_err |
ty_param(_) |
ty_self(_) |
- ty_vec(_, _) => {
+ ty_vec(_, None) => {
false
}
ty_box(typ) | ty_uniq(typ) => {
}
// Fixed-length vectors.
// FIXME(#11924) Behavior undecided for zero-length vectors.
- ty_vec(ty, VstoreFixed(_)) => {
- type_structurally_recursive(cx, sp, seen, ty)
+ ty_vec(mt, Some(_)) => {
+ type_structurally_recursive(cx, sp, seen, mt.ty)
}
// Push struct and enum def-ids onto `seen` before recursing.
// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
pub fn deref(t: t, explicit: bool) -> Option<mt> {
match get(t).sty {
- ty_box(typ) | ty_uniq(typ) => Some(mt {
- ty: typ,
- mutbl: ast::MutImmutable,
- }),
- ty_rptr(_, mt) => Some(mt),
+ ty_box(typ) | ty_uniq(typ) => match get(typ).sty {
+ // Don't deref ~[] etc., might need to generalise this to all DST.
+ ty_vec(_, None) => None,
+ _ => Some(mt {
+ ty: typ,
+ mutbl: ast::MutImmutable,
+ }),
+ },
+ ty_rptr(_, mt) => match get(mt.ty).sty {
+ // Don't deref &[], might need to generalise this to all DST.
+ ty_vec(_, None) => None,
+ _ => Some(mt),
+ },
ty_ptr(mt) if explicit => Some(mt),
_ => None
}
}
// Returns the type of t[i]
-pub fn index(t: t) -> Option<t> {
+pub fn index(t: t) -> Option<mt> {
match get(t).sty {
- ty_vec(ty, _) => Some(ty),
- ty_str(_) => Some(mk_u8()),
+ ty_vec(mt, _) => Some(mt),
+ ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
+ ty_box(t) | ty_uniq(t) => match get(t).sty {
+ ty_vec(mt, None) => Some(mt),
+ _ => None,
+ },
+ ty_str(_) => Some(mt {ty: mk_u8(), mutbl: ast::MutImmutable}),
_ => None
}
}
ty: t) -> Region {
match get(ty).sty {
ty_rptr(r, _) => r,
- ty_vec(_, VstoreSlice(r, _)) => r,
- ty_str(VstoreSlice(r, ())) => r,
+ ty_str(VstoreSlice(r)) => r,
ref s => {
tcx.sess.span_bug(
span,
r: Region, m: ast::Mutability,
ty: ty::t) -> ty::t {
match get(ty).sty {
- ty_vec(ty, _) => {
- ty::mk_vec(cx, ty, VstoreSlice(r, m))
+ ty_uniq(t) | ty_ptr(mt{ty: t, ..}) |
+ ty_rptr(_, mt{ty: t, ..}) => match get(t).sty {
+ ty::ty_vec(mt, None) => ty::mk_slice(cx, r, ty::mt {ty: mt.ty, mutbl: m}),
+ ref s => {
+ cx.sess.span_bug(
+ span,
+ format!("borrow-vec associated with bad sty: {:?}",
+ s));
+ }
+ },
+ ty_vec(mt, Some(_)) => {
+ ty::mk_slice(cx, r, ty::mt {ty: mt.ty, mutbl: m})
}
ty_str(_) => {
- ty::mk_str(cx, VstoreSlice(r, ()))
+ ty::mk_str(cx, VstoreSlice(r))
}
ref s => {
return t_norm;
}
- fn fold_vstore<M>(&mut self, vstore: Vstore<M>) -> Vstore<M> {
+ fn fold_vstore(&mut self, vstore: Vstore) -> Vstore {
match vstore {
VstoreFixed(..) | VstoreUniq => vstore,
- VstoreSlice(_, m) => VstoreSlice(ReStatic, m)
+ VstoreSlice(_) => VstoreSlice(ReStatic)
}
}
ty_uniq(_) => {
byte!(10);
}
- ty_vec(_, v) => {
+ ty_vec(m, Some(_)) => {
byte!(11);
- hash!(v);
+ mt(&mut state, m);
+ 1u8.hash(&mut state);
+ }
+ ty_vec(m, None) => {
+ byte!(11);
+ mt(&mut state, m);
+ 0u8.hash(&mut state);
}
ty_ptr(m) => {
byte!(12);
r
}
- fn fold_vstore<M>(&mut self, vstore: ty::Vstore<M>) -> ty::Vstore<M> {
+ fn fold_vstore(&mut self, vstore: ty::Vstore) -> ty::Vstore {
super_fold_vstore(self, vstore)
}
ty::ty_ptr(ref tm) => {
ty::ty_ptr(this.fold_mt(tm))
}
- ty::ty_vec(ty, vst) => {
- ty::ty_vec(this.fold_ty(ty), this.fold_vstore(vst))
+ ty::ty_vec(ref tm, sz) => {
+ ty::ty_vec(this.fold_mt(tm), sz)
}
ty::ty_enum(tid, ref substs) => {
ty::ty_enum(tid, this.fold_substs(substs))
}
}
-pub fn super_fold_vstore<T:TypeFolder, M>(this: &mut T,
- vstore: ty::Vstore<M>)
- -> ty::Vstore<M> {
+pub fn super_fold_vstore<T:TypeFolder>(this: &mut T,
+ vstore: ty::Vstore)
+ -> ty::Vstore {
match vstore {
ty::VstoreFixed(i) => ty::VstoreFixed(i),
ty::VstoreUniq => ty::VstoreUniq,
- ty::VstoreSlice(r, m) => ty::VstoreSlice(this.fold_region(r), m),
+ ty::VstoreSlice(r) => ty::VstoreSlice(this.fold_region(r)),
}
}
}
}
+ fn ast_ty_to_mt<AC:AstConv, RS:RegionScope>(this: &AC,
+ rscope: &RS,
+ ty: &ast::Ty) -> ty::mt {
+ ty::mt {ty: ast_ty_to_ty(this, rscope, ty), mutbl: ast::MutImmutable}
+ }
+
// Handle ~, and & being able to mean strs and vecs.
// If a_seq_ty is a str or a vec, make it a str/vec.
// Also handle first-class trait types.
RS:RegionScope>(
this: &AC,
rscope: &RS,
- a_seq_ty: &ast::Ty,
+ a_seq_ty: &ast::MutTy,
ptr_ty: PointerTy,
constr: |ty::t| -> ty::t)
-> ty::t {
let tcx = this.tcx();
debug!("mk_pointer(ptr_ty={:?})", ptr_ty);
- match a_seq_ty.node {
+ match a_seq_ty.ty.node {
ast::TyVec(ty) => {
- let vst = ptr_ty.expect_vstore(tcx, a_seq_ty.span, "vectors");
- debug!("&[]: vst={:?}", vst);
- return ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, ty), vst);
+ let mut mt = ast_ty_to_mt(this, rscope, ty);
+ if a_seq_ty.mutbl == ast::MutMutable {
+ mt.mutbl = ast::MutMutable;
+ }
+ return constr(ty::mk_vec(tcx, mt, None));
}
ast::TyPath(ref path, ref bounds, id) => {
// Note that the "bounds must be empty if path is not a trait"
ty::VstoreUniq => {
return ty::mk_str(tcx, ty::VstoreUniq);
}
- ty::VstoreSlice(r, ast::MutImmutable) => {
- return ty::mk_str(tcx, ty::VstoreSlice(r, ()));
+ ty::VstoreSlice(r) => {
+ return ty::mk_str(tcx, ty::VstoreSlice(r));
}
_ => {}
}
this, rscope, trait_def_id, None, path);
let trait_store = match ptr_ty {
VStore(ty::VstoreUniq) => ty::UniqTraitStore,
- VStore(ty::VstoreSlice(r, m)) => {
- ty::RegionTraitStore(r, m)
+ VStore(ty::VstoreSlice(r)) => {
+ ty::RegionTraitStore(r, a_seq_ty.mutbl)
}
_ => {
tcx.sess.span_err(
_ => {}
}
- constr(ast_ty_to_ty(this, rscope, a_seq_ty))
+ constr(ast_ty_to_ty(this, rscope, a_seq_ty.ty))
}
let tcx = this.tcx();
ast::TyNil => ty::mk_nil(),
ast::TyBot => ty::mk_bot(),
ast::TyBox(ty) => {
- mk_pointer(this, rscope, ty, Box, |ty| ty::mk_box(tcx, ty))
+ let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
+ mk_pointer(this, rscope, &mt, Box, |ty| ty::mk_box(tcx, ty))
}
ast::TyUniq(ty) => {
- mk_pointer(this, rscope, ty, VStore(ty::VstoreUniq),
+ let mt = ast::MutTy { ty: ty, mutbl: ast::MutImmutable };
+ mk_pointer(this, rscope, &mt, VStore(ty::VstoreUniq),
|ty| ty::mk_uniq(tcx, ty))
}
ast::TyVec(ty) => {
tcx.sess.span_err(ast_ty.span, "bare `[]` is not a type");
// return /something/ so they can at least get more errors
- ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, ty), ty::VstoreUniq)
+ let vec_ty = ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty), None);
+ ty::mk_uniq(tcx, vec_ty)
}
ast::TyPtr(ref mt) => {
ty::mk_ptr(tcx, ty::mt {
ast::TyRptr(ref region, ref mt) => {
let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
debug!("ty_rptr r={}", r.repr(this.tcx()));
- mk_pointer(this, rscope, &*mt.ty, VStore(ty::VstoreSlice(r, mt.mutbl)),
+ mk_pointer(this, rscope, mt, VStore(ty::VstoreSlice(r)),
|ty| ty::mk_rptr(tcx, r, ty::mt {ty: ty, mutbl: mt.mutbl}))
}
ast::TyTup(ref fields) => {
Ok(ref r) => {
match *r {
const_eval::const_int(i) =>
- ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, ty),
- ty::VstoreFixed(i as uint)),
+ ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
+ Some(i as uint)),
const_eval::const_uint(i) =>
- ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, ty),
- ty::VstoreFixed(i as uint)),
+ ty::mk_vec(tcx, ast_ty_to_mt(this, rscope, ty),
+ Some(i as uint)),
_ => {
tcx.sess.span_fatal(
ast_ty.span, "expected constant expr for vector length");
fcx.infcx().next_region_var(
infer::PatternRegion(pat.span));
+ let check_err = || {
+ for &elt in before.iter() {
+ check_pat(pcx, elt, ty::mk_err());
+ }
+ for &elt in slice.iter() {
+ check_pat(pcx, elt, ty::mk_err());
+ }
+ for &elt in after.iter() {
+ check_pat(pcx, elt, ty::mk_err());
+ }
+ // See [Note-Type-error-reporting] in middle/typeck/infer/mod.rs
+ fcx.infcx().type_error_message_str_with_expected(
+ pat.span,
+ |expected, actual| {
+ expected.map_or("".to_owned(), |e| {
+ format!("mismatched types: expected `{}` but found {}",
+ e, actual)})},
+ Some(expected),
+ "a vector pattern".to_owned(),
+ None);
+ fcx.write_error(pat.id);
+ };
+
let (elt_type, region_var, mutbl) = match *structure_of(fcx,
pat.span,
expected) {
- ty::ty_vec(ty, vstore) => {
- match vstore {
- ty::VstoreSlice(r, m) => (ty, r, m),
- ty::VstoreUniq => {
- fcx.type_error_message(pat.span,
- |_| {
- ~"unique vector patterns are no \
- longer supported"
- },
- expected,
- None);
- (ty, default_region_var, ast::MutImmutable)
- }
- ty::VstoreFixed(_) => {
- (ty, default_region_var, ast::MutImmutable)
- }
- }
- }
- _ => {
- for &elt in before.iter() {
- check_pat(pcx, elt, ty::mk_err());
+ ty::ty_vec(mt, Some(_)) => (mt.ty, default_region_var, ast::MutImmutable),
+ ty::ty_uniq(t) => match ty::get(t).sty {
+ ty::ty_vec(mt, None) => {
+ fcx.type_error_message(pat.span,
+ |_| {
+ ~"unique vector patterns are no \
+ longer supported"
+ },
+ expected,
+ None);
+ (mt.ty, default_region_var, ast::MutImmutable)
}
- for &elt in slice.iter() {
- check_pat(pcx, elt, ty::mk_err());
+ _ => {
+ check_err();
+ return;
}
- for &elt in after.iter() {
- check_pat(pcx, elt, ty::mk_err());
+ },
+ ty::ty_rptr(r, mt) => match ty::get(mt.ty).sty {
+ ty::ty_vec(mt, None) => (mt.ty, r, mt.mutbl),
+ _ => {
+ check_err();
+ return;
}
- // See [Note-Type-error-reporting] in middle/typeck/infer/mod.rs
- fcx.infcx().type_error_message_str_with_expected(
- pat.span,
- |expected, actual| {
- expected.map_or("".to_owned(), |e| {
- format!("mismatched types: expected `{}` but found {}",
- e, actual)})},
- Some(expected),
- "a vector pattern".to_owned(),
- None);
- fcx.write_error(pat.id);
+ },
+ _ => {
+ check_err();
return;
}
};
}
match slice {
Some(slice_pat) => {
- let slice_ty = ty::mk_vec(tcx,
- elt_type,
- ty::VstoreSlice(region_var, mutbl)
- );
+ let slice_ty = ty::mk_slice(tcx,
+ region_var,
+ ty::mt {ty: elt_type, mutbl: mutbl});
check_pat(pcx, slice_pat, slice_ty);
}
None => ()
use middle::typeck::{param_numbered, param_self, param_index};
use middle::typeck::check::regionmanip::replace_late_bound_regions_in_fn_sig;
use util::common::indenter;
+use util::ppaux;
use util::ppaux::Repr;
use collections::HashSet;
fn search(&self, self_ty: ty::t) -> Option<MethodCallee> {
let span = self.self_expr.map_or(self.span, |e| e.span);
let self_expr_id = self.self_expr.map(|e| e.id);
+
let (self_ty, autoderefs, result) =
check::autoderef(
self.fcx, span, self_ty, self_expr_id, PreferMutLvalue,
None => None,
Some(method) => {
debug!("(searching for autoderef'd method) writing \
- adjustment {:?}", adjustment);
+ adjustment {:?} for {}", adjustment, self.ty_to_str( self_ty));
match adjustment {
Some((self_expr_id, adj)) => {
self.fcx.write_adjustment(self_expr_id, adj);
ty::ty_rptr(_, self_mt) => {
let region =
self.infcx().next_region_var(infer::Autoref(self.span));
+ let (extra_derefs, auto) = match ty::get(self_mt.ty).sty {
+ ty::ty_vec(_, None) => (0, ty::AutoBorrowVec(region, self_mt.mutbl)),
+ _ => (1, ty::AutoPtr(region, self_mt.mutbl)),
+ };
(ty::mk_rptr(tcx, region, self_mt),
ty::AutoDerefRef {
- autoderefs: autoderefs+1,
- autoref: Some(ty::AutoPtr(region, self_mt.mutbl))})
- }
- ty::ty_vec(self_ty, VstoreSlice(_, mutbl)) => {
- let region =
- self.infcx().next_region_var(infer::Autoref(self.span));
- (ty::mk_vec(tcx, self_ty, VstoreSlice(region, mutbl)),
- ty::AutoDerefRef {
- autoderefs: autoderefs,
- autoref: Some(ty::AutoBorrowVec(region, mutbl))})
+ autoderefs: autoderefs + extra_derefs,
+ autoref: Some(auto)})
}
+
ty::ty_trait(~ty::TyTrait {
def_id, ref substs, store: ty::RegionTraitStore(_, mutbl), bounds
}) => {
}
}
+ fn auto_slice_vec(&self, mt: ty::mt, autoderefs: uint) -> Option<MethodCallee> {
+ let tcx = self.tcx();
+ debug!("auto_slice_vec {}", ppaux::ty_to_str(tcx, mt.ty));
+
+ // First try to borrow to a slice
+ let entry = self.search_for_some_kind_of_autorefd_method(
+ AutoBorrowVec, autoderefs, [MutImmutable, MutMutable],
+ |m,r| ty::mk_slice(tcx, r,
+ ty::mt {ty:mt.ty, mutbl:m}));
+
+ if entry.is_some() {
+ return entry;
+ }
+
+ // Then try to borrow to a slice *and* borrow a pointer.
+ self.search_for_some_kind_of_autorefd_method(
+ AutoBorrowVecRef, autoderefs, [MutImmutable, MutMutable],
+ |m,r| {
+ let slice_ty = ty::mk_slice(tcx, r,
+ ty::mt {ty:mt.ty, mutbl:m});
+ // NB: we do not try to autoref to a mutable
+ // pointer. That would be creating a pointer
+ // to a temporary pointer (the borrowed
+ // slice), so any update the callee makes to
+ // it can't be observed.
+ ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:MutImmutable})
+ })
+ }
+
fn search_for_autosliced_method(&self,
self_ty: ty::t,
autoderefs: uint)
*/
let tcx = self.tcx();
+ debug!("search_for_autosliced_method {}", ppaux::ty_to_str(tcx, self_ty));
+
let sty = ty::get(self_ty).sty.clone();
match sty {
- ty_vec(ty, VstoreUniq) |
- ty_vec(ty, VstoreSlice(..)) |
- ty_vec(ty, VstoreFixed(_)) => {
- // First try to borrow to a slice
- let entry = self.search_for_some_kind_of_autorefd_method(
- AutoBorrowVec, autoderefs, [MutImmutable, MutMutable],
- |m,r| ty::mk_vec(tcx, ty, VstoreSlice(r, m)));
-
- if entry.is_some() { return entry; }
-
- // Then try to borrow to a slice *and* borrow a pointer.
- self.search_for_some_kind_of_autorefd_method(
- AutoBorrowVecRef, autoderefs, [MutImmutable, MutMutable],
- |m,r| {
- let slice_ty = ty::mk_vec(tcx, ty, VstoreSlice(r, m));
- // NB: we do not try to autoref to a mutable
- // pointer. That would be creating a pointer
- // to a temporary pointer (the borrowed
- // slice), so any update the callee makes to
- // it can't be observed.
- ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:MutImmutable})
- })
- }
+ ty_rptr(_, mt) => match ty::get(mt.ty).sty {
+ ty_vec(mt, None) => self.auto_slice_vec(mt, autoderefs),
+ _ => None
+ },
+ ty_uniq(t) => match ty::get(t).sty {
+ ty_vec(mt, None) => self.auto_slice_vec(mt, autoderefs),
+ _ => None
+ },
+ ty_vec(mt, Some(_)) => self.auto_slice_vec(mt, autoderefs),
ty_str(VstoreUniq) |
ty_str(VstoreFixed(_)) => {
let entry = self.search_for_some_kind_of_autorefd_method(
AutoBorrowVec, autoderefs, [MutImmutable],
- |_m,r| ty::mk_str(tcx, VstoreSlice(r, ())));
+ |_m,r| ty::mk_str(tcx, VstoreSlice(r)));
if entry.is_some() { return entry; }
self.search_for_some_kind_of_autorefd_method(
AutoBorrowVecRef, autoderefs, [MutImmutable],
|m,r| {
- let slice_ty = ty::mk_str(tcx, VstoreSlice(r, ()));
+ let slice_ty = ty::mk_str(tcx, VstoreSlice(r));
ty::mk_rptr(tcx, r, ty::mt {ty:slice_ty, mutbl:m})
})
}
});
debug!("after replacing bound regions, fty={}", self.ty_to_str(fty));
- // before we only checked whether self_ty could be a subtype
+ // Before, we only checked whether self_ty could be a subtype
// of rcvr_ty; now we actually make it so (this may cause
// variables to unify etc). Since we checked beforehand, and
// nothing has changed in the meantime, this unification
debug!("(is relevant?) explicit self is a region");
match ty::get(rcvr_ty).sty {
ty::ty_rptr(_, mt) => {
- mutability_matches(mt.mutbl, m) &&
- rcvr_matches_ty(self.fcx, mt.ty, candidate)
+ match ty::get(mt.ty).sty {
+ ty::ty_vec(_, None) => false,
+ _ => mutability_matches(mt.mutbl, m) &&
+ rcvr_matches_ty(self.fcx, mt.ty, candidate),
+ }
}
ty::ty_trait(~ty::TyTrait {
debug!("(is relevant?) explicit self is a unique pointer");
match ty::get(rcvr_ty).sty {
ty::ty_uniq(typ) => {
- rcvr_matches_ty(self.fcx, typ, candidate)
+ match ty::get(typ).sty {
+ ty::ty_vec(_, None) => false,
+ _ => rcvr_matches_ty(self.fcx, typ, candidate),
+ }
}
ty::ty_trait(~ty::TyTrait {
let tcx = fcx.ccx.tcx;
match lit.node {
- ast::LitStr(..) => ty::mk_str(tcx, ty::VstoreSlice(ty::ReStatic, ())),
+ ast::LitStr(..) => ty::mk_str(tcx, ty::VstoreSlice(ty::ReStatic)),
ast::LitBinary(..) => {
- ty::mk_vec(tcx, ty::mk_u8(),
- ty::VstoreSlice(ty::ReStatic, ast::MutImmutable))
+ ty::mk_slice(tcx, ty::ReStatic, ty::mt{ ty: ty::mk_u8(), mutbl: ast::MutImmutable })
}
ast::LitChar(_) => ty::mk_char(),
ast::LitInt(_, t) => ty::mk_mach_int(t),
ast::ExprVstore(ev, vst) => {
let typ = match ev.node {
ast::ExprLit(lit) if ast_util::lit_is_str(lit) => {
- let v = ast_expr_vstore_to_vstore(fcx, ev, vst, ());
+ let v = ast_expr_vstore_to_vstore(fcx, ev, vst);
ty::mk_str(tcx, v)
}
ast::ExprVec(ref args) => {
ast::ExprVstoreMutSlice => ast::MutMutable,
_ => ast::MutImmutable,
};
- let v = ast_expr_vstore_to_vstore(fcx, ev, vst, mutability);
+ let v = ast_expr_vstore_to_vstore(fcx, ev, vst);
let mut any_error = false;
let mut any_bot = false;
let t: ty::t = fcx.infcx().next_ty_var();
} else if any_bot {
ty::mk_bot()
} else {
- ty::mk_vec(tcx, t, v)
+ match v {
+ ty::VstoreFixed(sz) => ty::mk_vec(tcx,
+ ty::mt {ty: t, mutbl: mutability},
+ Some(sz)),
+ ty::VstoreUniq => ty::mk_uniq(tcx,
+ ty::mk_vec(tcx,
+ ty::mt {ty: t, mutbl: mutability},
+ None)), // Sadly, we know the length
+ // - Some(args.len()) - but
+ // must thow it away or cause
+ // confusion further down the
+ // pipeline. Hopefully we can
+ // remedy this later.
+ // See below (x3) too.
+ ty::VstoreSlice(r) => ty::mk_slice(tcx, r,
+ ty::mt {ty: t, mutbl: mutability}),
+ }
}
}
ast::ExprRepeat(element, count_expr) => {
ast::ExprVstoreMutSlice => ast::MutMutable,
_ => ast::MutImmutable,
};
- let v = ast_expr_vstore_to_vstore(fcx, ev, vst, mutability);
+ let tt = ast_expr_vstore_to_vstore(fcx, ev, vst);
let t = fcx.infcx().next_ty_var();
check_expr_has_type(fcx, element, t);
let arg_t = fcx.expr_ty(element);
} else if ty::type_is_bot(arg_t) {
ty::mk_bot()
} else {
- ty::mk_vec(tcx, t, v)
+ match tt {
+ ty::VstoreFixed(sz) => ty::mk_vec(tcx,
+ ty::mt {ty: t, mutbl: mutability},
+ Some(sz)),
+ ty::VstoreUniq => ty::mk_uniq(tcx,
+ ty::mk_vec(tcx,
+ ty::mt {ty: t, mutbl: mutability},
+ None)),
+ ty::VstoreSlice(r) => ty::mk_slice(tcx, r,
+ ty::mt {ty: t, mutbl: mutability}),
+ }
}
}
_ =>
fn is_vec(t: ty::t) -> bool {
match ty::get(t).sty {
ty::ty_vec(..) => true,
+ ty::ty_ptr(ty::mt{ty: t, ..}) | ty::ty_rptr(_, ty::mt{ty: t, ..}) |
+ ty::ty_box(t) | ty::ty_uniq(t) => match ty::get(t).sty {
+ ty::ty_vec(_, None) => true,
+ _ => false,
+ },
_ => false
}
}
for e in args.iter() {
check_expr_has_type(fcx, *e, t);
}
- let typ = ty::mk_vec(tcx, t, ty::VstoreFixed(args.len()));
+ let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
+ Some(args.len()));
fcx.write_ty(id, typ);
}
ast::ExprRepeat(element, count_expr) => {
fcx.write_bot(id);
}
else {
- let t = ty::mk_vec(tcx, t, ty::VstoreFixed(count));
+ let t = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
+ Some(count));
fcx.write_ty(id, t);
}
}
autoderef(fcx, expr.span, raw_base_t, Some(base.id),
lvalue_pref, |base_t, _| ty::index(base_t));
match field_ty {
- Some(ty) => {
+ Some(mt) => {
check_expr_has_type(fcx, idx, ty::mk_uint());
- fcx.write_ty(id, ty);
+ fcx.write_ty(id, mt.ty);
fcx.write_autoderef_adjustment(base.id, autoderefs);
}
None => {
return ty::type_is_c_like_enum(fcx.ccx.tcx, typ_s);
}
-pub fn ast_expr_vstore_to_vstore<M>(fcx: &FnCtxt,
- e: &ast::Expr,
- v: ast::ExprVstore,
- m: M)
- -> ty::Vstore<M> {
+pub fn ast_expr_vstore_to_vstore(fcx: &FnCtxt,
+ e: &ast::Expr,
+ v: ast::ExprVstore)
+ -> ty::Vstore {
match v {
ast::ExprVstoreUniq => ty::VstoreUniq,
ast::ExprVstoreSlice | ast::ExprVstoreMutSlice => {
match e.node {
ast::ExprLit(..) => {
// string literals and *empty slices* live in static memory
- ty::VstoreSlice(ty::ReStatic, m)
+ ty::VstoreSlice(ty::ReStatic)
}
ast::ExprVec(ref elements) if elements.len() == 0 => {
// string literals and *empty slices* live in static memory
- ty::VstoreSlice(ty::ReStatic, m)
+ ty::VstoreSlice(ty::ReStatic)
}
ast::ExprRepeat(..) |
ast::ExprVec(..) => {
// vector literals are temporaries on the stack
match fcx.tcx().region_maps.temporary_scope(e.id) {
Some(scope) => {
- ty::VstoreSlice(ty::ReScope(scope), m)
+ ty::VstoreSlice(ty::ReScope(scope))
}
None => {
// this slice occurs in a static somewhere
- ty::VstoreSlice(ty::ReStatic, m)
+ ty::VstoreSlice(ty::ReStatic)
}
}
}
let r_index_expr = ty::ReScope(index_expr.id);
match ty::get(indexed_ty).sty {
- ty::ty_str(ty::VstoreSlice(r_ptr, ())) |
- ty::ty_vec(_, ty::VstoreSlice(r_ptr, _)) => {
+ ty::ty_str(ty::VstoreSlice(r_ptr)) => {
rcx.fcx.mk_subr(true, infer::IndexSlice(index_expr.span),
r_index_expr, r_ptr);
}
+ ty::ty_rptr(r_ptr, mt) => match ty::get(mt.ty).sty {
+ ty::ty_vec(_, None) => {
+ rcx.fcx.mk_subr(true, infer::IndexSlice(index_expr.span),
+ r_index_expr, r_ptr);
+ }
+ _ => {}
+ },
_ => {}
}
fn fold_ty(&mut self, ty: ty::t) -> ty::t {
match ty::get(ty).sty {
- ty::ty_rptr(r, ty::mt {ty, ..}) |
- ty::ty_vec(ty, ty::VstoreSlice(r, _)) => {
+ ty::ty_rptr(r, ty::mt {ty, ..}) => {
self.relate(r);
self.stack.push(r);
ty_fold::super_fold_ty(self, ty);
// See above for details.
match ty::get(b).sty {
ty::ty_rptr(_, mt_b) => {
- return self.unpack_actual_value(a, |sty_a| {
- self.coerce_borrowed_pointer(a, sty_a, b, mt_b)
- });
+ match ty::get(mt_b.ty).sty {
+ ty::ty_vec(mt_b, None) => {
+ return self.unpack_actual_value(a, |sty_a| {
+ self.coerce_borrowed_vector(a, sty_a, b, mt_b.mutbl)
+ });
+ }
+ ty::ty_vec(_, _) => {},
+ _ => {
+ return self.unpack_actual_value(a, |sty_a| {
+ self.coerce_borrowed_pointer(a, sty_a, b, mt_b)
+ });
+ }
+ };
}
ty::ty_str(VstoreSlice(..)) => {
});
}
- ty::ty_vec(_, VstoreSlice(_, mutbl_b)) => {
- return self.unpack_actual_value(a, |sty_a| {
- self.coerce_borrowed_vector(a, sty_a, b, mutbl_b)
- });
- }
-
ty::ty_closure(~ty::ClosureTy {store: ty::RegionTraitStore(..), ..}) => {
return self.unpack_actual_value(a, |sty_a| {
self.coerce_borrowed_fn(a, sty_a, b)
};
let r_a = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
- let a_borrowed = ty::mk_str(self.get_ref().infcx.tcx, VstoreSlice(r_a, ()));
+ let a_borrowed = ty::mk_str(self.get_ref().infcx.tcx, VstoreSlice(r_a));
if_ok!(self.subtype(a_borrowed, b));
Ok(Some(@AutoDerefRef(AutoDerefRef {
autoderefs: 0,
let sub = Sub(*self.get_ref());
let r_borrow = self.get_ref().infcx.next_region_var(Coercion(self.get_ref().trace));
let ty_inner = match *sty_a {
- ty::ty_vec(ty, _) => ty,
+ ty::ty_uniq(t) | ty::ty_ptr(ty::mt{ty: t, ..}) |
+ ty::ty_rptr(_, ty::mt{ty: t, ..}) => match ty::get(t).sty {
+ ty::ty_vec(mt, None) => mt.ty,
+ _ => {
+ return self.subtype(a, b);
+ }
+ },
+ ty::ty_vec(mt, _) => mt.ty,
_ => {
return self.subtype(a, b);
}
};
- let a_borrowed = ty::mk_vec(self.get_ref().infcx.tcx, ty_inner,
- VstoreSlice(r_borrow, mutbl_b));
+ let a_borrowed = ty::mk_slice(self.get_ref().infcx.tcx, r_borrow,
+ mt {ty: ty_inner, mutbl: mutbl_b});
if_ok!(sub.tys(a_borrowed, b));
Ok(Some(@AutoDerefRef(AutoDerefRef {
autoderefs: 0,
fn vstores(&self,
vk: ty::terr_vstore_kind,
- a: ty::Vstore<()>,
- b: ty::Vstore<()>)
- -> cres<ty::Vstore<()>> {
+ a: ty::Vstore,
+ b: ty::Vstore)
+ -> cres<ty::Vstore> {
debug!("{}.vstores(a={:?}, b={:?})", self.tag(), a, b);
match (a, b) {
- (ty::VstoreSlice(a_r, _), ty::VstoreSlice(b_r, _)) => {
+ (ty::VstoreSlice(a_r), ty::VstoreSlice(b_r)) => {
self.contraregions(a_r, b_r).and_then(|r| {
- Ok(ty::VstoreSlice(r, ()))
+ Ok(ty::VstoreSlice(r))
})
}
}
(&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
- this.tys(a_inner, b_inner).and_then(|typ| Ok(ty::mk_uniq(tcx, typ)))
+ let typ = if_ok!(this.tys(a_inner, b_inner));
+
+ match (&ty::get(a_inner).sty, &ty::get(b_inner).sty) {
+ (&ty::ty_vec(_, None), &ty::ty_vec(_, None)) => Ok(ty::mk_uniq(tcx, typ)),
+ (&ty::ty_vec(_, None), _) |
+ (_, &ty::ty_vec(_, None)) => Err(ty::terr_sorts(expected_found(this, a, b))),
+ _ => Ok(ty::mk_uniq(tcx, typ)),
+ }
}
(&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
- this.mts(a_mt, b_mt).and_then(|mt| Ok(ty::mk_ptr(tcx, mt)))
+ let mt = if_ok!(this.mts(a_mt, b_mt));
+ match (&ty::get(a_mt.ty).sty, &ty::get(b_mt.ty).sty) {
+ (&ty::ty_vec(_, None), &ty::ty_vec(_, None)) => Ok(ty::mk_ptr(tcx, mt)),
+ (&ty::ty_vec(_, None), _) |
+ (_, &ty::ty_vec(_, None)) => Err(ty::terr_sorts(expected_found(this, a, b))),
+ _ => Ok(ty::mk_ptr(tcx, mt)),
+ }
}
(&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
- let r = if_ok!(this.contraregions(a_r, b_r));
- let mt = if_ok!(this.mts(a_mt, b_mt));
- Ok(ty::mk_rptr(tcx, r, mt))
+ let r = if_ok!(this.contraregions(a_r, b_r));
+ let mt = if_ok!(this.mts(a_mt, b_mt));
+
+ // This is a horible hack - historically, [T] was not treated as a type,
+ // so, for example, &T and &[U] should not unify. In fact the only thing
+ // &[U] should unify with is &[T]. We preserve that behaviour with this
+ // check. See also ty_uniq, ty_ptr.
+ match (&ty::get(a_mt.ty).sty, &ty::get(b_mt.ty).sty) {
+ (&ty::ty_vec(_, None), &ty::ty_vec(_, None)) => Ok(ty::mk_rptr(tcx, r, mt)),
+ (&ty::ty_vec(_, None), _) |
+ (_, &ty::ty_vec(_, None)) => Err(ty::terr_sorts(expected_found(this, a, b))),
+ _ => Ok(ty::mk_rptr(tcx, r, mt)),
+ }
}
- (&ty::ty_vec(a_inner, vs_a), &ty::ty_vec(b_inner, vs_b)) => {
- // This could be nicer if we didn't have to go through .mts(a, b).
- let (vs_a, mutbl_a) = match vs_a {
- ty::VstoreFixed(n) => (ty::VstoreFixed(n), ast::MutImmutable),
- ty::VstoreSlice(r, m) => (ty::VstoreSlice(r, ()), m),
- ty::VstoreUniq => (ty::VstoreUniq, ast::MutImmutable)
- };
- let (vs_b, mutbl_b) = match vs_b {
- ty::VstoreFixed(n) => (ty::VstoreFixed(n), ast::MutImmutable),
- ty::VstoreSlice(r, m) => (ty::VstoreSlice(r, ()), m),
- ty::VstoreUniq => (ty::VstoreUniq, ast::MutImmutable)
- };
- let a_mt = ty::mt {
- ty: a_inner,
- mutbl: mutbl_a
- };
- let b_mt = ty::mt {
- ty: b_inner,
- mutbl: mutbl_b
- };
- this.mts(&a_mt, &b_mt).and_then(|mt| {
- this.vstores(ty::terr_vec, vs_a, vs_b).and_then(|vs| {
- let store = match vs {
- ty::VstoreFixed(n) => ty::VstoreFixed(n),
- ty::VstoreSlice(r, _) => ty::VstoreSlice(r, mt.mutbl),
- ty::VstoreUniq => ty::VstoreUniq
- };
- Ok(ty::mk_vec(tcx, mt.ty, store))
- })
+ (&ty::ty_vec(ref a_mt, sz_a), &ty::ty_vec(ref b_mt, sz_b)) => {
+ this.mts(a_mt, b_mt).and_then(|mt| {
+ if sz_a == sz_b {
+ Ok(ty::mk_vec(tcx, mt, sz_a))
+ } else {
+ Err(ty::terr_sorts(expected_found(this, a, b)))
+ }
})
}
self.add_constraints_from_vstore(vstore, variance);
}
- ty::ty_vec(ty, vstore) => {
- self.add_constraints_from_vstore(vstore, variance);
- let mt = ty::mt {
- ty: ty,
- mutbl: match vstore {
- ty::VstoreSlice(_, m) => m,
- _ => ast::MutImmutable
- }
- };
- self.add_constraints_from_mt(&mt, variance);
+ ty::ty_vec(ref mt, _) => {
+ self.add_constraints_from_mt(mt, variance);
}
ty::ty_uniq(typ) | ty::ty_box(typ) => {
/// Adds constraints appropriate for a vector with Vstore `vstore`
/// appearing in a context with ambient variance `variance`
- fn add_constraints_from_vstore<M>(&mut self,
- vstore: ty::Vstore<M>,
- variance: VarianceTermPtr<'a>) {
+ fn add_constraints_from_vstore(&mut self,
+ vstore: ty::Vstore,
+ variance: VarianceTermPtr<'a>) {
match vstore {
- ty::VstoreSlice(r, _) => {
+ ty::VstoreSlice(r) => {
let contra = self.contravariant(variance);
self.add_constraints_from_region(r, contra);
}
let bound_str = bounds.repr(cx);
format!("{}{}{}{}", trait_store_to_str(cx, store), ty, bound_sep, bound_str)
}
- ty_vec(ty, vs) => {
- match vs {
- ty::VstoreFixed(n) => {
- format!("[{}, .. {}]", ty_to_str(cx, ty), n)
- }
- _ => {
- format!("{}[{}]", vs.repr(cx), ty_to_str(cx, ty))
- }
- }
- }
ty_str(vs) => {
match vs {
ty::VstoreFixed(n) => format!("str/{}", n),
ty::VstoreUniq => "~str".to_owned(),
- ty::VstoreSlice(r, ()) => format!("{}str", region_ptr_to_str(cx, r))
+ ty::VstoreSlice(r) => format!("{}str", region_ptr_to_str(cx, r))
}
}
+ ty_vec(ref mt, sz) => {
+ match sz {
+ Some(n) => {
+ format!("[{}, .. {}]", mt_to_str(cx, mt), n)
+ }
+ None => {
+ format!("[{}]", ty_to_str(cx, mt.ty))
+ }
+ }
+ }
}
}
match *self {
ty::VstoreFixed(n) => format!("{}", n),
ty::VstoreUniq => "~".to_owned(),
- ty::VstoreSlice(r, m) => {
- format!("{}{}", region_ptr_to_str(tcx, r), mutability_to_str(m))
- }
- }
- }
-}
-
-impl Repr for ty::Vstore<()> {
- fn repr(&self, tcx: &ctxt) -> ~str {
- match *self {
- ty::VstoreFixed(n) => format!("{}", n),
- ty::VstoreUniq => "~".to_owned(),
- ty::VstoreSlice(r, ()) => region_ptr_to_str(tcx, r)
+ ty::VstoreSlice(r) => region_ptr_to_str(tcx, r)
}
}
}