From c18a1327e3ccf02ae9f755ca280d53177eeb298d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 7 Nov 2014 06:16:57 -0500 Subject: [PATCH] Make TyTrait embed a `TraitRef`, so that when we extend TraitRef, it naturally carries over to object types. I wanted to embed an `Rc`, but I was foiled by the current static rules, which prohibit non-Sync values from being stored in static locations. This means that the constants for `ty_int` and so forth cannot be initialized. --- src/librustc/metadata/tydecode.rs | 5 +- src/librustc/metadata/tyencode.rs | 11 ++-- src/librustc/middle/astencode.rs | 42 ++++++------ src/librustc/middle/traits/coherence.rs | 2 +- src/librustc/middle/trans/debuginfo.rs | 10 +-- src/librustc/middle/trans/expr.rs | 6 +- src/librustc/middle/ty.rs | 66 +++++++++++-------- src/librustc/middle/ty_fold.rs | 16 ++--- src/librustc/middle/typeck/astconv.rs | 40 +++++------ src/librustc/middle/typeck/check/method.rs | 45 ++++++------- src/librustc/middle/typeck/check/vtable.rs | 13 ++-- src/librustc/middle/typeck/coherence/mod.rs | 8 +-- .../middle/typeck/coherence/orphan.rs | 25 ++++--- src/librustc/middle/typeck/collect.rs | 14 ++-- src/librustc/middle/typeck/infer/coercion.rs | 29 ++++---- src/librustc/middle/typeck/infer/combine.rs | 10 +-- src/librustc/middle/typeck/infer/mod.rs | 10 +-- src/librustc/middle/typeck/variance.rs | 10 +-- src/librustc/util/ppaux.rs | 8 +-- 19 files changed, 178 insertions(+), 192 deletions(-) diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 227a6f71bfd..26b2afd2f3c 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -389,11 +389,10 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t { } 'x' => { 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 trait_ref = parse_trait_ref(st, |x,y| conv(x,y)); let bounds = parse_existential_bounds(st, |x,y| conv(x,y)); assert_eq!(next(st), ']'); - return ty::mk_trait(st.tcx, def, substs, bounds); + return ty::mk_trait(st.tcx, trait_ref, 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 027b9980a32..a7b64cb20e5 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -231,13 +231,10 @@ fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) { enc_substs(w, cx, substs); mywrite!(w, "]"); } - ty::ty_trait(box ty::TyTrait { - def_id, - ref substs, - ref bounds - }) => { - mywrite!(w, "x[{}|", (cx.ds)(def_id)); - enc_substs(w, cx, substs); + ty::ty_trait(box ty::TyTrait { ref principal, + ref bounds }) => { + mywrite!(w, "x["); + enc_trait_ref(w, cx, principal); enc_existential_bounds(w, cx, bounds); mywrite!(w, "]"); } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 9268418ef94..aaf3b16c5ee 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1085,16 +1085,19 @@ impl<'a> rbml_writer_helpers for Encoder<'a> { this.emit_enum_variant_arg(1, |this| idx.encode(this)) }) } - ty::UnsizeVtable(ty::TyTrait { def_id, - bounds: ref b, - ref substs }, + ty::UnsizeVtable(ty::TyTrait { ref principal, + bounds: ref b }, self_ty) => { this.emit_enum_variant("UnsizeVtable", 2, 4, |this| { - this.emit_enum_variant_arg( - 0, |this| Ok(this.emit_existential_bounds(ecx, b))); - this.emit_enum_variant_arg(1, |this| def_id.encode(this)); - this.emit_enum_variant_arg(2, |this| Ok(this.emit_ty(ecx, self_ty))); - this.emit_enum_variant_arg(3, |this| Ok(this.emit_substs(ecx, substs))) + this.emit_enum_variant_arg(0, |this| { + try!(this.emit_struct_field("principal", 0, |this| { + Ok(this.emit_trait_ref(ecx, &*principal)) + })); + this.emit_struct_field("bounds", 1, |this| { + Ok(this.emit_existential_bounds(ecx, b)) + }) + }); + this.emit_enum_variant_arg(1, |this| Ok(this.emit_ty(ecx, self_ty))) }) } } @@ -1693,18 +1696,19 @@ impl<'a> rbml_decoder_decoder_helpers for reader::Decoder<'a> { ty::UnsizeStruct(box uk, idx) } 2 => { - let b = - this.read_enum_variant_arg( - 0, |this| Ok(this.read_existential_bounds(dcx))).unwrap(); - let def_id: ast::DefId = - this.read_enum_variant_arg(1, |this| Decodable::decode(this)).unwrap(); + let ty_trait = try!(this.read_enum_variant_arg(0, |this| { + let principal = try!(this.read_struct_field("principal", 0, |this| { + Ok(this.read_trait_ref(dcx)) + })); + Ok(ty::TyTrait { + principal: (*principal).clone(), + bounds: try!(this.read_struct_field("bounds", 1, |this| { + Ok(this.read_existential_bounds(dcx)) + })), + }) + })); let self_ty = - this.read_enum_variant_arg(2, |this| Ok(this.read_ty(dcx))).unwrap(); - let substs = this.read_enum_variant_arg(3, - |this| Ok(this.read_substs(dcx))).unwrap(); - let ty_trait = ty::TyTrait { def_id: def_id.tr(dcx), - bounds: b, - substs: substs }; + this.read_enum_variant_arg(1, |this| Ok(this.read_ty(dcx))).unwrap(); ty::UnsizeVtable(ty_trait, self_ty) } _ => panic!("bad enum variant for ty::UnsizeKind") diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index 09490f9bdf7..9900620b229 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -143,7 +143,7 @@ pub fn ty_is_local(tcx: &ty::ctxt, } ty::ty_trait(ref tt) => { - tt.def_id.krate == ast::LOCAL_CRATE + tt.principal.def_id.krate == ast::LOCAL_CRATE } // Type parameters may be bound to types that are not local to diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 8309811cf0b..5b2e978e11f 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -423,8 +423,8 @@ impl TypeMap { from_def_id_and_substs(self, cx, - trait_data.def_id, - &trait_data.substs, + trait_data.principal.def_id, + &trait_data.principal.substs, &mut unique_type_id); }, ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => { @@ -2813,7 +2813,7 @@ fn trait_pointer_metadata(cx: &CrateContext, // But it does not describe the trait's methods. let def_id = match ty::get(trait_type).sty { - ty::ty_trait(box ty::TyTrait { def_id, .. }) => def_id, + ty::ty_trait(box ty::TyTrait { ref principal, .. }) => principal.def_id, _ => { let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type); cx.sess().bug(format!("debuginfo: Unexpected trait-object type in \ @@ -3739,8 +3739,8 @@ fn push_debuginfo_type_name(cx: &CrateContext, output.push(']'); }, ty::ty_trait(ref trait_data) => { - push_item_name(cx, trait_data.def_id, false, output); - push_type_params(cx, &trait_data.substs, output); + push_item_name(cx, trait_data.principal.def_id, false, output); + push_type_params(cx, &trait_data.principal.substs, output); }, ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => { if fn_style == ast::UnsafeFn { diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 399be73329b..4b61f0c1409 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -324,10 +324,10 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, _ => bcx.sess().bug(format!("UnsizeStruct with bad sty: {}", bcx.ty_to_string(unsized_ty)).as_slice()) }, - &ty::UnsizeVtable(ty::TyTrait { def_id, ref substs, .. }, _) => { - let substs = substs.with_self_ty(unsized_ty); + &ty::UnsizeVtable(ty::TyTrait { ref principal, .. }, _) => { + let substs = principal.substs.with_self_ty(unsized_ty); let trait_ref = - Rc::new(ty::TraitRef { def_id: def_id, + Rc::new(ty::TraitRef { def_id: principal.def_id, substs: substs }); let trait_ref = trait_ref.subst(bcx.tcx(), &bcx.fcx.param_substs.substs); diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index d1baeac81ab..3e8a7bb842c 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -378,14 +378,14 @@ pub fn type_of_adjust(cx: &ctxt, adj: &AutoAdjustment) -> Option { fn type_of_autoref(cx: &ctxt, autoref: &AutoRef) -> Option { match autoref { &AutoUnsize(ref k) => match k { - &UnsizeVtable(TyTrait { def_id, ref substs, bounds }, _) => { - Some(mk_trait(cx, def_id, substs.clone(), bounds)) + &UnsizeVtable(TyTrait { ref principal, bounds }, _) => { + Some(mk_trait(cx, (*principal).clone(), bounds)) } _ => None }, &AutoUnsizeUniq(ref k) => match k { - &UnsizeVtable(TyTrait { def_id, ref substs, bounds }, _) => { - Some(mk_uniq(cx, mk_trait(cx, def_id, substs.clone(), bounds))) + &UnsizeVtable(TyTrait { ref principal, bounds }, _) => { + Some(mk_uniq(cx, mk_trait(cx, (*principal).clone(), bounds))) } _ => None }, @@ -983,12 +983,12 @@ pub enum sty { #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct TyTrait { - pub def_id: DefId, - pub substs: Substs, + // Principal trait reference. + pub principal: TraitRef, // would use Rc, but it runs afoul of some static rules pub bounds: ExistentialBounds } -#[deriving(PartialEq, Eq, Hash, Show)] +#[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct TraitRef { pub def_id: DefId, pub substs: Substs, @@ -1643,8 +1643,8 @@ pub fn mk_t(cx: &ctxt, st: sty) -> t { &ty_enum(_, ref substs) | &ty_struct(_, ref substs) => { flags = flags | sflags(substs); } - &ty_trait(box TyTrait { ref substs, ref bounds, .. }) => { - flags = flags | sflags(substs); + &ty_trait(box TyTrait { ref principal, ref bounds }) => { + flags = flags | sflags(&principal.substs); flags = flags | flags_for_bounds(bounds); } &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => { @@ -1874,14 +1874,12 @@ pub fn mk_ctor_fn(cx: &ctxt, pub fn mk_trait(cx: &ctxt, - did: ast::DefId, - substs: Substs, + principal: ty::TraitRef, bounds: ExistentialBounds) -> t { // take a copy of substs so that we own the vectors inside let inner = box TyTrait { - def_id: did, - substs: substs, + principal: principal, bounds: bounds }; mk_t(cx, ty_trait(inner)) @@ -1934,9 +1932,15 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) { ty_ptr(ref tm) | ty_rptr(_, ref tm) => { maybe_walk_ty(tm.ty, f); } - ty_enum(_, ref substs) | ty_struct(_, ref substs) | ty_unboxed_closure(_, _, ref substs) | - ty_trait(box TyTrait { ref substs, .. }) => { - for subty in (*substs).types.iter() { + ty_trait(box TyTrait { ref principal, .. }) => { + for subty in principal.substs.types.iter() { + maybe_walk_ty(*subty, |x| f(x)); + } + } + ty_enum(_, ref substs) | + ty_struct(_, ref substs) | + ty_unboxed_closure(_, _, ref substs) => { + for subty in substs.types.iter() { maybe_walk_ty(*subty, |x| f(x)); } } @@ -3554,8 +3558,8 @@ pub fn unsize_ty(cx: &ctxt, format!("UnsizeStruct with bad sty: {}", ty_to_string(cx, ty)).as_slice()) }, - &UnsizeVtable(TyTrait { def_id, ref substs, bounds }, _) => { - mk_trait(cx, def_id, substs.clone(), bounds) + &UnsizeVtable(TyTrait { ref principal, bounds }, _) => { + mk_trait(cx, (*principal).clone(), bounds) } } } @@ -3808,7 +3812,7 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String { ty_bare_fn(_) => "extern fn".to_string(), ty_closure(_) => "fn".to_string(), ty_trait(ref inner) => { - format!("trait {}", item_path_str(cx, inner.def_id)) + format!("trait {}", item_path_str(cx, inner.principal.def_id)) } ty_struct(id, _) => { format!("struct {}", item_path_str(cx, id)) @@ -4230,11 +4234,14 @@ pub fn try_add_builtin_trait( pub fn ty_to_def_id(ty: t) -> Option { match get(ty).sty { - ty_trait(box TyTrait { def_id: id, .. }) | + ty_trait(ref tt) => + Some(tt.principal.def_id), ty_struct(id, _) | ty_enum(id, _) | - ty_unboxed_closure(id, _, _) => Some(id), - _ => None + ty_unboxed_closure(id, _, _) => + Some(id), + _ => + None } } @@ -5213,9 +5220,9 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 { } } } - ty_trait(box TyTrait { def_id: d, bounds, .. }) => { + ty_trait(box TyTrait { ref principal, bounds }) => { byte!(17); - did(&mut state, d); + did(&mut state, principal.def_id); hash!(bounds); } ty_struct(d, _) => { @@ -5504,12 +5511,13 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec, typ: t) { walk_ty(typ, |typ| { match get(typ).sty { - ty_rptr(region, _) => accumulator.push(region), + ty_rptr(region, _) => { + accumulator.push(region) + } + ty_trait(ref t) => { + accumulator.push_all(t.principal.substs.regions().as_slice()); + } ty_enum(_, ref substs) | - ty_trait(box TyTrait { - ref substs, - .. - }) | ty_struct(_, ref substs) => { accum_substs(accumulator, substs); } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index a96e81ce20b..2b83da35c3b 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -373,12 +373,11 @@ impl TypeFoldable for ty::UnsizeKind { match *self { ty::UnsizeLength(len) => ty::UnsizeLength(len), ty::UnsizeStruct(box ref k, n) => ty::UnsizeStruct(box k.fold_with(folder), n), - ty::UnsizeVtable(ty::TyTrait{bounds, def_id, ref substs}, self_ty) => { + ty::UnsizeVtable(ty::TyTrait{ref principal, bounds}, self_ty) => { ty::UnsizeVtable( ty::TyTrait { + principal: principal.fold_with(folder), bounds: bounds.fold_with(folder), - def_id: def_id, - substs: substs.fold_with(folder) }, self_ty.fold_with(folder)) } @@ -529,15 +528,10 @@ pub fn super_fold_sty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, ty::ty_enum(tid, ref substs) => { ty::ty_enum(tid, substs.fold_with(this)) } - ty::ty_trait(box ty::TyTrait { - def_id, - ref substs, - bounds - }) => { + ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => { ty::ty_trait(box ty::TyTrait { - def_id: def_id, - substs: substs.fold_with(this), - bounds: this.fold_existential_bounds(bounds), + principal: (*principal).fold_with(this), + bounds: bounds.fold_with(this), }) } ty::ty_tup(ref ts) => { diff --git a/src/librustc/middle/typeck/astconv.rs b/src/librustc/middle/typeck/astconv.rs index ae0bbd617e2..6430362f9cd 100644 --- a/src/librustc/middle/typeck/astconv.rs +++ b/src/librustc/middle/typeck/astconv.rs @@ -405,11 +405,11 @@ pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC, associated_type: Option, path: &ast::Path, binder_id: ast::NodeId) - -> Rc + -> ty::TraitRef where AC: AstConv<'tcx>, RS: RegionScope { let trait_def = this.get_trait_def(trait_def_id); - Rc::new(ty::TraitRef { + ty::TraitRef { def_id: trait_def_id, substs: ast_path_substs(this, rscope, @@ -419,7 +419,7 @@ pub fn ast_path_to_trait_ref<'tcx,AC,RS>(this: &AC, associated_type, path, binder_id) - }) + } } pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( @@ -702,26 +702,17 @@ fn mk_pointer<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( None, path, id); - let bounds = match *opt_bounds { - None => { - conv_existential_bounds(this, - rscope, - path.span, - [result.clone()].as_slice(), - [].as_slice()) - } - Some(ref bounds) => { - conv_existential_bounds(this, - rscope, - path.span, - [result.clone()].as_slice(), - bounds.as_slice()) - } - }; + let empty_vec = []; + let bounds = match *opt_bounds { None => empty_vec.as_slice(), + Some(ref bounds) => bounds.as_slice() }; + let existential_bounds = conv_existential_bounds(this, + rscope, + path.span, + &[Rc::new(result.clone())], + bounds); let tr = ty::mk_trait(tcx, - result.def_id, - result.substs.clone(), - bounds); + result, + existential_bounds); return match ptr_ty { Uniq => { return ty::mk_uniq(tcx, tr); @@ -943,11 +934,10 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( let bounds = conv_existential_bounds(this, rscope, ast_ty.span, - &[result.clone()], + &[Rc::new(result.clone())], ast_bounds); ty::mk_trait(tcx, - result.def_id, - result.substs.clone(), + result, bounds) } def::DefTy(did, _) | def::DefStruct(did) => { diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index ef616a4a07a..6280fce035a 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -632,9 +632,9 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> { let span = self.self_expr.map_or(self.span, |e| e.span); check::autoderef(self.fcx, span, self_ty, None, NoPreference, |self_ty, _| { match get(self_ty).sty { - ty_trait(box TyTrait { def_id, ref substs, bounds, .. }) => { - self.push_inherent_candidates_from_object(self_ty, def_id, substs, bounds); - self.push_inherent_impl_candidates_for_type(def_id); + ty_trait(box TyTrait { ref principal, bounds, .. }) => { + self.push_inherent_candidates_from_object(self_ty, &*principal, bounds); + self.push_inherent_impl_candidates_for_type(principal.def_id); } ty_enum(did, _) | ty_struct(did, _) | @@ -744,24 +744,23 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> { fn push_inherent_candidates_from_object(&mut self, self_ty: ty::t, - did: DefId, - substs: &subst::Substs, + principal: &ty::TraitRef, _bounds: ty::ExistentialBounds) { debug!("push_inherent_candidates_from_object(self_ty={})", self_ty.repr(self.tcx())); let tcx = self.tcx(); - // It is illegal to invoke a method on a trait instance that refers to - // the `Self` type. Here, we use a substitution that replaces `Self` - // with the object type itself. Hence, a `&self` method will wind up - // with an argument type like `&Trait`. - let rcvr_substs = substs.with_self_ty(self_ty); - - let trait_ref = Rc::new(TraitRef { - def_id: did, - substs: rcvr_substs.clone() - }); + // It is illegal to invoke a method on a trait instance that + // refers to the `Self` type. An error will be reported by + // `enforce_object_limitations()` if the method refers to the + // `Self` type anywhere other than the receiver. Here, we use + // a substitution that replaces `Self` with the object type + // itself. Hence, a `&self` method will wind up with an + // argument type like `&Trait`. + let rcvr_substs = principal.substs.with_self_ty(self_ty); + let trait_ref = Rc::new(TraitRef { def_id: principal.def_id, + substs: rcvr_substs.clone() }); self.push_inherent_candidates_from_bounds_inner( &[trait_ref.clone()], @@ -796,7 +795,7 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> { method_ty: m, origin: MethodTraitObject(MethodObject { trait_ref: new_trait_ref, - object_trait_id: did, + object_trait_id: principal.def_id, method_num: method_num, real_index: vtable_index }) @@ -1151,17 +1150,19 @@ impl<'a, 'tcx> LookupContext<'a, 'tcx> { fn auto_slice_trait(&self, ty: ty::t, autoderefs: uint) -> Option { debug!("auto_slice_trait"); match ty::get(ty).sty { - ty_trait(box ty::TyTrait { - def_id: trt_did, - substs: ref trt_substs, - bounds: b, - .. }) => { + ty_trait(box ty::TyTrait { ref principal, + bounds: b, + .. }) => { + let trt_did = principal.def_id; + let trt_substs = &principal.substs; let tcx = self.tcx(); self.search_for_some_kind_of_autorefd_method( |r, m| AutoPtr(r, m, None), autoderefs, [MutImmutable, MutMutable], |m, r| { - let tr = ty::mk_trait(tcx, trt_did, trt_substs.clone(), b); + let principal = ty::TraitRef::new(trt_did, + trt_substs.clone()); + let tr = ty::mk_trait(tcx, principal, b); ty::mk_rptr(tcx, r, ty::mt{ ty: tr, mutbl: m }) }) } diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 2fcce4cc3dc..498594716e7 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -140,11 +140,11 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa // `call_once` which is the method which takes self by value. What could go // wrong? match tcx.lang_items.fn_once_trait() { - Some(def_id) if def_id == object_trait.def_id => return, + Some(def_id) if def_id == object_trait.principal.def_id => return, _ => {} } - let trait_items = ty::trait_items(tcx, object_trait.def_id); + let trait_items = ty::trait_items(tcx, object_trait.principal.def_id); let mut errors = Vec::new(); for item in trait_items.iter() { @@ -158,7 +158,7 @@ pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Spa let mut errors = errors.iter().flat_map(|x| x.iter()).peekable(); if errors.peek().is_some() { - let trait_name = ty::item_path_str(tcx, object_trait.def_id); + let trait_name = ty::item_path_str(tcx, object_trait.principal.def_id); span_err!(tcx.sess, span, E0038, "cannot convert to a trait object because trait `{}` is not object-safe", trait_name); @@ -241,8 +241,7 @@ pub fn register_object_cast_obligations(fcx: &FnCtxt, // needs some refactoring so there is a more convenient type to pass around. let object_trait_ty = ty::mk_trait(fcx.tcx(), - object_trait.def_id, - object_trait.substs.clone(), + object_trait.principal.clone(), object_trait.bounds); debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}", @@ -252,13 +251,13 @@ pub fn register_object_cast_obligations(fcx: &FnCtxt, // Take the type parameters from the object type, but set // the Self type (which is unknown, for the object type) // to be the type we are casting from. - let mut object_substs = object_trait.substs.clone(); + let mut object_substs = object_trait.principal.substs.clone(); assert!(object_substs.self_ty().is_none()); object_substs.types.push(SelfSpace, referent_ty); // Create the obligation for casting from T to Trait. let object_trait_ref = - Rc::new(ty::TraitRef { def_id: object_trait.def_id, + Rc::new(ty::TraitRef { def_id: object_trait.principal.def_id, substs: object_substs }); let object_obligation = Obligation::new( diff --git a/src/librustc/middle/typeck/coherence/mod.rs b/src/librustc/middle/typeck/coherence/mod.rs index 19ff82469b5..898d987ace7 100644 --- a/src/librustc/middle/typeck/coherence/mod.rs +++ b/src/librustc/middle/typeck/coherence/mod.rs @@ -112,8 +112,8 @@ fn get_base_type_def_id(inference_context: &InferCtxt, ty_rptr(_, ty::mt {ty, ..}) | ty_uniq(ty) => { match ty::get(ty).sty { - ty_trait(box ty::TyTrait { def_id, .. }) => { - Some(def_id) + ty_trait(box ty::TyTrait { ref principal, .. }) => { + Some(principal.def_id) } _ => { panic!("get_base_type() returned a type that wasn't an \ @@ -121,8 +121,8 @@ fn get_base_type_def_id(inference_context: &InferCtxt, } } } - ty_trait(box ty::TyTrait { def_id, .. }) => { - Some(def_id) + ty_trait(box ty::TyTrait { ref principal, .. }) => { + Some(principal.def_id) } _ => { panic!("get_base_type() returned a type that wasn't an \ diff --git a/src/librustc/middle/typeck/coherence/orphan.rs b/src/librustc/middle/typeck/coherence/orphan.rs index 3c4ad347361..ba362fb878c 100644 --- a/src/librustc/middle/typeck/coherence/orphan.rs +++ b/src/librustc/middle/typeck/coherence/orphan.rs @@ -18,6 +18,7 @@ use middle::ty; use syntax::ast::{Item, ItemImpl}; use syntax::ast; use syntax::ast_util; +use syntax::codemap::Span; use syntax::visit; use util::ppaux::Repr; @@ -30,6 +31,17 @@ struct OrphanChecker<'cx, 'tcx:'cx> { tcx: &'cx ty::ctxt<'tcx> } +impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { + fn check_def_id(&self, span: Span, def_id: ast::DefId) { + if def_id.krate != ast::LOCAL_CRATE { + span_err!(self.tcx.sess, span, E0116, + "cannot associate methods with a type outside the \ + crate the type is defined in; define and implement \ + a trait or new type instead"); + } + } +} + impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v ast::Item) { let def_id = ast_util::local_def(item.id); @@ -41,14 +53,11 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { let self_ty = ty::lookup_item_type(self.tcx, def_id).ty; match ty::get(self_ty).sty { ty::ty_enum(def_id, _) | - ty::ty_struct(def_id, _) | - ty::ty_trait(box ty::TyTrait{ def_id, ..}) => { - if def_id.krate != ast::LOCAL_CRATE { - span_err!(self.tcx.sess, item.span, E0116, - "cannot associate methods with a type outside the \ - crate the type is defined in; define and implement \ - a trait or new type instead"); - } + ty::ty_struct(def_id, _) => { + self.check_def_id(item.span, def_id); + } + ty::ty_trait(box ty::TyTrait{ ref principal, ..}) => { + self.check_def_id(item.span, principal.def_id); } _ => { span_err!(self.tcx.sess, item.span, E0118, diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index ae2073f6316..d365c54c701 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -1335,13 +1335,13 @@ pub fn instantiate_trait_ref<'tcx,AC>(this: &AC, ast_trait_ref.ref_id) { def::DefTrait(trait_did) => { let trait_ref = - astconv::ast_path_to_trait_ref(this, - &rscope, - trait_did, - Some(self_ty), - associated_type, - &ast_trait_ref.path, - ast_trait_ref.ref_id); + Rc::new(astconv::ast_path_to_trait_ref(this, + &rscope, + trait_did, + Some(self_ty), + associated_type, + &ast_trait_ref.path, + ast_trait_ref.ref_id)); this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone()); diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index e44aa3e8221..718d70050a0 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -413,15 +413,14 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { let ty = ty::mk_vec(tcx, t_a, None); Some((ty, ty::UnsizeLength(len))) } - (&ty::ty_trait(..), &ty::ty_trait(..)) => None, - (_, &ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds })) => { - let ty = ty::mk_trait(tcx, - def_id, - substs.clone(), - bounds); - Some((ty, ty::UnsizeVtable(ty::TyTrait { def_id: def_id, - bounds: bounds, - substs: substs.clone() }, + (&ty::ty_trait(..), &ty::ty_trait(..)) => { + None + } + (_, &ty::ty_trait(box ty::TyTrait { ref principal, bounds })) => { + // FIXME what is the purpose of `ty`? + let ty = ty::mk_trait(tcx, (*principal).clone(), bounds); + Some((ty, ty::UnsizeVtable(ty::TyTrait { principal: (*principal).clone(), + bounds: bounds }, ty_a))) } (&ty::ty_struct(did_a, ref substs_a), &ty::ty_struct(did_b, ref substs_b)) @@ -524,16 +523,10 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { match *sty_a { ty::ty_rptr(_, ty::mt{ty, mutbl}) => match ty::get(ty).sty { - ty::ty_trait(box ty::TyTrait { - def_id, - ref substs, - bounds, - .. - }) => - { + ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => { debug!("mutbl={} b_mutbl={}", mutbl, b_mutbl); - - let tr = ty::mk_trait(tcx, def_id, substs.clone(), bounds); + // FIXME what is purpose of this type `tr`? + let tr = ty::mk_trait(tcx, (*principal).clone(), bounds); try!(self.subtype(mk_ty(tr), b)); Ok(Some(AdjustDerefRef(AutoDerefRef { autoderefs: 1, diff --git a/src/librustc/middle/typeck/infer/combine.rs b/src/librustc/middle/typeck/infer/combine.rs index e51eb331cdc..ab3ec4991c3 100644 --- a/src/librustc/middle/typeck/infer/combine.rs +++ b/src/librustc/middle/typeck/infer/combine.rs @@ -461,15 +461,11 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, a: ty::t, b: ty::t) -> cres { + &ty::ty_trait(ref b_)) => { debug!("Trying to match traits {} and {}", a, b); - let substs = try!(this.substs(a_.def_id, &a_.substs, &b_.substs)); + let principal = try!(this.trait_refs(&a_.principal, &b_.principal)); let bounds = try!(this.existential_bounds(a_.bounds, b_.bounds)); - Ok(ty::mk_trait(tcx, - a_.def_id, - substs.clone(), - bounds)) + Ok(ty::mk_trait(tcx, principal, bounds)) } (&ty::ty_struct(a_id, ref a_substs), &ty::ty_struct(b_id, ref b_substs)) diff --git a/src/librustc/middle/typeck/infer/mod.rs b/src/librustc/middle/typeck/infer/mod.rs index 55c3c236853..23000949115 100644 --- a/src/librustc/middle/typeck/infer/mod.rs +++ b/src/librustc/middle/typeck/infer/mod.rs @@ -856,16 +856,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { -> ty::TraitRef { // make up a dummy type just to reuse/abuse the resolve machinery let dummy0 = ty::mk_trait(self.tcx, - trait_ref.def_id, - trait_ref.substs.clone(), + (*trait_ref).clone(), ty::region_existential_bound(ty::ReStatic)); let dummy1 = self.resolve_type_vars_if_possible(dummy0); match ty::get(dummy1).sty { - ty::ty_trait(box ty::TyTrait { ref def_id, ref substs, .. }) => { - ty::TraitRef { - def_id: *def_id, - substs: (*substs).clone(), - } + ty::ty_trait(box ty::TyTrait { ref principal, .. }) => { + (*principal).clone() } _ => { self.tcx.sess.bug( diff --git a/src/librustc/middle/typeck/variance.rs b/src/librustc/middle/typeck/variance.rs index 4227cc521b4..b6d8c85fa0b 100644 --- a/src/librustc/middle/typeck/variance.rs +++ b/src/librustc/middle/typeck/variance.rs @@ -778,14 +778,14 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance); } - ty::ty_trait(box ty::TyTrait { def_id, ref substs, bounds }) => { - let trait_def = ty::lookup_trait_def(self.tcx(), def_id); + ty::ty_trait(box ty::TyTrait { ref principal, bounds }) => { + let trait_def = ty::lookup_trait_def(self.tcx(), principal.def_id); let generics = &trait_def.generics; // Traits DO have a Self type parameter, but it is // erased from object types. assert!(!generics.types.is_empty_in(subst::SelfSpace) && - substs.types.is_empty_in(subst::SelfSpace)); + principal.substs.types.is_empty_in(subst::SelfSpace)); // Traits never declare region parameters in the self // space. @@ -801,10 +801,10 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_region(bounds.region_bound, contra); self.add_constraints_from_substs( - def_id, + principal.def_id, generics.types.get_slice(subst::TypeSpace), generics.regions.get_slice(subst::TypeSpace), - substs, + &principal.substs, variance); } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 9080b12c543..60a7436dbaa 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -435,12 +435,12 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { parameterized(cx, base.as_slice(), substs, &generics) } ty_trait(box ty::TyTrait { - def_id: did, ref substs, ref bounds + ref principal, ref bounds }) => { - let base = ty::item_path_str(cx, did); - let trait_def = ty::lookup_trait_def(cx, did); + let base = ty::item_path_str(cx, principal.def_id); + let trait_def = ty::lookup_trait_def(cx, principal.def_id); let ty = parameterized(cx, base.as_slice(), - substs, &trait_def.generics); + &principal.substs, &trait_def.generics); let bound_str = bounds.user_string(cx); let bound_sep = if bound_str.is_empty() { "" } else { "+" }; format!("{}{}{}",