From 8e7213f65b4348e1b54d8baeeb291267581227d2 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 11 Jun 2014 17:18:57 +1200 Subject: [PATCH] Remove TraitStore from ty_trait 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. --- src/librustc/metadata/tydecode.rs | 3 +- src/librustc/metadata/tyencode.rs | 2 - src/librustc/middle/kind.rs | 14 ++- src/librustc/middle/lint.rs | 3 - src/librustc/middle/mem_categorization.rs | 8 -- src/librustc/middle/trans/adt.rs | 7 +- src/librustc/middle/trans/base.rs | 7 +- src/librustc/middle/trans/common.rs | 2 +- src/librustc/middle/trans/consts.rs | 4 +- src/librustc/middle/trans/datum.rs | 4 +- src/librustc/middle/trans/debuginfo.rs | 49 ++++----- src/librustc/middle/trans/expr.rs | 25 ++--- src/librustc/middle/trans/glue.rs | 33 +++--- src/librustc/middle/trans/reflect.rs | 24 ++-- src/librustc/middle/trans/type_of.rs | 15 ++- src/librustc/middle/ty.rs | 109 +++++++++--------- src/librustc/middle/ty_fold.rs | 2 - src/librustc/middle/typeck/astconv.rs | 55 ++++++---- src/librustc/middle/typeck/check/_match.rs | 4 +- src/librustc/middle/typeck/check/method.rs | 96 ++++++++-------- src/librustc/middle/typeck/check/mod.rs | 2 +- src/librustc/middle/typeck/check/regionck.rs | 21 ++-- src/librustc/middle/typeck/check/vtable.rs | 106 +++++++++++------- src/librustc/middle/typeck/coherence.rs | 37 ++++--- src/librustc/middle/typeck/infer/coercion.rs | 110 +++++++++++-------- src/librustc/middle/typeck/infer/combine.rs | 38 ++++--- src/librustc/middle/typeck/infer/mod.rs | 1 - src/librustc/util/ppaux.rs | 5 +- src/libserialize/json.rs | 21 ++-- src/libsyntax/parse/mod.rs | 8 +- 30 files changed, 451 insertions(+), 364 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 6a60f91a1ae4f..4897117431bbd 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -346,10 +346,9 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t { 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)); diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 830178ee88082..e1fa4abefdd06 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -232,12 +232,10 @@ fn enc_sty(w: &mut MemWriter, cx: &ctxt, st: &ty::sty) { 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); diff --git a/src/librustc/middle/kind.rs b/src/librustc/middle/kind.rs index 1a3cb16675014..970ae36238bd6 100644 --- a/src/librustc/middle/kind.rs +++ b/src/librustc/middle/kind.rs @@ -361,9 +361,12 @@ fn check_bounds_on_type_parameters(cx: &mut Context, e: &Expr) { 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); + } + _ => {} + }, _ => {} } } @@ -530,9 +533,8 @@ pub fn check_cast_for_escaping_regions( { // 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 diff --git a/src/librustc/middle/lint.rs b/src/librustc/middle/lint.rs index 392821a6ad381..ba05dc1b48a5e 100644 --- a/src/librustc/middle/lint.rs +++ b/src/librustc/middle/lint.rs @@ -980,9 +980,6 @@ fn check_heap_type(cx: &Context, span: Span, ty: ty::t) { n_box += 1; } ty::ty_uniq(_) | - ty::ty_trait(box ty::TyTrait { - store: ty::UniqTraitStore, .. - }) | ty::ty_closure(box ty::ClosureTy { store: ty::UniqTraitStore, .. diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 9b5930cf9ada3..8224557f86007 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -174,7 +174,6 @@ pub enum deref_kind { pub fn opt_deref_kind(t: ty::t) -> Option { 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)) } @@ -183,13 +182,6 @@ pub fn opt_deref_kind(t: ty::t) -> Option { 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, _), diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 1b530ea342491..9f4b11116dbb7 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -292,12 +292,11 @@ impl Case { fn find_ptr(&self) -> Option { 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 } diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 998e8500b994d..7e4fec14f48e1 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -1794,6 +1794,9 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t) -> Vec<(uint, u6 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)); } @@ -1803,9 +1806,9 @@ pub fn get_fn_llvm_attributes(ccx: &CrateContext, fn_ty: ty::t) -> Vec<(uint, u6 // 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)); diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 565ec7d824710..d7509866e0886 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -67,7 +67,7 @@ pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool { 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 { diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index 45019edc58bdf..f0efd13377b78 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -143,7 +143,9 @@ fn const_deref(cx: &CrateContext, v: ValueRef, t: ty::t, explicit: bool) 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), } } diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index 1142b67fdbfad..158a7d6cf7ab9 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -157,9 +157,7 @@ pub fn appropriate_rvalue_mode(ccx: &CrateContext, ty: ty::t) -> RvalueMode { * 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 diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index b934f23abb48c..d05e9954cf457 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -285,8 +285,8 @@ impl TypeMap { // unique ptr (~) -> {~ :pointee-uid:} // @-ptr (@) -> {@ :pointee-uid:} // sized vec ([T, ..x]) -> {[:size:] :element-uid:} - // vec slice (&[T]) -> {& [] :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 -> { :store-sigil: |(:param-uid:),* <,_...>| -> \ // :return-type-uid: : (:bounds:)*} // function -> { fn( (:param-uid:)* <,_...> ) -> \ @@ -361,18 +361,12 @@ impl TypeMap { 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("[]"); } }; @@ -382,12 +376,6 @@ impl TypeMap { 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, @@ -2901,6 +2889,16 @@ fn type_metadata(cx: &CrateContext, 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!(); @@ -2917,6 +2915,17 @@ fn type_metadata(cx: &CrateContext, 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!(); @@ -2930,16 +2939,6 @@ fn type_metadata(cx: &CrateContext, 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, diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 01ba6113c0d51..42c7a71bab84d 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -769,15 +769,12 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>, } 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) => { @@ -1578,7 +1575,7 @@ pub fn cast_type_kind(t: ty::t) -> cast_kind { 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, @@ -1794,8 +1791,8 @@ fn deref_once<'a>(bcx: &'a Block<'a>, 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), } } @@ -1812,8 +1809,8 @@ fn deref_once<'a>(bcx: &'a Block<'a>, 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)); diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index ef9bf4eebe24b..7024ea4b37569 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -100,7 +100,7 @@ pub fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t { 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` does not allocate. @@ -295,10 +295,10 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' 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 @@ -306,6 +306,8 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' }) } 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); @@ -313,7 +315,22 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' 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) @@ -336,16 +353,6 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' } } } - 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); diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index f67fc57bb4407..506817629565e 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -157,7 +157,7 @@ impl<'a, 'b> Reflector<'a, 'b> { 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 { @@ -174,6 +174,13 @@ impl<'a, 'b> Reflector<'a, 'b> { 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, @@ -196,6 +203,13 @@ impl<'a, 'b> Reflector<'a, 'b> { 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()) @@ -351,14 +365,6 @@ impl<'a, 'b> Reflector<'a, 'b> { }) } - 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"), diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 4701a9e322500..31bf6cb0110a4 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -116,20 +116,25 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type { 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) @@ -152,7 +157,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type { } 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()) } @@ -215,6 +220,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type { 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(), } } @@ -230,6 +236,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type { // 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(), } } @@ -245,7 +252,6 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type { 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) @@ -268,6 +274,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type { 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") diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 3ac1027221b61..ac1b6ca591bec 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -742,7 +742,6 @@ pub enum sty { pub struct TyTrait { pub def_id: DefId, pub substs: Substs, - pub store: TraitStore, pub bounds: BuiltinBounds } @@ -1196,14 +1195,8 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t { &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 @@ -1434,14 +1427,12 @@ pub fn mk_ctor_fn(cx: &ctxt, 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)) @@ -1577,9 +1568,9 @@ fn type_is_slice(ty:t) -> bool { 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) } } @@ -1635,7 +1626,7 @@ pub fn type_is_region_ptr(ty: t) -> bool { 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 @@ -1651,7 +1642,10 @@ pub fn type_is_unsafe_ptr(ty: t) -> bool { 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 } } @@ -2060,8 +2054,8 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { } } - 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) => { @@ -2185,7 +2179,16 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { 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. @@ -2198,20 +2201,10 @@ pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents { } 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, @@ -2470,6 +2463,10 @@ pub fn is_type_representable(cx: &ctxt, sp: Span, ty: t) -> Representability { 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 } @@ -2559,7 +2556,7 @@ pub fn deref(t: t, explicit: bool) -> Option { 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, @@ -2567,7 +2564,7 @@ pub fn deref(t: t, explicit: bool) -> Option { }, 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), @@ -2888,7 +2885,19 @@ pub fn adjust_ty(cx: &ctxt, } 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 + }) + } + } } } } @@ -2926,10 +2935,20 @@ pub fn adjust_ty(cx: &ctxt, 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, @@ -4264,11 +4283,11 @@ pub fn visitor_object_ty(tcx: &ctxt, 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 { @@ -4562,17 +4581,9 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 { } } } - 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, _) => { diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index e5fbe9df98f22..2488d2da779b3 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -364,13 +364,11 @@ pub fn super_fold_sty(this: &mut T, 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 }) } diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index f380004fb081e..7ca8a74ae636c 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -584,10 +584,25 @@ fn mk_pointer { - 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( @@ -596,19 +611,8 @@ fn mk_pointer { // Note that the "bounds must be empty if path is not a trait" @@ -651,11 +655,20 @@ fn mk_pointer { + return ty::mk_uniq(tcx, tr); + } + ty::RegionTraitStore(r, m) => { + return ty::mk_rptr(tcx, r, ty::mt{mutbl: m, ty: tr}); + } + } } _ => {} } diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 3933c30d5c98b..edb77e04b3078 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -725,10 +725,10 @@ pub fn check_pointer_pat(pcx: &pat_ctxt, 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); } _ => { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index 864de344db2cd..fafc84d2b10f0 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -277,14 +277,14 @@ fn construct_transformed_self_ty_for_object( 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, @@ -433,10 +433,13 @@ impl<'a> LookupContext<'a> { 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); @@ -774,6 +777,7 @@ impl<'a> LookupContext<'a> { 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), @@ -781,18 +785,6 @@ impl<'a> LookupContext<'a> { 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 { @@ -862,6 +854,26 @@ impl<'a> LookupContext<'a> { }) } + // Coerce Box/&Trait instances to &Trait. + fn auto_slice_trait(&self, ty: ty::t, autoderefs: uint) -> Option { + 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) @@ -871,38 +883,23 @@ impl<'a> LookupContext<'a> { * `~[]` 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. @@ -1313,17 +1310,15 @@ impl<'a> LookupContext<'a> { 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 } @@ -1335,16 +1330,13 @@ impl<'a> LookupContext<'a> { 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 } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 73b92e5b8684c..7d647dea32278 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -3021,7 +3021,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt, 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) { diff --git a/src/librustc/middle/typeck/check/regionck.rs b/src/librustc/middle/typeck/check/regionck.rs index 93ab492eb3af5..6706f8804a5c8 100644 --- a/src/librustc/middle/typeck/check/regionck.rs +++ b/src/librustc/middle/typeck/check/regionck.rs @@ -543,15 +543,18 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { // 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); + } + _ => {} + } } _ => () } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 7d2b9d9aa8697..fe79dabc3f8de 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -302,6 +302,7 @@ fn search_for_vtable(vcx: &VtableContext, trait_ref: Rc, is_early: bool) -> Option { + debug!("nrc - search_for_vtable"); let tcx = vcx.tcx(); let mut found = Vec::new(); @@ -464,7 +465,6 @@ fn fixup_substs(vcx: &VtableContext, // 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 { @@ -518,43 +518,50 @@ fn insert_vtables(fcx: &FnCtxt, vtable_key: MethodCall, vtables: vtable_res) { } 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` - 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` + // 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(); @@ -594,38 +601,49 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { // 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 { @@ -716,9 +734,17 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { 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(..) => {} diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 04bf939ceb8d1..b12e3b614d1be 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -74,10 +74,16 @@ fn get_base_type(inference_context: &InferCtxt, } 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(..) | @@ -87,6 +93,7 @@ fn get_base_type(inference_context: &InferCtxt, get(original_type).sty); None } + ty_trait(..) => fail!("should have been caught") } } @@ -108,18 +115,10 @@ fn type_is_defined_in_local_crate(tcx: &ty::ctxt, original_type: t) -> bool { 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() { @@ -150,16 +149,22 @@ fn get_base_type_def_id(inference_context: &InferCtxt, original_type: t) -> Option { 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"); diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index c03c7386fb331..0568542472b79 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -100,7 +100,7 @@ impl<'f> Coerce<'f> { // 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| { @@ -113,6 +113,28 @@ impl<'f> Coerce<'f> { 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) @@ -121,6 +143,31 @@ impl<'f> Coerce<'f> { }; } + 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(..), .. @@ -136,44 +183,6 @@ impl<'f> Coerce<'f> { }); } - 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(..) => {} - } - } - _ => {} } @@ -335,15 +344,20 @@ impl<'f> Coerce<'f> { 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); } diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index ac6851518083d..cc898ab9c6692 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -378,17 +378,19 @@ pub fn super_tys(this: &C, a: ty::t, b: ty::t) -> cres { // 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(this: &C, - a: ty::t, - b: ty::t, - a_inner: ty::t, - b_inner: ty::t, - result: ty::t) -> cres { + fn check_ptr_to_unsized(this: &C, + a: ty::t, + b: ty::t, + a_inner: ty::t, + b_inner: ty::t, + result: ty::t) -> cres { 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), } @@ -478,12 +480,10 @@ pub fn super_tys(this: &C, a: ty::t, b: ty::t) -> cres { 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)) } @@ -499,18 +499,28 @@ pub fn super_tys(this: &C, a: ty::t, b: ty::t) -> cres { (&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)) => { diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index f43ee1e8aabaa..7a7dbaa549a5c 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -694,7 +694,6 @@ impl<'a> InferCtxt<'a> { 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 { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index ac8ca05f8d016..6e9ee92c0a35e 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -390,7 +390,7 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> String { 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); @@ -398,8 +398,7 @@ pub fn ty_to_str(cx: &ctxt, typ: t) -> String { 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) diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 6ea7cde3b27da..fa8d341e05de2 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -233,7 +233,7 @@ use std::f64; 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; @@ -369,10 +369,11 @@ impl<'a> Encoder<'a> { pub fn buffer_encode, io::IoError>>(to_encode_object: &T) -> Vec { //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() } @@ -543,8 +544,11 @@ impl<'a> ::Encoder for Encoder<'a> { // 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) != '"' && @@ -778,8 +782,11 @@ impl<'a> ::Encoder for PrettyEncoder<'a> { // 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) != '"' && diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index faffc49684603..eb0c6f2555aee 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -281,6 +281,7 @@ mod test { 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}; @@ -295,8 +296,11 @@ mod test { fn to_json_str<'a, E: Encodable, 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() }