Refactor ty_vec represent &[T] as &([T])

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.
This commit is contained in:
Nick Cameron 2014-04-09 19:15:31 +12:00
parent 3757f01c9b
commit 37306c1d25
28 changed files with 759 additions and 510 deletions

View File

@ -137,8 +137,7 @@ pub fn parse_substs_data(data: &[u8], crate_num: ast::CrateNum, pos: uint, tcx:
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);
@ -150,11 +149,24 @@ fn parse_vstore<M>(st: &mut PState, conv: conv_did,
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,
@ -342,12 +354,12 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
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' => {
@ -396,7 +408,7 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::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);}
}
}

View File

@ -204,17 +204,17 @@ fn enc_bound_region(w: &mut MemWriter, cx: &ctxt, br: ty::BoundRegion) {
}
}
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);
}
}
}
@ -292,14 +292,18 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) {
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");

View File

@ -191,7 +191,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, pats: Vec<@Pat> ) {
}
}
}
ty::ty_vec(..) => {
ty::ty_vec(..) | ty::ty_rptr(..) => {
match *ctor {
vec(n) => Some(format!("vectors of length {}", n)),
_ => None
@ -258,50 +258,57 @@ fn is_useful(cx: &MatchCheckCtxt, m: &matrix, v: &[@Pat]) -> useful {
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
}
ty::ty_vec(_, ty::VstoreFixed(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
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(),
}
}
});
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
not_useful
}
ty::ty_vec(_, Some(n)) => {
is_useful_specialized(cx, m, v, vec(n), n, left_ty)
}
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
}
_ => {
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)
let arity = ctor_arity(cx, &single, left_ty);
is_useful_specialized(cx, m, v, single, arity, left_ty)
}
}
}
@ -394,17 +401,16 @@ fn is_wild(cx: &MatchCheckCtxt, p: @Pat) -> bool {
}
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() {
@ -441,7 +447,7 @@ fn missing_ctor(cx: &MatchCheckCtxt,
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() {
@ -464,8 +470,19 @@ fn missing_ctor(cx: &MatchCheckCtxt,
_ => 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 {
@ -511,31 +528,37 @@ fn missing_ctor(cx: &MatchCheckCtxt,
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
}
}

View File

@ -918,7 +918,6 @@ fn check_heap_type(cx: &Context, span: Span, ty: ty::t) {
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;
@ -1156,10 +1155,13 @@ fn check_unused_result(cx: &Context, s: &ast::Stmt) {
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`")
}
_ => {}
},
_ => {}
}
}

View File

@ -170,7 +170,6 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
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))
@ -180,13 +179,12 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
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)))
}
@ -204,7 +202,7 @@ pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
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))))
}
@ -483,8 +481,8 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
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(..) => {
@ -785,7 +783,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
//! 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(),
@ -868,13 +866,10 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
*/
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(
@ -1307,6 +1302,11 @@ impl Repr for InteriorKind {
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

View File

@ -438,7 +438,8 @@ impl<'a,'b> Clone for ArmData<'a, 'b> {
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 {
@ -1109,8 +1110,9 @@ fn extract_vec_elems<'a>(
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]));

View File

@ -188,7 +188,7 @@ fn decl_fn(llmod: ModuleRef, name: &str, cc: lib::llvm::CallConv,
// 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);
}
@ -260,7 +260,7 @@ pub fn decl_rust_fn(ccx: &CrateContext, has_env: bool,
// 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);
@ -664,8 +664,12 @@ pub fn iter_structural_ty<'r,
}
})
}
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);

View File

@ -653,7 +653,7 @@ pub fn trans_call_inner<'a>(
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));
}
_ => {}

View File

@ -711,8 +711,12 @@ pub enum MonoDataClass {
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

View File

@ -139,8 +139,11 @@ fn const_deref(cx: &CrateContext, v: ValueRef, t: ty::t, explicit: bool)
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)
@ -244,7 +247,7 @@ pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef
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)
@ -432,14 +435,21 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr,
"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;

View File

@ -2202,27 +2202,27 @@ fn type_metadata(cx: &CrateContext,
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)

View File

@ -240,8 +240,8 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>,
// 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]));
@ -1505,16 +1505,19 @@ pub enum cast_kind {
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
}
}
@ -1717,7 +1720,10 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
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) => {
@ -1731,16 +1737,21 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
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))
}
}
}
_ => {

View File

@ -83,19 +83,21 @@ fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t {
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
}
}
@ -284,12 +286,22 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'
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| {

View File

@ -54,7 +54,7 @@ impl<'a> Reflector<'a> {
// 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());
@ -121,10 +121,10 @@ impl<'a> Reflector<'a> {
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());
@ -168,17 +168,12 @@ impl<'a> Reflector<'a> {
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 {
@ -188,19 +183,37 @@ impl<'a> Reflector<'a> {
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) => {

View File

@ -162,8 +162,10 @@ pub fn trans_slice_vstore<'a>(
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);
@ -461,6 +463,35 @@ pub fn get_fixed_base_and_byte_len(bcx: &Block,
(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)
@ -477,16 +508,17 @@ pub fn get_base_and_len(bcx: &Block,
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 {

View File

@ -117,14 +117,17 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
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)
}
@ -133,8 +136,8 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
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(..) => {
@ -153,7 +156,8 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
}
}
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))
}
@ -215,18 +219,21 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
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(..)) => {
@ -238,8 +245,8 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
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(_) => {
@ -271,7 +278,9 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
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")

View File

@ -130,16 +130,14 @@ pub struct mt {
}
#[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)]
@ -735,8 +733,8 @@ pub enum sty {
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),
@ -813,7 +811,7 @@ pub enum type_err {
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>),
@ -1179,13 +1177,9 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
return f;
}
match &st {
&ty_str(VstoreSlice(r, ())) => {
&ty_str(VstoreSlice(r)) => {
flags |= rflags(r);
}
&ty_vec(ty, VstoreSlice(r, _)) => {
flags |= rflags(r);
flags |= get(ty).flags;
}
&ty_nil | &ty_bool | &ty_char | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
&ty_str(_) => {}
// You might think that we could just return ty_err for
@ -1212,10 +1206,10 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t {
_ => {}
}
}
&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) => {
@ -1349,7 +1343,7 @@ pub fn mk_mach_float(tm: ast::FloatTy) -> t {
#[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))
}
@ -1385,8 +1379,16 @@ pub fn mk_nil_ptr(cx: &ctxt) -> t {
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)) }
@ -1465,8 +1467,8 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) {
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) |
@ -1601,13 +1603,23 @@ pub fn type_is_self(ty: t) -> bool {
}
}
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)
}
}
@ -1621,7 +1633,12 @@ pub fn type_is_simd(cx: &ctxt, ty: t) -> bool {
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"),
}
}
@ -1655,8 +1672,13 @@ pub fn type_is_boxed(ty: t) -> bool {
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
}
}
@ -1669,7 +1691,7 @@ pub fn type_is_unsafe_ptr(ty: t) -> bool {
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
}
}
@ -1743,8 +1765,7 @@ fn type_needs_unwind_cleanup_(cx: &ctxt, ty: t,
!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 {
@ -2086,19 +2107,11 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
borrowed_contents(r, mt.mutbl))
}
ty_vec(ty, VstoreUniq) => {
tc_ty(cx, ty, cache).owned_pointer()
ty_vec(mt, _) => {
tc_mt(cx, mt, cache)
}
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_str(VstoreSlice(r, ())) => {
ty_str(VstoreSlice(r)) => {
borrowed_contents(r, ast::MutImmutable)
}
@ -2321,8 +2334,8 @@ pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
// 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 |
@ -2338,7 +2351,7 @@ pub fn is_instantiable(cx: &ctxt, r_ty: t) -> bool {
ty_err |
ty_param(_) |
ty_self(_) |
ty_vec(_, _) => {
ty_vec(_, None) => {
false
}
ty_box(typ) | ty_uniq(typ) => {
@ -2459,8 +2472,8 @@ pub fn is_type_representable(cx: &ctxt, sp: Span, ty: t) -> Representability {
}
// 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.
@ -2604,21 +2617,34 @@ pub fn type_is_c_like_enum(cx: &ctxt, ty: t) -> bool {
// 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
}
}
@ -2723,8 +2749,7 @@ pub fn ty_region(tcx: &ctxt,
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,
@ -2929,12 +2954,22 @@ pub fn adjust_ty(cx: &ctxt,
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 => {
@ -4152,10 +4187,10 @@ pub fn normalize_ty(cx: &ctxt, t: t) -> t {
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)
}
}
@ -4575,9 +4610,15 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
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);

View File

@ -68,7 +68,7 @@ pub trait TypeFolder {
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)
}
@ -147,8 +147,8 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
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))
@ -191,13 +191,13 @@ pub fn super_fold_sty<T:TypeFolder>(this: &mut T,
}
}
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)),
}
}

View File

@ -389,6 +389,12 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
}
}
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.
@ -396,18 +402,20 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
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"
@ -421,8 +429,8 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
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));
}
_ => {}
}
@ -432,8 +440,8 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
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(
@ -456,7 +464,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
_ => {}
}
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();
@ -479,16 +487,19 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
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 {
@ -499,7 +510,7 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
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) => {
@ -612,11 +623,11 @@ pub fn ast_ty_to_ty<AC:AstConv, RS:RegionScope>(
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");

View File

@ -616,48 +616,58 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
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)
}
}
}
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)
}
_ => {
check_err();
return;
}
},
ty::ty_rptr(r, mt) => match ty::get(mt.ty).sty {
ty::ty_vec(mt, None) => (mt.ty, r, mt.mutbl),
_ => {
check_err();
return;
}
},
_ => {
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);
check_err();
return;
}
};
@ -666,10 +676,9 @@ pub fn check_pat(pcx: &pat_ctxt, pat: &ast::Pat, expected: ty::t) {
}
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 => ()

View File

@ -93,6 +93,7 @@ use middle::typeck::{MethodStatic, MethodObject};
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;
@ -332,6 +333,7 @@ impl<'a> LookupContext<'a> {
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,
@ -721,7 +723,7 @@ impl<'a> LookupContext<'a> {
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);
@ -765,19 +767,16 @@ impl<'a> LookupContext<'a> {
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
}) => {
@ -808,6 +807,35 @@ impl<'a> LookupContext<'a> {
}
}
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)
@ -818,44 +846,32 @@ impl<'a> LookupContext<'a> {
*/
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})
})
}
@ -1163,7 +1179,7 @@ impl<'a> LookupContext<'a> {
});
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
@ -1293,8 +1309,11 @@ impl<'a> LookupContext<'a> {
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 {
@ -1312,7 +1331,10 @@ impl<'a> LookupContext<'a> {
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 {

View File

@ -1286,10 +1286,9 @@ pub fn check_lit(fcx: &FnCtxt, lit: &ast::Lit) -> ty::t {
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),
@ -2458,7 +2457,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
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) => {
@ -2466,7 +2465,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
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();
@ -2485,7 +2484,23 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
} 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) => {
@ -2495,7 +2510,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
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);
@ -2504,7 +2519,17 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
} 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}),
}
}
}
_ =>
@ -2949,6 +2974,11 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
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
}
}
@ -3005,7 +3035,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
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) => {
@ -3021,7 +3052,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
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);
}
}
@ -3089,9 +3121,9 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
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 => {
@ -3833,33 +3865,32 @@ pub fn type_is_c_like_enum(fcx: &FnCtxt, sp: Span, typ: ty::t) -> bool {
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)
}
}
}

View File

@ -928,11 +928,17 @@ fn constrain_index(rcx: &mut Rcx,
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);
}
_ => {}
},
_ => {}
}

View File

@ -100,8 +100,7 @@ pub fn relate_nested_regions(tcx: &ty::ctxt,
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);

View File

@ -102,9 +102,19 @@ impl<'f> Coerce<'f> {
// 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(..)) => {
@ -113,12 +123,6 @@ impl<'f> Coerce<'f> {
});
}
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)
@ -266,7 +270,7 @@ impl<'f> Coerce<'f> {
};
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,
@ -287,14 +291,21 @@ impl<'f> Coerce<'f> {
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,

View File

@ -270,15 +270,15 @@ pub trait Combine {
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))
})
}
@ -510,48 +510,49 @@ pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
}
(&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)))
}
})
}

View File

@ -717,16 +717,8 @@ impl<'a> ConstraintContext<'a> {
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) => {
@ -799,11 +791,11 @@ impl<'a> ConstraintContext<'a> {
/// 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);
}

View File

@ -395,23 +395,23 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> ~str {
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))
}
}
}
}
}
@ -853,19 +853,7 @@ impl Repr for ty::Vstore {
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)
}
}
}