Use ty_rptr/ty_uniq(ty_trait) rather than TraitStore to represent trait types.
Also addresses (but doesn't close) #12470.
Part of the work towards DST (#12938).
[breaking-change] lifetime parameters in `&mut trait` are now invariant. They used to be contravariant.
assert_eq!(next(st), '[');
let def = parse_def(st, NominalType, |x,y| conv(x,y));
let substs = parse_substs(st, |x,y| conv(x,y));
- let store = parse_trait_store(st, |x,y| conv(x,y));
let bounds = parse_bounds(st, |x,y| conv(x,y));
assert_eq!(next(st), ']');
- return ty::mk_trait(st.tcx, def, substs, store, bounds.builtin_bounds);
+ return ty::mk_trait(st.tcx, def, substs, bounds.builtin_bounds);
}
'p' => {
let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
ty::ty_trait(box ty::TyTrait {
def_id,
ref substs,
- store,
bounds
}) => {
mywrite!(w, "x[{}|", (cx.ds)(def_id));
enc_substs(w, cx, substs);
- enc_trait_store(w, cx, store);
let bounds = ty::ParamBounds {builtin_bounds: bounds,
trait_bounds: Vec::new()};
enc_bounds(w, cx, &bounds);
fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span: Span) {
check_cast_for_escaping_regions(cx, source_ty, target_ty, span);
match ty::get(target_ty).sty {
- ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
- check_trait_cast_bounds(cx, span, source_ty, bounds);
- }
+ ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ ty, .. }) => match ty::get(ty).sty {
+ ty::ty_trait(box ty::TyTrait { bounds, .. }) => {
+ check_trait_cast_bounds(cx, span, source_ty, bounds);
+ }
+ _ => {}
+ },
_ => {}
}
}
{
// Determine what type we are casting to; if it is not a trait, then no
// worries.
- match ty::get(target_ty).sty {
- ty::ty_trait(..) => {}
- _ => { return; }
+ if !ty::type_is_trait(target_ty) {
+ return;
}
// Collect up the regions that appear in the target type. We want to
n_box += 1;
}
ty::ty_uniq(_) |
- ty::ty_trait(box ty::TyTrait {
- store: ty::UniqTraitStore, ..
- }) |
ty::ty_closure(box ty::ClosureTy {
store: ty::UniqTraitStore,
..
pub fn opt_deref_kind(t: ty::t) -> Option<deref_kind> {
match ty::get(t).sty {
ty::ty_uniq(_) |
- ty::ty_trait(box ty::TyTrait { store: ty::UniqTraitStore, .. }) |
ty::ty_closure(box 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_trait(box ty::TyTrait {
- store: ty::RegionTraitStore(r, mutbl),
- ..
- }) => {
- let kind = ty::BorrowKind::from_mutbl(mutbl);
- Some(deref_ptr(BorrowedPtr(kind, r)))
- }
ty::ty_closure(box ty::ClosureTy {
store: ty::RegionTraitStore(r, _),
fn find_ptr(&self) -> Option<uint> {
self.tys.iter().position(|&ty| {
match ty::get(ty).sty {
- ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty {
- ty::ty_vec(_, None) | ty::ty_str => false,
+ ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
+ ty::ty_vec(_, None) | ty::ty_str| ty::ty_trait(..) => false,
_ => true,
},
- ty::ty_uniq(..) | ty::ty_box(..) |
- ty::ty_bare_fn(..) => true,
+ ty::ty_box(..) | ty::ty_bare_fn(..) => true,
// Is that everything? Would closures or slices qualify?
_ => false
}
match ty::get(ret_ty).sty {
// `~` pointer return values never alias because ownership
// is transferred
+ ty::ty_uniq(it) if match ty::get(it).sty {
+ ty::ty_str | ty::ty_vec(..) | ty::ty_trait(..) => true, _ => false
+ } => {}
ty::ty_uniq(_) => {
attrs.push((lib::llvm::ReturnIndex as uint, lib::llvm::NoAliasAttribute as u64));
}
// We can also mark the return value as `nonnull` in certain cases
match ty::get(ret_ty).sty {
// These are not really pointers but pairs, (pointer, len)
- ty::ty_rptr(_, ty::mt { ty: it, .. }) |
+ ty::ty_uniq(it) |
ty::ty_rptr(_, ty::mt { ty: it, .. }) if match ty::get(it).sty {
- ty::ty_str | ty::ty_vec(..) => true, _ => false
+ ty::ty_str | ty::ty_vec(..) | ty::ty_trait(..) => true, _ => false
} => {}
ty::ty_uniq(_) | ty::ty_rptr(_, _) => {
attrs.push((lib::llvm::ReturnIndex as uint, lib::llvm::NonNullAttribute as u64));
ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
type_is_newtype_immediate(ccx, ty) || ty::type_is_bot(ty) ||
ty::type_is_simd(tcx, ty);
- if simple {
+ if simple && !ty::type_is_trait(ty) {
return true;
}
match ty::get(ty).sty {
let dv = match ty::get(t).sty {
ty::ty_ptr(mt) | ty::ty_rptr(_, mt) => {
match ty::get(mt.ty).sty {
- ty::ty_vec(_, None) | ty::ty_str => cx.sess().bug("unexpected slice"),
+ ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => {
+ cx.sess().bug("unexpected unsized type")
+ }
_ => const_deref_ptr(cx, v),
}
}
* on whether type is immediate or not.
*/
- if type_is_zero_size(ccx, ty) {
- ByValue
- } else if type_is_immediate(ccx, ty) {
+ if type_is_immediate(ccx, ty) {
ByValue
} else {
ByRef
// unique ptr (~) -> {~ :pointee-uid:}
// @-ptr (@) -> {@ :pointee-uid:}
// sized vec ([T, ..x]) -> {[:size:] :element-uid:}
- // vec slice (&[T]) -> {&<mut> [] :element-uid:}
- // trait (~ | &[mut] T) -> {:sigil: trait_:svh: / :node-id:_<(:param-uid:),*> }
+ // unsized vec ([T]) -> {[] :element-uid:}
+ // trait (T) -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
// closure -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
// :return-type-uid: : (:bounds:)*}
// function -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
unique_type_id.push_str(inner_type_id.as_slice());
},
- ty::ty_vec(ty::mt { ty: inner_type, mutbl }, optional_length) => {
+ ty::ty_vec(ty::mt { ty: inner_type, .. }, optional_length) => {
match optional_length {
Some(len) => {
unique_type_id.push_str(format!("[{}]", len).as_slice());
}
None => {
- unique_type_id.push_char('&');
-
- if mutbl == ast::MutMutable {
- unique_type_id.push_str("mut");
- }
-
unique_type_id.push_str("[]");
}
};
unique_type_id.push_str(inner_type_id.as_slice());
},
ty::ty_trait(ref trait_data) => {
- match trait_data.store {
- ty::UniqTraitStore => unique_type_id.push_char('~'),
- ty::RegionTraitStore(_, ast::MutMutable) => unique_type_id.push_str("&mut"),
- ty::RegionTraitStore(_, ast::MutImmutable) => unique_type_id.push_char('&'),
- };
-
unique_type_id.push_str("trait ");
from_def_id_and_substs(self,
let i8_t = ty::mk_i8();
heap_vec_metadata(cx, pointee_type, i8_t, unique_type_id, usage_site_span)
}
+ ty::ty_trait(box ty::TyTrait {
+ def_id,
+ ref substs,
+ ref bounds
+ }) => {
+ MetadataCreationResult::new(
+ trait_metadata(cx, def_id, t, substs, ty::UniqTraitStore,
+ bounds, unique_type_id),
+ false)
+ }
_ => {
let pointee_metadata = type_metadata(cx, pointee_type, usage_site_span);
return_if_created_in_meantime!();
ty::ty_str => {
vec_slice_metadata(cx, t, ty::mk_i8(), unique_type_id, usage_site_span)
}
+ ty::ty_trait(box ty::TyTrait {
+ def_id,
+ ref substs,
+ ref bounds
+ }) => {
+ MetadataCreationResult::new(
+ trait_metadata(cx, def_id, t, substs,
+ ty::RegionTraitStore(ty::ReStatic, mt.mutbl),
+ bounds, unique_type_id),
+ false)
+ }
_ => {
let pointee = type_metadata(cx, mt.ty, usage_site_span);
return_if_created_in_meantime!();
ty::ty_closure(ref closurety) => {
subroutine_type_metadata(cx, unique_type_id, &closurety.sig, usage_site_span)
}
- ty::ty_trait(box ty::TyTrait {
- def_id,
- ref substs,
- store,
- ref bounds
- }) => {
- MetadataCreationResult::new(
- trait_metadata(cx, def_id, t, substs, store, bounds, unique_type_id),
- false)
- }
ty::ty_struct(def_id, ref substs) => {
prepare_struct_metadata(cx,
t,
}
ast::ExprCast(ref val, _) => {
// DPS output mode means this is a trait cast:
- match ty::get(node_id_type(bcx, expr.id)).sty {
- ty::ty_trait(..) => {
- let datum = unpack_datum!(bcx, trans(bcx, &**val));
- meth::trans_trait_cast(bcx, datum, expr.id, dest)
- }
- _ => {
- bcx.tcx().sess.span_bug(expr.span,
- "expr_cast of non-trait");
- }
+ if ty::type_is_trait(node_id_type(bcx, expr.id)) {
+ let datum = unpack_datum!(bcx, trans(bcx, &**val));
+ meth::trans_trait_cast(bcx, datum, expr.id, dest)
+ } else {
+ bcx.tcx().sess.span_bug(expr.span,
+ "expr_cast of non-trait");
}
}
ast::ExprAssignOp(op, ref dst, ref src) => {
ty::ty_float(..) => cast_float,
ty::ty_ptr(..) => cast_pointer,
ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty{
- ty::ty_vec(_, None) | ty::ty_str => cast_other,
+ ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => cast_other,
_ => cast_pointer,
},
ty::ty_bare_fn(..) => cast_pointer,
let r = match ty::get(datum.ty).sty {
ty::ty_uniq(content_ty) => {
match ty::get(content_ty).sty {
- ty::ty_vec(_, None) | ty::ty_str
- => bcx.tcx().sess.span_bug(expr.span, "unexpected ~[T]"),
+ ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..)
+ => bcx.tcx().sess.span_bug(expr.span, "unexpected unsized box"),
_ => deref_owned_pointer(bcx, expr, datum, content_ty),
}
}
ty::ty_ptr(ty::mt { ty: content_ty, .. }) |
ty::ty_rptr(_, ty::mt { ty: content_ty, .. }) => {
match ty::get(content_ty).sty {
- ty::ty_vec(_, None) | ty::ty_str
- => bcx.tcx().sess.span_bug(expr.span, "unexpected &[T]"),
+ ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..)
+ => bcx.tcx().sess.span_bug(expr.span, "unexpected unsized reference"),
_ => {
assert!(!ty::type_needs_drop(bcx.tcx(), datum.ty));
ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ) => {
match ty::get(typ).sty {
- ty::ty_vec(_, None) | ty::ty_str => t,
+ ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => t,
_ => {
let llty = sizing_type_of(ccx, typ);
// `Box<ZeroSizeType>` does not allocate.
decr_refcnt_maybe_free(bcx, v0, body_ty)
}
ty::ty_uniq(content_ty) => {
- let llbox = Load(bcx, v0);
- let not_null = IsNotNull(bcx, llbox);
match ty::get(content_ty).sty {
ty::ty_vec(mt, None) => {
+ let llbox = Load(bcx, v0);
+ let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, mt.ty);
// FIXME: #13994: the old `Box<[T]>` will not support sized deallocation
})
}
ty::ty_str => {
+ let llbox = Load(bcx, v0);
+ let not_null = IsNotNull(bcx, llbox);
with_cond(bcx, not_null, |bcx| {
let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
let bcx = tvec::make_drop_glue_unboxed(bcx, llbox, unit_ty);
trans_exchange_free(bcx, llbox, 0, 8)
})
}
+ ty::ty_trait(..) => {
+ let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
+ // Only drop the value when it is non-null
+ with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue)), |bcx| {
+ let dtor_ptr = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
+ let dtor = Load(bcx, dtor_ptr);
+ Call(bcx,
+ dtor,
+ [PointerCast(bcx, lluniquevalue, Type::i8p(bcx.ccx()))],
+ []);
+ bcx
+ })
+ }
_ => {
+ 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_ty(bcx, llbox, content_ty)
}
}
}
- ty::ty_trait(box ty::TyTrait { store: ty::UniqTraitStore, .. }) => {
- let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]);
- // Only drop the value when it is non-null
- with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue)), |bcx| {
- let dtor_ptr = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable]));
- let dtor = Load(bcx, dtor_ptr);
- Call(bcx, dtor, [PointerCast(bcx, lluniquevalue, Type::i8p(bcx.ccx()))], []);
- bcx
- })
- }
ty::ty_closure(ref f) if f.store == ty::UniqTraitStore => {
let box_cell_v = GEPi(bcx, v0, [0u, abi::fn_field_box]);
let env = Load(bcx, box_cell_v);
let extra = extra.append(self.c_mt(mt).as_slice());
self.visit("evec_fixed", extra.as_slice())
}
- ty::ty_vec(..) | ty::ty_str => fail!("unexpected unsized type"),
+ ty::ty_vec(..) | ty::ty_str | ty::ty_trait(..) => fail!("unexpected unsized type"),
// Should remove mt from box and uniq.
ty::ty_box(typ) => {
let extra = self.c_mt(&ty::mt {
self.visit("evec_uniq", extra.as_slice())
}
ty::ty_str => self.visit("estr_uniq", &[]),
+ ty::ty_trait(..) => {
+ let extra = [
+ self.c_slice(token::intern_and_get_ident(
+ ty_to_str(tcx, t).as_slice()))
+ ];
+ self.visit("trait", extra);
+ }
_ => {
let extra = self.c_mt(&ty::mt {
ty: typ,
extra.as_slice())
}
ty::ty_str => self.visit("estr_slice", &[]),
+ ty::ty_trait(..) => {
+ let extra = [
+ self.c_slice(token::intern_and_get_ident(
+ ty_to_str(tcx, t).as_slice()))
+ ];
+ self.visit("trait", extra);
+ }
_ => {
let extra = self.c_mt(mt);
self.visit("rptr", extra.as_slice())
})
}
- ty::ty_trait(..) => {
- let extra = [
- self.c_slice(token::intern_and_get_ident(
- ty_to_str(tcx, t).as_slice()))
- ];
- self.visit("trait", extra);
- }
-
// Miscellaneous extra types
ty::ty_infer(_) => self.leaf("infer"),
ty::ty_err => self.leaf("err"),
ty::ty_float(t) => Type::float_from_ty(cx, t),
ty::ty_box(..) |
- ty::ty_uniq(..) |
ty::ty_ptr(..) => Type::i8p(cx),
+ ty::ty_uniq(ty) => {
+ match ty::get(ty).sty {
+ ty::ty_trait(..) => Type::opaque_trait(cx),
+ _ => Type::i8p(cx),
+ }
+ }
ty::ty_rptr(_, mt) => {
match ty::get(mt.ty).sty {
ty::ty_vec(_, None) | ty::ty_str => {
Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false)
}
+ ty::ty_trait(..) => Type::opaque_trait(cx),
_ => Type::i8p(cx),
}
}
ty::ty_bare_fn(..) => Type::i8p(cx),
ty::ty_closure(..) => Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false),
- ty::ty_trait(..) => Type::opaque_trait(cx),
ty::ty_vec(mt, Some(size)) => {
Type::array(&sizing_type_of(cx, mt.ty), size as u64)
}
ty::ty_infer(..) | ty::ty_param(..) |
- ty::ty_err(..) | ty::ty_vec(_, None) | ty::ty_str => {
+ ty::ty_err(..) | ty::ty_vec(_, None) | ty::ty_str | ty::ty_trait(..) => {
cx.sess().bug(format!("fictitious type {:?} in sizing_type_of()",
ty::get(t).sty).as_slice())
}
match ty::get(typ).sty {
ty::ty_vec(mt, None) => Type::vec(cx, &type_of(cx, mt.ty)).ptr_to(),
ty::ty_str => Type::vec(cx, &Type::i8(cx)).ptr_to(),
+ ty::ty_trait(..) => Type::opaque_trait(cx),
_ => type_of(cx, typ).ptr_to(),
}
}
// This means we get a nicer name in the output
cx.tn.find_type("str_slice").unwrap()
}
+ ty::ty_trait(..) => Type::opaque_trait(cx),
_ => type_of(cx, mt.ty).ptr_to(),
}
}
let fn_ty = type_of_fn_from_ty(cx, t).ptr_to();
Type::struct_(cx, [fn_ty, Type::i8p(cx)], false)
}
- ty::ty_trait(..) => Type::opaque_trait(cx),
ty::ty_tup(..) => {
let repr = adt::represent_type(cx, t);
adt::type_of(cx, &*repr)
ty::ty_vec(_, None) => cx.sess().bug("type_of with unsized ty_vec"),
ty::ty_str => cx.sess().bug("type_of with unsized (bare) ty_str"),
+ ty::ty_trait(..) => cx.sess().bug("type_of with unsized ty_trait"),
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")
pub struct TyTrait {
pub def_id: DefId,
pub substs: Substs,
- pub store: TraitStore,
pub bounds: BuiltinBounds
}
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
flags |= sflags(substs);
}
- &ty_trait(box ty::TyTrait { ref substs, store, .. }) => {
+ &ty_trait(box ty::TyTrait { ref substs, .. }) => {
flags |= sflags(substs);
- match store {
- RegionTraitStore(r, _) => {
- flags |= rflags(r);
- }
- _ => {}
- }
}
&ty_box(tt) | &ty_uniq(tt) => {
flags |= get(tt).flags
pub fn mk_trait(cx: &ctxt,
did: ast::DefId,
substs: Substs,
- store: TraitStore,
bounds: BuiltinBounds)
-> t {
// take a copy of substs so that we own the vectors inside
let inner = box TyTrait {
def_id: did,
substs: substs,
- store: store,
bounds: bounds
};
mk_t(cx, ty_trait(inner))
pub fn type_is_structural(ty: t) -> bool {
match get(ty).sty {
- ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) | ty_trait(..) |
+ ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
ty_vec(_, Some(_)) => true,
- _ => type_is_slice(ty)
+ _ => type_is_slice(ty) | type_is_trait(ty)
}
}
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) | ty_str => false,
+ ty_vec(_, None) | ty_str | ty_trait(..) => false,
_ => true
},
_ => false
pub fn type_is_unique(ty: t) -> bool {
match get(ty).sty {
- ty_uniq(_) => true,
+ ty_uniq(_) => match get(ty).sty {
+ ty_trait(..) => false,
+ _ => true
+ },
_ => false
}
}
}
}
- ty_trait(box ty::TyTrait { store, bounds, .. }) => {
- object_contents(cx, store, bounds)
+ ty_trait(box ty::TyTrait { bounds, .. }) => {
+ object_contents(cx, bounds)
}
ty_ptr(ref mt) => {
fn closure_contents(cx: &ctxt, cty: &ClosureTy) -> TypeContents {
// Closure contents are just like trait contents, but with potentially
// even more stuff.
- let st = object_contents(cx, cty.store, cty.bounds);
+ let st = object_contents(cx, cty.bounds);
+
+ let st = match cty.store {
+ UniqTraitStore => {
+ st.owned_pointer()
+ }
+ RegionTraitStore(r, mutbl) => {
+ st.reference(borrowed_contents(r, mutbl))
+ }
+ };
// This also prohibits "@once fn" from being copied, which allows it to
// be called. Neither way really makes much sense.
}
fn object_contents(cx: &ctxt,
- store: TraitStore,
bounds: BuiltinBounds)
-> TypeContents {
// These are the type contents of the (opaque) interior
- let contents = kind_bounds_to_contents(cx, bounds, []);
-
- match store {
- UniqTraitStore => {
- contents.owned_pointer()
- }
- RegionTraitStore(r, mutbl) => {
- contents.reference(borrowed_contents(r, mutbl))
- }
- }
+ kind_bounds_to_contents(cx, bounds, [])
}
fn kind_bounds_to_contents(cx: &ctxt,
pub fn type_is_trait(ty: t) -> bool {
match get(ty).sty {
+ ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) => match get(ty).sty {
+ ty_trait(..) => true,
+ _ => false
+ },
ty_trait(..) => true,
_ => false
}
match get(t).sty {
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) | ty_str => None,
+ ty_vec(_, None) | ty_str | ty_trait(..) => 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) | ty_str => None,
+ ty_vec(_, None) | ty_str | ty_trait(..) => None,
_ => Some(mt),
},
ty_ptr(mt) if explicit => Some(mt),
}
AutoObject(store, bounds, def_id, ref substs) => {
- mk_trait(cx, def_id, substs.clone(), store, bounds)
+
+ let tr = mk_trait(cx, def_id, substs.clone(), bounds);
+ match store {
+ UniqTraitStore => {
+ mk_uniq(cx, tr)
+ }
+ RegionTraitStore(r, m) => {
+ mk_rptr(cx, r, mt {
+ ty: tr,
+ mutbl: m
+ })
+ }
+ }
}
}
}
fn borrow_obj(cx: &ctxt, span: Span, r: Region,
m: ast::Mutability, ty: ty::t) -> ty::t {
match get(ty).sty {
- ty_trait(box ty::TyTrait {def_id, ref substs, bounds, .. }) => {
- ty::mk_trait(cx, def_id, substs.clone(),
- RegionTraitStore(r, m), bounds)
- }
+ ty_uniq(t) | ty_rptr(_, mt{ty: t, ..}) => match get(t).sty {
+ ty_trait(box ty::TyTrait {def_id, ref substs, bounds, .. }) => {
+ mk_rptr(cx, r, mt {
+ ty: ty::mk_trait(cx, def_id, substs.clone(), bounds),
+ mutbl: m
+ })
+ }
+ _ => {
+ cx.sess.span_bug(
+ span,
+ format!("borrow-trait-obj associated with bad sty: {:?}",
+ get(ty).sty).as_slice());
+ }
+ },
ref s => {
cx.sess.span_bug(
span,
let substs = Substs::empty();
let trait_ref = Rc::new(TraitRef { def_id: trait_lang_item, substs: substs });
Ok((trait_ref.clone(),
- mk_trait(tcx,
- trait_ref.def_id,
- trait_ref.substs.clone(),
- RegionTraitStore(region, ast::MutMutable),
- empty_builtin_bounds())))
+ mk_rptr(tcx, region, mt {mutbl: ast::MutMutable,
+ ty: mk_trait(tcx,
+ trait_ref.def_id,
+ trait_ref.substs.clone(),
+ empty_builtin_bounds()) })))
}
pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
}
}
}
- ty_trait(box ty::TyTrait { def_id: d, store, bounds, .. }) => {
+ ty_trait(box ty::TyTrait { def_id: d, bounds, .. }) => {
byte!(17);
did(&mut state, d);
- match store {
- UniqTraitStore => byte!(0),
- RegionTraitStore(r, m) => {
- byte!(1)
- region(&mut state, r);
- hash!(m);
- }
- }
hash!(bounds);
}
ty_struct(d, _) => {
ty::ty_trait(box ty::TyTrait {
def_id,
ref substs,
- store,
bounds
}) => {
ty::ty_trait(box ty::TyTrait {
def_id: def_id,
substs: substs.fold_with(this),
- store: store.fold_with(this),
bounds: bounds
})
}
return constr(ty::mk_vec(tcx, mt, None));
}
ast::TyUnboxedFn(ref unboxed_function) => {
- let trait_store = match ptr_ty {
- Uniq => ty::UniqTraitStore,
+ let ty::TraitRef {
+ def_id,
+ substs
+ } = trait_ref_for_unboxed_function(this,
+ rscope,
+ &**unboxed_function,
+ None);
+ let tr = ty::mk_trait(this.tcx(),
+ def_id,
+ substs,
+ ty::empty_builtin_bounds());
+ match ptr_ty {
+ Uniq => {
+ return ty::mk_uniq(this.tcx(), tr);
+ }
RPtr(r) => {
- ty::RegionTraitStore(r, a_seq_ty.mutbl)
+ return ty::mk_rptr(this.tcx(),
+ r,
+ ty::mt {mutbl: a_seq_ty.mutbl, ty: tr});
}
_ => {
tcx.sess.span_err(
forms of casting-to-trait");
return ty::mk_err();
}
- };
- let ty::TraitRef {
- def_id,
- substs
- } = trait_ref_for_unboxed_function(this,
- rscope,
- &**unboxed_function,
- None);
- return ty::mk_trait(this.tcx(),
- def_id,
- substs,
- trait_store,
- ty::empty_builtin_bounds());
+
+ }
}
ast::TyPath(ref path, ref bounds, id) => {
// Note that the "bounds must be empty if path is not a trait"
path.span,
bounds,
trait_store);
- return ty::mk_trait(tcx,
- result.def_id,
- result.substs.clone(),
- trait_store,
- bounds);
+ let tr = ty::mk_trait(tcx,
+ result.def_id,
+ result.substs.clone(),
+ bounds);
+ // We could just match on ptr_ty, but we need to pass a trait
+ // store to conv_builtin_bounds, so mathc twice for now.
+ return match trait_store {
+ ty::UniqTraitStore => {
+ return ty::mk_uniq(tcx, tr);
+ }
+ ty::RegionTraitStore(r, m) => {
+ return ty::mk_rptr(tcx, r, ty::mt{mutbl: m, ty: tr});
+ }
+ }
}
_ => {}
}
fcx.write_ty(pat_id, expected);
};
match *structure_of(fcx, span, expected) {
- ty::ty_uniq(e_inner) if pointer_kind == Send => {
+ ty::ty_uniq(e_inner) if pointer_kind == Send && !ty::type_is_trait(e_inner) => {
check_inner(e_inner);
}
- ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed => {
+ ty::ty_rptr(_, e_inner) if pointer_kind == Borrowed && !ty::type_is_trait(e_inner.ty) => {
check_inner(e_inner.ty);
}
_ => {
match ty::get(transformed_self_ty).sty {
ty::ty_rptr(r, mt) => { // must be SelfRegion
let r = r.subst(tcx, rcvr_substs); // handle Early-Bound lifetime
- ty::mk_trait(tcx, trait_def_id, obj_substs,
- RegionTraitStore(r, mt.mutbl),
- ty::empty_builtin_bounds())
+ let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
+ ty::empty_builtin_bounds());
+ ty::mk_rptr(tcx, r, ty::mt{ ty: tr, mutbl: mt.mutbl })
}
ty::ty_uniq(_) => { // must be SelfUniq
- ty::mk_trait(tcx, trait_def_id, obj_substs,
- UniqTraitStore,
- ty::empty_builtin_bounds())
+ let tr = ty::mk_trait(tcx, trait_def_id, obj_substs,
+ ty::empty_builtin_bounds());
+ ty::mk_uniq(tcx, tr)
}
_ => {
tcx.sess.span_bug(span,
let span = self.self_expr.map_or(self.span, |e| e.span);
check::autoderef(self.fcx, span, self_ty, None, PreferMutLvalue, |self_ty, _| {
match get(self_ty).sty {
- ty_trait(box TyTrait { def_id, ref substs, .. }) => {
- self.push_inherent_candidates_from_object(def_id, substs);
- self.push_inherent_impl_candidates_for_type(def_id);
- }
+ ty_uniq(ty) | ty_rptr(_, mt {ty, ..}) => match get(ty).sty{
+ ty_trait(box TyTrait { def_id, ref substs, .. }) => {
+ self.push_inherent_candidates_from_object(def_id, substs);
+ self.push_inherent_impl_candidates_for_type(def_id);
+ }
+ _ => {}
+ },
ty_enum(did, _) | ty_struct(did, _) => {
if self.check_traits == CheckTraitsAndInherentMethods {
self.push_inherent_impl_candidates_for_type(did);
let (extra_derefs, auto) = match ty::get(self_mt.ty).sty {
ty::ty_vec(_, None) => (0, ty::AutoBorrowVec(region, self_mt.mutbl)),
ty::ty_str => (0, ty::AutoBorrowVec(region, self_mt.mutbl)),
+ ty::ty_trait(..) => (0, ty::AutoBorrowObj(region, self_mt.mutbl)),
_ => (1, ty::AutoPtr(region, self_mt.mutbl)),
};
(ty::mk_rptr(tcx, region, self_mt),
autoderefs: autoderefs + extra_derefs,
autoref: Some(auto)})
}
-
- ty::ty_trait(box ty::TyTrait {
- def_id, ref substs, store: ty::RegionTraitStore(_, mutbl), bounds
- }) => {
- let region =
- self.infcx().next_region_var(infer::Autoref(self.span));
- (ty::mk_trait(tcx, def_id, substs.clone(),
- ty::RegionTraitStore(region, mutbl), bounds),
- ty::AutoDerefRef {
- autoderefs: autoderefs,
- autoref: Some(ty::AutoBorrowObj(region, mutbl))})
- }
_ => {
(self_ty,
ty::AutoDerefRef {
})
}
+ // Coerce Box/&Trait instances to &Trait.
+ fn auto_slice_trait(&self, ty: ty::t, autoderefs: uint) -> Option<MethodCallee> {
+ match ty::get(ty).sty {
+ ty_trait(box ty::TyTrait {
+ def_id: trt_did,
+ substs: ref trt_substs,
+ bounds: b,
+ .. }) => {
+ let tcx = self.tcx();
+ self.search_for_some_kind_of_autorefd_method(
+ AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
+ |m, r| {
+ let tr = ty::mk_trait(tcx, trt_did, trt_substs.clone(), b);
+ ty::mk_rptr(tcx, r, ty::mt{ ty: tr, mutbl: m })
+ })
+ }
+ _ => fail!("Expected ty_trait in auto_slice_trait")
+ }
+ }
+
fn search_for_autosliced_method(&self,
self_ty: ty::t,
autoderefs: uint)
* `~[]` to `&[]`.
*/
- let tcx = self.tcx();
- debug!("search_for_autosliced_method {}", ppaux::ty_to_str(tcx, self_ty));
+ debug!("search_for_autosliced_method {}", ppaux::ty_to_str(self.tcx(), self_ty));
let sty = ty::get(self_ty).sty.clone();
match sty {
ty_rptr(_, mt) => match ty::get(mt.ty).sty {
ty_vec(mt, None) => self.auto_slice_vec(mt, autoderefs),
+ ty_trait(..) => self.auto_slice_trait(mt.ty, autoderefs),
_ => None
},
ty_uniq(t) => match ty::get(t).sty {
ty_vec(mt, None) => self.auto_slice_vec(mt, autoderefs),
ty_str => self.auto_slice_str(autoderefs),
+ ty_trait(..) => self.auto_slice_trait(t, autoderefs),
_ => None
},
ty_vec(mt, Some(_)) => self.auto_slice_vec(mt, autoderefs),
- ty_trait(box ty::TyTrait {
- def_id: trt_did,
- substs: trt_substs,
- bounds: b,
- ..
- }) => {
- // Coerce Box/&Trait instances to &Trait.
-
- self.search_for_some_kind_of_autorefd_method(
- AutoBorrowObj, autoderefs, [MutImmutable, MutMutable],
- |m, r| {
- ty::mk_trait(tcx, trt_did, trt_substs.clone(),
- RegionTraitStore(r, m), b)
- })
- }
-
ty_closure(..) => {
// This case should probably be handled similarly to
// Trait instances.
ty::ty_rptr(_, mt) => {
match ty::get(mt.ty).sty {
ty::ty_vec(_, None) | ty::ty_str => false,
+ ty::ty_trait(box ty::TyTrait { def_id: self_did, .. }) => {
+ mutability_matches(mt.mutbl, m) &&
+ rcvr_matches_object(self_did, candidate)
+ }
_ => mutability_matches(mt.mutbl, m) &&
rcvr_matches_ty(self.fcx, mt.ty, candidate),
}
}
- ty::ty_trait(box ty::TyTrait {
- def_id: self_did, store: RegionTraitStore(_, self_m), ..
- }) => {
- mutability_matches(self_m, m) &&
- rcvr_matches_object(self_did, candidate)
- }
_ => false
}
ty::ty_uniq(typ) => {
match ty::get(typ).sty {
ty::ty_vec(_, None) | ty::ty_str => false,
+ ty::ty_trait(box ty::TyTrait { def_id: self_did, .. }) => {
+ rcvr_matches_object(self_did, candidate)
+ }
_ => rcvr_matches_ty(self.fcx, typ, candidate),
}
}
- ty::ty_trait(box ty::TyTrait {
- def_id: self_did, store: UniqTraitStore, ..
- }) => {
- rcvr_matches_object(self_did, candidate)
- }
-
_ => false
}
}
else {
match ty::get(t_1).sty {
// This will be looked up later on
- ty::ty_trait(..) => (),
+ _ if ty::type_is_trait(t_1) => {},
_ => {
if ty::type_is_nil(t_e) {
// explaining how it goes about doing that.
let target_ty = rcx.resolve_node_type(expr.id);
match ty::get(target_ty).sty {
- ty::ty_trait(box ty::TyTrait {
- store: ty::RegionTraitStore(trait_region, _), ..
- }) => {
- let source_ty = rcx.resolve_expr_type_adjusted(&**source);
- constrain_regions_in_type(
- rcx,
- trait_region,
- infer::RelateObjectBound(expr.span),
- source_ty);
+ ty::ty_rptr(trait_region, ty::mt{ty, ..}) => {
+ match ty::get(ty).sty {
+ ty::ty_trait(..) => {
+ let source_ty = rcx.resolve_expr_type_adjusted(&**source);
+ constrain_regions_in_type(
+ rcx,
+ trait_region,
+ infer::RelateObjectBound(expr.span),
+ source_ty);
+ }
+ _ => {}
+ }
}
_ => ()
}
trait_ref: Rc<ty::TraitRef>,
is_early: bool)
-> Option<vtable_origin> {
+ debug!("nrc - search_for_vtable");
let tcx = vcx.tcx();
let mut found = Vec::new();
// use a dummy type just to package up the substs that need fixing up
let t = ty::mk_trait(tcx,
id, substs,
- ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
ty::empty_builtin_bounds());
fixup_ty(vcx, span, t, is_early).map(|t_f| {
match ty::get(t_f).sty {
}
pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
+ fn mutability_allowed(a_mutbl: ast::Mutability,
+ b_mutbl: ast::Mutability) -> bool {
+ a_mutbl == b_mutbl ||
+ (a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable)
+ }
+
debug!("vtable: early_resolve_expr() ex with id {:?} (early: {}): {}",
ex.id, is_early, expr_to_str(ex));
let _indent = indenter();
let cx = fcx.ccx;
let resolve_object_cast = |src: &ast::Expr, target_ty: ty::t| {
- match ty::get(target_ty).sty {
- // Bounds of type's contents are not checked here, but in kind.rs.
- ty::ty_trait(box ty::TyTrait {
- def_id: target_def_id, substs: ref target_substs, store, ..
- }) => {
- fn mutability_allowed(a_mutbl: ast::Mutability,
- b_mutbl: ast::Mutability) -> bool {
- a_mutbl == b_mutbl ||
- (a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable)
- }
- // Look up vtables for the type we're casting to,
- // passing in the source and target type. The source
- // must be a pointer type suitable to the object sigil,
- // e.g.: `&x as &Trait` or `box x as Box<Trait>`
- let ty = structurally_resolved_type(fcx, ex.span,
- fcx.expr_ty(src));
- match (&ty::get(ty).sty, store) {
- (&ty::ty_rptr(_, mt), ty::RegionTraitStore(_, mutbl))
- if !mutability_allowed(mt.mutbl, mutbl) => {
+ // Look up vtables for the type we're casting to,
+ // passing in the source and target type. The source
+ // must be a pointer type suitable to the object sigil,
+ // e.g.: `&x as &Trait` or `box x as Box<Trait>`
+ // Bounds of type's contents are not checked here, but in kind.rs.
+ let src_ty = structurally_resolved_type(fcx, ex.span,
+ fcx.expr_ty(src));
+ match (&ty::get(target_ty).sty, &ty::get(src_ty).sty) {
+ (&ty::ty_rptr(_, ty::mt{ty, mutbl}), &ty::ty_rptr(_, mt))
+ if !mutability_allowed(mt.mutbl, mutbl) => {
+ match ty::get(ty).sty {
+ ty::ty_trait(..) => {
fcx.tcx()
.sess
.span_err(ex.span, "types differ in mutability");
}
+ _ => {}
+ }
+ }
- (&ty::ty_uniq(..), ty::UniqTraitStore) |
- (&ty::ty_rptr(..), ty::RegionTraitStore(..)) => {
- let typ = match &ty::get(ty).sty {
- &ty::ty_box(typ) | &ty::ty_uniq(typ) => typ,
- &ty::ty_rptr(_, mt) => mt.ty,
- _ => fail!("shouldn't get here"),
- };
+ (&ty::ty_uniq(ty), &ty::ty_uniq(..) ) |
+ (&ty::ty_rptr(_, ty::mt{ty, ..}), &ty::ty_rptr(..)) => {
+ match ty::get(ty).sty {
+ ty::ty_trait(box ty::TyTrait {
+ def_id: target_def_id, substs: ref target_substs, ..
+ }) => {
+ debug!("nrc correct path");
+ let typ = match &ty::get(src_ty).sty {
+ &ty::ty_uniq(typ) => typ,
+ &ty::ty_rptr(_, mt) => mt.ty,
+ _ => fail!("shouldn't get here"),
+ };
let vcx = fcx.vtable_context();
// Now, if this is &trait, we need to link the
// regions.
- match (&ty::get(ty).sty, store) {
- (&ty::ty_rptr(ra, _),
- ty::RegionTraitStore(rb, _)) => {
+ match (&ty::get(src_ty).sty, &ty::get(target_ty).sty) {
+ (&ty::ty_rptr(ra, _), &ty::ty_rptr(rb, _)) => {
+ debug!("nrc - make subr");
infer::mk_subr(fcx.infcx(),
false,
- infer::RelateObjectBound(
- ex.span),
+ infer::RelateObjectBound(ex.span),
rb,
ra);
}
_ => {}
}
}
+ _ => {}
+ }
+ }
- (_, ty::UniqTraitStore) => {
+ (&ty::ty_uniq(ty), _) => {
+ match ty::get(ty).sty {
+ ty::ty_trait(..) => {
fcx.ccx.tcx.sess.span_err(
ex.span,
format!("can only cast an boxed pointer \
to a boxed object, not a {}",
- ty::ty_sort_str(fcx.tcx(), ty)).as_slice());
+ ty::ty_sort_str(fcx.tcx(), src_ty)).as_slice());
}
+ _ => {}
+ }
- (_, ty::RegionTraitStore(..)) => {
+ }
+ (&ty::ty_rptr(_, ty::mt{ty, ..}), _) => {
+ match ty::get(ty).sty {
+ ty::ty_trait(..) => {
fcx.ccx.tcx.sess.span_err(
ex.span,
format!("can only cast an &-pointer \
to an &-object, not a {}",
- ty::ty_sort_str(fcx.tcx(), ty)).as_slice());
+ ty::ty_sort_str(fcx.tcx(), src_ty)).as_slice());
}
+ _ => {}
}
}
- _ => { /* not a cast to a trait; ignore */ }
+
+ _ => {}
}
};
match ex.node {
ex.repr(fcx.tcx()),
is_early);
- let object_ty = ty::mk_trait(cx.tcx, def_id,
- substs.clone(),
- store, bounds);
+ let trait_ty = ty::mk_trait(cx.tcx,
+ def_id,
+ substs.clone(),
+ bounds);
+ let object_ty = match store {
+ ty::UniqTraitStore => ty::mk_uniq(cx.tcx, trait_ty),
+ ty::RegionTraitStore(r, m) => {
+ ty::mk_rptr(cx.tcx, r, ty::mt {ty: trait_ty, mutbl: m})
+ }
+ };
+
resolve_object_cast(ex, object_ty);
}
AutoAddEnv(..) => {}
}
match get(resolved_type).sty {
- ty_enum(..) | ty_trait(..) | ty_struct(..) => {
+ ty_enum(..) | ty_struct(..) => {
debug!("(getting base type) found base type");
Some(resolved_type)
}
+ // FIXME(14865) I would prefere to use `_` here, but that causes a
+ // compiler error.
+ ty_uniq(_) | ty_rptr(_, _) | ty_trait(..) if ty::type_is_trait(resolved_type) => {
+ debug!("(getting base type) found base type (trait)");
+ Some(resolved_type)
+ }
ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
get(original_type).sty);
None
}
+ ty_trait(..) => fail!("should have been caught")
}
}
found_nominal = true;
}
}
- ty_trait(box ty::TyTrait { def_id, ref store, .. }) => {
+ ty_trait(box ty::TyTrait { def_id, .. }) => {
if def_id.krate == ast::LOCAL_CRATE {
found_nominal = true;
}
- if *store == ty::UniqTraitStore {
- match tcx.lang_items.owned_box() {
- Some(did) if did.krate == ast::LOCAL_CRATE => {
- found_nominal = true;
- }
- _ => {}
- }
- }
}
ty_uniq(..) => {
match tcx.lang_items.owned_box() {
original_type: t)
-> Option<DefId> {
match get_base_type(inference_context, span, original_type) {
- None => {
- return None;
- }
+ None => None,
Some(base_type) => {
match get(base_type).sty {
ty_enum(def_id, _) |
- ty_struct(def_id, _) |
- ty_trait(box ty::TyTrait { def_id, .. }) => {
- return Some(def_id);
+ ty_struct(def_id, _) => {
+ Some(def_id)
}
+ ty_rptr(_, ty::mt {ty, ..}) | ty_uniq(ty) => match ty::get(ty).sty {
+ ty_trait(box ty::TyTrait { def_id, .. }) => {
+ Some(def_id)
+ }
+ _ => {
+ fail!("get_base_type() returned a type that wasn't an \
+ enum, struct, or trait");
+ }
+ },
_ => {
fail!("get_base_type() returned a type that wasn't an \
enum, struct, or trait");
// Note: does not attempt to resolve type variables we encounter.
// See above for details.
match ty::get(b).sty {
- ty::ty_rptr(_, mt_b) => {
+ ty::ty_rptr(r_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_string(a, sty_a, b)
});
}
+
+ ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds }) => {
+ let result = self.unpack_actual_value(a, |sty_a| {
+ match *sty_a {
+ ty::ty_rptr(_, mt_a) => match ty::get(mt_a.ty).sty {
+ ty::ty_trait(..) => {
+ self.coerce_borrowed_object(a, sty_a, b, mt_b.mutbl)
+ }
+ _ => self.coerce_object(a, sty_a, b, def_id, substs,
+ ty::RegionTraitStore(r_b, mt_b.mutbl),
+ bounds)
+ },
+ _ => self.coerce_borrowed_object(a, sty_a, b, mt_b.mutbl)
+ }
+ });
+
+ match result {
+ Ok(t) => return Ok(t),
+ Err(..) => {}
+ }
+ }
+
_ => {
return self.unpack_actual_value(a, |sty_a| {
self.coerce_borrowed_pointer(a, sty_a, b, mt_b)
};
}
+ ty::ty_uniq(t_b) => {
+ match ty::get(t_b).sty {
+ ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds }) => {
+ let result = self.unpack_actual_value(a, |sty_a| {
+ match *sty_a {
+ ty::ty_uniq(t_a) => match ty::get(t_a).sty {
+ ty::ty_trait(..) => {
+ Err(ty::terr_mismatch)
+ }
+ _ => self.coerce_object(a, sty_a, b, def_id, substs,
+ ty::UniqTraitStore, bounds)
+ },
+ _ => Err(ty::terr_mismatch)
+ }
+ });
+
+ match result {
+ Ok(t) => return Ok(t),
+ Err(..) => {}
+ }
+ }
+ _ => {}
+ }
+ }
+
ty::ty_closure(box ty::ClosureTy {
store: ty::RegionTraitStore(..),
..
});
}
- ty::ty_trait(box ty::TyTrait {
- def_id, ref substs, store: ty::UniqTraitStore, bounds
- }) => {
- let result = self.unpack_actual_value(a, |sty_a| {
- match *sty_a {
- ty::ty_uniq(..) => {
- self.coerce_object(a, sty_a, b, def_id, substs,
- ty::UniqTraitStore, bounds)
- }
- _ => Err(ty::terr_mismatch)
- }
- });
-
- match result {
- Ok(t) => return Ok(t),
- Err(..) => {}
- }
- }
-
- ty::ty_trait(box ty::TyTrait {
- def_id, ref substs, store: ty::RegionTraitStore(region, m), bounds
- }) => {
- let result = self.unpack_actual_value(a, |sty_a| {
- match *sty_a {
- ty::ty_rptr(..) => {
- self.coerce_object(a, sty_a, b, def_id, substs,
- ty::RegionTraitStore(region, m), bounds)
- }
- _ => self.coerce_borrowed_object(a, sty_a, b, m)
- }
- });
-
- match result {
- Ok(t) => return Ok(t),
- Err(..) => {}
- }
- }
-
_ => {}
}
let r_a = self.get_ref().infcx.next_region_var(coercion);
let a_borrowed = match *sty_a {
- ty::ty_trait(box ty::TyTrait {
- def_id,
- ref substs,
- bounds,
- ..
- }) => {
- ty::mk_trait(tcx, def_id, substs.clone(),
- ty::RegionTraitStore(r_a, b_mutbl), bounds)
- }
+ ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
+ ty::ty_trait(box ty::TyTrait {
+ def_id,
+ ref substs,
+ bounds,
+ ..
+ }) => {
+ let tr = ty::mk_trait(tcx, def_id, substs.clone(), bounds);
+ ty::mk_rptr(tcx, r_a, ty::mt{ mutbl: b_mutbl, ty: tr })
+ }
+ _ => {
+ return self.subtype(a, b);
+ }
+ },
_ => {
return self.subtype(a, b);
}
// 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.
- fn check_ptr_to_vec<C:Combine>(this: &C,
- a: ty::t,
- b: ty::t,
- a_inner: ty::t,
- b_inner: ty::t,
- result: ty::t) -> cres<ty::t> {
+ fn check_ptr_to_unsized<C:Combine>(this: &C,
+ a: ty::t,
+ b: ty::t,
+ a_inner: ty::t,
+ b_inner: ty::t,
+ result: ty::t) -> cres<ty::t> {
match (&ty::get(a_inner).sty, &ty::get(b_inner).sty) {
(&ty::ty_vec(_, None), &ty::ty_vec(_, None)) |
- (&ty::ty_str, &ty::ty_str) => Ok(result),
+ (&ty::ty_str, &ty::ty_str) |
+ (&ty::ty_trait(..), &ty::ty_trait(..)) => Ok(result),
(&ty::ty_vec(_, None), _) | (_, &ty::ty_vec(_, None)) |
- (&ty::ty_str, _) | (_, &ty::ty_str)
+ (&ty::ty_str, _) | (_, &ty::ty_str) |
+ (&ty::ty_trait(..), _) | (_, &ty::ty_trait(..))
=> Err(ty::terr_sorts(expected_found(this, a, b))),
_ => Ok(result),
}
if a_.def_id == b_.def_id => {
debug!("Trying to match traits {:?} and {:?}", a, b);
let substs = if_ok!(this.substs(a_.def_id, &a_.substs, &b_.substs));
- let s = if_ok!(this.trait_stores(ty::terr_trait, a_.store, b_.store));
let bounds = if_ok!(this.bounds(a_.bounds, b_.bounds));
Ok(ty::mk_trait(tcx,
a_.def_id,
substs.clone(),
- s,
bounds))
}
(&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
let typ = if_ok!(this.tys(a_inner, b_inner));
- check_ptr_to_vec(this, a, b, a_inner, b_inner, ty::mk_uniq(tcx, typ))
+ check_ptr_to_unsized(this, a, b, a_inner, b_inner, ty::mk_uniq(tcx, typ))
}
(&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
let mt = if_ok!(this.mts(a_mt, b_mt));
- check_ptr_to_vec(this, a, b, a_mt.ty, b_mt.ty, ty::mk_ptr(tcx, mt))
+ check_ptr_to_unsized(this, a, b, a_mt.ty, b_mt.ty, 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));
- check_ptr_to_vec(this, a, b, a_mt.ty, b_mt.ty, ty::mk_rptr(tcx, r, mt))
+ // FIXME(14985) If we have mutable references to trait objects, we
+ // used to use covariant subtyping. I have preserved this behaviour,
+ // even though it is probably incorrect. So don't go down the usual
+ // path which would require invariance.
+ let mt = match (&ty::get(a_mt.ty).sty, &ty::get(b_mt.ty).sty) {
+ (&ty::ty_trait(..), &ty::ty_trait(..)) if a_mt.mutbl == b_mt.mutbl => {
+ let ty = if_ok!(this.tys(a_mt.ty, b_mt.ty));
+ ty::mt { ty: ty, mutbl: a_mt.mutbl }
+ }
+ _ => if_ok!(this.mts(a_mt, b_mt))
+ };
+ check_ptr_to_unsized(this, a, b, a_mt.ty, b_mt.ty, ty::mk_rptr(tcx, r, mt))
}
(&ty::ty_vec(ref a_mt, sz_a), &ty::ty_vec(ref b_mt, sz_b)) => {
let dummy0 = ty::mk_trait(self.tcx,
trait_ref.def_id,
trait_ref.substs.clone(),
- ty::UniqTraitStore,
ty::empty_builtin_bounds());
let dummy1 = self.resolve_type_vars_if_possible(dummy0);
match ty::get(dummy1).sty {
parameterized(cx, base.as_slice(), substs, &generics)
}
ty_trait(box ty::TyTrait {
- def_id: did, ref substs, store, ref bounds
+ def_id: did, ref substs, ref bounds
}) => {
let base = ty::item_path_str(cx, did);
let trait_def = ty::lookup_trait_def(cx, did);
substs, &trait_def.generics);
let bound_sep = if bounds.is_empty() { "" } else { ":" };
let bound_str = bounds.repr(cx);
- format!("{}{}{}{}",
- trait_store_to_str(cx, store),
+ format!("{}{}{}",
ty,
bound_sep,
bound_str)
use std::fmt;
use std::io::MemWriter;
use std::io;
-use std::mem::swap;
+use std::mem::{swap,transmute};
use std::num;
use std::str::ScalarValue;
use std::str;
pub fn buffer_encode<T:Encodable<Encoder<'a>, io::IoError>>(to_encode_object: &T) -> Vec<u8> {
//Serialize the object in a string using a writer
let mut m = MemWriter::new();
- {
+ // FIXME(14302) remove the transmute and unsafe block.
+ unsafe {
let mut encoder = Encoder::new(&mut m as &mut io::Writer);
// MemWriter never Errs
- let _ = to_encode_object.encode(&mut encoder);
+ let _ = to_encode_object.encode(transmute(&mut encoder));
}
m.unwrap()
}
// ref #12967, make sure to wrap a key in double quotes,
// in the event that its of a type that omits them (eg numbers)
let mut buf = MemWriter::new();
- let mut check_encoder = Encoder::new(&mut buf);
- try!(f(&mut check_encoder));
+ // FIXME(14302) remove the transmute and unsafe block.
+ unsafe {
+ let mut check_encoder = Encoder::new(&mut buf);
+ try!(f(transmute(&mut check_encoder)));
+ }
let buf = buf.unwrap();
let out = from_utf8(buf.as_slice()).unwrap();
let needs_wrapping = out.char_at(0) != '"' &&
// ref #12967, make sure to wrap a key in double quotes,
// in the event that its of a type that omits them (eg numbers)
let mut buf = MemWriter::new();
- let mut check_encoder = PrettyEncoder::new(&mut buf);
- try!(f(&mut check_encoder));
+ // FIXME(14302) remove the transmute and unsafe block.
+ unsafe {
+ let mut check_encoder = PrettyEncoder::new(&mut buf);
+ try!(f(transmute(&mut check_encoder)));
+ }
let buf = buf.unwrap();
let out = from_utf8(buf.as_slice()).unwrap();
let needs_wrapping = out.char_at(0) != '"' &&
use serialize::{json, Encodable};
use std::io;
use std::io::MemWriter;
+ use std::mem::transmute;
use std::str;
use std::gc::GC;
use codemap::{Span, BytePos, Spanned};
fn to_json_str<'a, E: Encodable<json::Encoder<'a>, io::IoError>>(val: &E) -> String {
let mut writer = MemWriter::new();
- let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
- let _ = val.encode(&mut encoder);
+ // FIXME(14302) remove the transmute and unsafe block.
+ unsafe {
+ let mut encoder = json::Encoder::new(&mut writer as &mut io::Writer);
+ let _ = val.encode(transmute(&mut encoder));
+ }
str::from_utf8(writer.unwrap().as_slice()).unwrap().to_string()
}