From 46c7a117f84954ce845c55c90db62952624638de Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Sat, 12 Nov 2016 15:46:16 -0700 Subject: [PATCH 1/7] Privatize TraitObject.principal and add a method accessor, returning Option. --- src/librustc/traits/coherence.rs | 16 +++---- src/librustc/traits/select.rs | 34 +++++++++------ src/librustc/ty/error.rs | 3 +- src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/flags.rs | 2 +- src/librustc/ty/item_path.rs | 2 +- src/librustc/ty/relate.rs | 13 +++--- src/librustc/ty/structural_impls.rs | 14 +++--- src/librustc/ty/sty.rs | 23 ++++++++-- src/librustc/ty/util.rs | 4 +- src/librustc/ty/walk.rs | 5 ++- src/librustc/ty/wf.rs | 4 +- src/librustc/util/ppaux.rs | 4 +- src/librustc_trans/base.rs | 2 +- src/librustc_trans/collector.rs | 2 +- src/librustc_trans/debuginfo/metadata.rs | 11 +++-- src/librustc_trans/debuginfo/type_names.rs | 10 +++-- src/librustc_trans/trans_item.rs | 10 +++-- src/librustc_typeck/astconv.rs | 12 +++--- src/librustc_typeck/check/cast.rs | 2 +- src/librustc_typeck/check/closure.rs | 2 +- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 4 +- src/librustc_typeck/check/method/suggest.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 2 +- src/librustc_typeck/coherence/orphan.rs | 4 +- src/librustc_typeck/coherence/overlap.rs | 4 +- src/librustc_typeck/variance/constraints.rs | 2 +- src/librustdoc/clean/mod.rs | 48 +++++++++++---------- 29 files changed, 142 insertions(+), 103 deletions(-) diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 2e06e83f8489c..d4e217fb710cc 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -225,14 +225,12 @@ fn ty_is_local(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal) -> bool { fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool { match ty.sty { - ty::TyBox(..) | ty::TyRef(..) => - true, - ty::TyAdt(def, _) => - def.is_fundamental(), - ty::TyTrait(ref data) => - tcx.has_attr(data.principal.def_id(), "fundamental"), - _ => - false + ty::TyBox(..) | ty::TyRef(..) => true, + ty::TyAdt(def, _) => def.is_fundamental(), + ty::TyTrait(ref data) => { + data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental")) + } + _ => false } } @@ -273,7 +271,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> } ty::TyTrait(ref tt) => { - tt.principal.def_id().is_local() + tt.principal().map_or(false, |p| p.def_id().is_local()) } ty::TyError => { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index c25e7ee344f6e..f79a212a473cd 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1528,7 +1528,10 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { _ => {} } - data.principal.with_self_ty(this.tcx(), self_ty) + match data.principal() { + Some(ref p) => p.with_self_ty(this.tcx(), self_ty), + None => return, + } } ty::TyInfer(ty::TyVar(_)) => { debug!("assemble_candidates_from_object_ty: ambiguous"); @@ -1611,8 +1614,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // // We always upcast when we can because of reason // #2 (region bounds). - data_a.principal.def_id() == data_b.principal.def_id() && - data_a.builtin_bounds.is_superset(&data_b.builtin_bounds) + match (data_a.principal(), data_b.principal()) { + (Some(ref a), Some(ref b)) => a.def_id() == b.def_id() && + data_a.builtin_bounds.is_superset(&data_b.builtin_bounds), + _ => false + } } // T -> Trait. @@ -2167,7 +2173,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { match self_ty.sty { ty::TyTrait(ref data) => { // OK to skip the binder, it is reintroduced below - let input_types = data.principal.input_types(); + let principal = data.principal().unwrap(); + let input_types = principal.input_types(); let assoc_types = data.projection_bounds.iter() .map(|pb| pb.skip_binder().ty); let all_types: Vec<_> = input_types.chain(assoc_types) @@ -2301,7 +2308,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.sty { ty::TyTrait(ref data) => { - data.principal.with_self_ty(self.tcx(), self_ty) + data.principal().unwrap().with_self_ty(self.tcx(), self_ty) } _ => { span_bug!(obligation.cause.span, @@ -2471,12 +2478,13 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). (&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => { // See assemble_candidates_for_unsizing for more info. - let new_trait = tcx.mk_trait(ty::TraitObject { - principal: data_a.principal, - region_bound: data_b.region_bound, - builtin_bounds: data_b.builtin_bounds, - projection_bounds: data_a.projection_bounds.clone(), - }); + let new_trait = tcx.mk_trait(ty::TraitObject::new( + data_a.principal(), + data_b.region_bound, + data_b.builtin_bounds, + data_a.projection_bounds.clone(), + )); + let origin = TypeOrigin::Misc(obligation.cause.span); let InferOk { obligations, .. } = self.infcx.sub_types(false, &obligation.cause, new_trait, target) .map_err(|_| Unimplemented)?; @@ -2499,7 +2507,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { data.builtin_bounds.iter().flat_map(|bound| { tcx.lang_items.from_builtin_kind(bound).ok() }) - .chain(Some(data.principal.def_id())); + .chain(data.principal().map(|ref p| p.def_id())); if let Some(did) = object_dids.find(|did| { !tcx.is_object_safe(*did) }) { @@ -2516,7 +2524,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { }; // Create the obligation for casting from T to Trait. - push(data.principal.with_self_ty(tcx, source).to_predicate()); + push(data.principal().unwrap().with_self_ty(tcx, source).to_predicate()); // We can only make objects from sized types. let mut builtin_bounds = data.builtin_bounds; diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 9b345c2d02329..8bdcc93fa2114 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -215,7 +215,8 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { ty::TyFnDef(..) => format!("fn item"), ty::TyFnPtr(_) => "fn pointer".to_string(), ty::TyTrait(ref inner) => { - format!("trait {}", tcx.item_path_str(inner.principal.def_id())) + inner.principal().map_or_else(|| "trait".to_string(), + |p| format!("trait {}", tcx.item_path_str(p.def_id()))) } ty::TyClosure(..) => "closure".to_string(), ty::TyTuple(_) => "tuple".to_string(), diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index befc9533c387b..3eab06dc674bf 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -60,7 +60,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType), ty::TyRawPtr(_) => Some(PtrSimplifiedType), ty::TyTrait(ref trait_info) => { - Some(TraitSimplifiedType(trait_info.principal.def_id())) + trait_info.principal().map(|p| TraitSimplifiedType(p.def_id())) } ty::TyRef(_, mt) => { // since we introduce auto-refs during method lookup, we diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 2c09b89beb232..026bf64533c88 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -123,7 +123,7 @@ impl FlagComputation { &ty::TyTrait(ref obj) => { let mut computation = FlagComputation::new(); - computation.add_substs(obj.principal.skip_binder().substs); + computation.add_substs(obj.principal().unwrap().skip_binder().substs); for projection_bound in &obj.projection_bounds { let mut proj_computation = FlagComputation::new(); proj_computation.add_existential_projection(&projection_bound.0); diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index b93a8698f603c..d1e6f5b8cd12e 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -316,7 +316,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { match ty.sty { ty::TyAdt(adt_def, _) => Some(adt_def.did), - ty::TyTrait(ref data) => Some(data.principal.def_id()), + ty::TyTrait(ref data) => data.principal().map(|ref p| p.def_id()), ty::TyArray(subty, _) | ty::TySlice(subty) | diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 2a01bad33c52e..a70cfabac8738 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -417,7 +417,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, (&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) => { - let principal = relation.relate(&a_obj.principal, &b_obj.principal)?; + let principal = match (a_obj.principal(), b_obj.principal()) { + (Some(ref a_p), Some(ref b_p)) => Some(relation.relate(a_p, b_p)?), + (None, None) => None, + _ => return Err(TypeError::Sorts(expected_found(relation, &a, &b))), + }; let r = relation.with_cause( Cause::ExistentialRegionBound, @@ -426,12 +430,7 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, &b_obj.region_bound))?; let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?; let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?; - Ok(tcx.mk_trait(ty::TraitObject { - principal: principal, - region_bound: r, - builtin_bounds: nb, - projection_bounds: pb - })) + Ok(tcx.mk_trait(ty::TraitObject::new(principal, r, nb, pb))) } (&ty::TyClosure(a_id, a_substs), diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index c8618cd154781..883f43258d899 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -429,16 +429,16 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TraitObject { - principal: self.principal.fold_with(folder), - region_bound: self.region_bound.fold_with(folder), - builtin_bounds: self.builtin_bounds, - projection_bounds: self.projection_bounds.fold_with(folder), - } + ty::TraitObject::new( + self.principal().map(|p| p.fold_with(folder)), + self.region_bound.fold_with(folder), + self.builtin_bounds, + self.projection_bounds.fold_with(folder), + ) } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.principal.visit_with(visitor) || + self.principal().map(|p| p.visit_with(visitor)).unwrap_or(true) || self.region_bound.visit_with(visitor) || self.projection_bounds.visit_with(visitor) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index cb3176cce10bd..454dedd937b7a 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -277,12 +277,29 @@ impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx> { #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] pub struct TraitObject<'tcx> { - pub principal: PolyExistentialTraitRef<'tcx>, + principal: Option>, pub region_bound: &'tcx ty::Region, pub builtin_bounds: BuiltinBounds, pub projection_bounds: Vec>, } +impl<'tcx> TraitObject<'tcx> { + pub fn new(principal: Option>, region_bound: &'tcx ty::Region, + builtin_bounds: BuiltinBounds, projection_bounds: Vec>) + -> Self { + TraitObject { + principal: principal, + region_bound: region_bound, + builtin_bounds: builtin_bounds, + projection_bounds: projection_bounds, + } + } + + pub fn principal(&self) -> Option> { + self.principal + } +} + /// A complete reference to a trait. These take numerous guises in syntax, /// but perhaps the most recognizable form is in a where clause: /// @@ -1221,7 +1238,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn ty_to_def_id(&self) -> Option { match self.sty { - TyTrait(ref tt) => Some(tt.principal.def_id()), + TyTrait(ref tt) => tt.principal().map(|p| p.def_id()), TyAdt(def, _) => Some(def.did), TyClosure(id, _) => Some(id), _ => None @@ -1245,7 +1262,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { } TyTrait(ref obj) => { let mut v = vec![obj.region_bound]; - v.extend(obj.principal.skip_binder().substs.regions()); + v.extend(obj.principal().unwrap().skip_binder().substs.regions()); v } TyAdt(_, substs) | TyAnon(_, substs) => { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 1dde8106ec6a6..bd7d72d3ef398 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -532,7 +532,9 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc self.hash(f.sig.inputs().skip_binder().len()); } TyTrait(ref data) => { - self.def_id(data.principal.def_id()); + if let Some(ref p) = data.principal() { + self.def_id(p.def_id()); + } self.hash(data.builtin_bounds); } TyTuple(tys) => { diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 2f9468dbe5887..02f55c6e34082 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -93,7 +93,10 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { stack.extend(data.trait_ref.substs.types().rev()); } ty::TyTrait(ref obj) => { - stack.extend(obj.principal.input_types().rev()); + match obj.principal() { + Some(ref p) => stack.extend(p.input_types().rev()), + None => {} + } stack.extend(obj.projection_bounds.iter().map(|pred| { pred.0.ty }).rev()); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 74c6d7d334c35..25015557ad4df 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -394,7 +394,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { data.builtin_bounds.iter().flat_map(|bound| { tcx.lang_items.from_builtin_kind(bound).ok() }) - .chain(Some(data.principal.def_id())); + .chain(data.principal().map(|ref p| p.def_id())); self.out.extend( component_traits.map(|did| { traits::Obligation::new( cause.clone(), @@ -492,7 +492,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { if !data.has_escaping_regions() { let implicit_bounds = object_region_bounds(self.infcx.tcx, - data.principal, + data.principal().unwrap(), data.builtin_bounds); let explicit_bound = data.region_bound; diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d04825d560444..c87f3ba0a59a5 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -339,7 +339,7 @@ impl<'tcx> fmt::Display for ty::TraitObject<'tcx> { // Use a type that can't appear in defaults of type parameters. let dummy_self = tcx.mk_infer(ty::FreshTy(0)); - let principal = tcx.lift(&self.principal) + let principal = self.principal().and_then(|ref p| tcx.lift(p)) .expect("could not lift TraitRef for printing") .with_self_ty(tcx, dummy_self).0; let projections = self.projection_bounds.iter().map(|p| { @@ -466,7 +466,7 @@ impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> { }; maybe_continue(f)?; - write!(f, "{:?}", self.principal)?; + write!(f, "{:?}", self.principal())?; let region_str = format!("{:?}", self.region_bound); if !region_str.is_empty() { diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c94c25e0b056c..a79f7e1733c26 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -302,7 +302,7 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>, old_info.expect("unsized_info: missing old info for trait upcast") } (_, &ty::TyTrait(ref data)) => { - let trait_ref = data.principal.with_self_ty(ccx.tcx(), source); + let trait_ref = data.principal().unwrap().with_self_ty(ccx.tcx(), source); let trait_ref = ccx.tcx().erase_regions(&trait_ref); consts::ptrcast(meth::get_vtable(ccx, trait_ref), Type::vtable_ptr(ccx)) diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 5c7b004375ed4..ac8793c47e726 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1004,7 +1004,7 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst()); if let ty::TyTrait(ref trait_ty) = trait_ty.sty { - let poly_trait_ref = trait_ty.principal.with_self_ty(scx.tcx(), impl_ty); + let poly_trait_ref = trait_ty.principal().unwrap().with_self_ty(scx.tcx(), impl_ty); let param_substs = scx.tcx().intern_substs(&[]); // Walk all methods of the trait, including those of its supertraits diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 5d01ca892b316..5af1b0faebc4a 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -431,8 +431,13 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // type is assigned the correct name, size, namespace, and source location. // But it does not describe the trait's methods. - let def_id = match trait_type.sty { - ty::TyTrait(ref data) => data.principal.def_id(), + let containing_scope = match trait_type.sty { + ty::TyTrait(ref data) => if let Some(principal) = data.principal() { + let def_id = principal.def_id(); + get_namespace_and_span_for_item(cx, def_id).0 + } else { + NO_SCOPE_METADATA + }, _ => { bug!("debuginfo: Unexpected trait-object type in \ trait_pointer_metadata(): {:?}", @@ -444,8 +449,6 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let trait_type_name = compute_debuginfo_type_name(cx, trait_object_type, false); - let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id); - let trait_llvm_type = type_of::type_of(cx, trait_object_type); let file_metadata = unknown_file_metadata(cx); diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index fce1ce5610555..1831125e8eb9e 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -94,10 +94,12 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, output.push(']'); }, ty::TyTrait(ref trait_data) => { - let principal = cx.tcx().erase_late_bound_regions_and_normalize( - &trait_data.principal); - push_item_name(cx, principal.def_id, false, output); - push_type_params(cx, principal.substs, output); + if let Some(principal) = trait_data.principal() { + let principal = cx.tcx().erase_late_bound_regions_and_normalize( + &principal); + push_item_name(cx, principal.def_id, false, output); + push_type_params(cx, principal.substs, output); + } }, ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) | ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => { diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index f2d1e375793b3..c46c6e6f769af 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -458,10 +458,12 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.push(']'); }, ty::TyTrait(ref trait_data) => { - self.push_def_path(trait_data.principal.def_id(), output); - self.push_type_params(trait_data.principal.skip_binder().substs, - &trait_data.projection_bounds, - output); + if let Some(principal) = trait_data.principal() { + self.push_def_path(principal.def_id(), output); + self.push_type_params(principal.skip_binder().substs, + &trait_data.projection_bounds, + output); + } }, ty::TyFnDef(.., &ty::BareFnTy{ unsafety, abi, ref sig } ) | ty::TyFnPtr(&ty::BareFnTy{ unsafety, abi, ref sig } ) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bb7b62533001d..9cf6f555744c1 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1135,12 +1135,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .emit(); } - let ty = tcx.mk_trait(ty::TraitObject { - principal: existential_principal, - region_bound: region_bound, - builtin_bounds: builtin_bounds, - projection_bounds: existential_projections - }); + let ty = tcx.mk_trait(ty::TraitObject::new( + Some(existential_principal), + region_bound, + builtin_bounds, + existential_projections + )); debug!("trait_object_type: {:?}", ty); ty } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 5839c606566c3..3e1a3c870ca0d 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -78,7 +78,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn unsize_kind(&self, t: Ty<'tcx>) -> Option> { match t.sty { ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length), - ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal.def_id())), + ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal().unwrap().def_id())), ty::TyAdt(def, substs) if def.is_struct() => { // FIXME(arielb1): do some kind of normalization match def.struct_variant().fields.last() { diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 75287d4064ae1..4627c166fc6f3 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -119,7 +119,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.deduce_sig_from_projection(&pb) }) .next(); - let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal.def_id()); + let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal().unwrap().def_id()); (sig, kind) } ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 54e93978b798d..4c19ea46e5a7f 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { .autoderef(self.span, self_ty) .filter_map(|(ty, _)| { match ty.sty { - ty::TyTrait(ref data) => Some(closure(self, ty, data.principal)), + ty::TyTrait(ref data) => data.principal().map(|p| closure(self, ty, p)), _ => None, } }) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 545d4e788524f..b76d13125b474 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -296,8 +296,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { match self_ty.sty { ty::TyTrait(box ref data) => { - self.assemble_inherent_candidates_from_object(self_ty, data.principal); - self.assemble_inherent_impl_candidates_for_type(data.principal.def_id()); + self.assemble_inherent_candidates_from_object(self_ty, data.principal().unwrap()); + self.assemble_inherent_impl_candidates_for_type(data.principal().unwrap().def_id()); } ty::TyAdt(def, _) => { self.assemble_inherent_impl_candidates_for_type(def.did); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 6598790355e82..eb6e84c7922ce 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -379,7 +379,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match ty.sty { ty::TyAdt(def, _) => def.did.is_local(), - ty::TyTrait(ref tr) => tr.principal.def_id().is_local(), + ty::TyTrait(ref tr) => tr.principal().map(|p| p.def_id().is_local()).unwrap_or(false), ty::TyParam(_) => true, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 2663739e36b28..0b6f2f554a177 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -68,7 +68,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { match ty.sty { TyAdt(def, _) => Some(def.did), - TyTrait(ref t) => Some(t.principal.def_id()), + TyTrait(ref t) => t.principal().map(|p| p.def_id()), TyBox(_) => self.inference_context.tcx.lang_items.owned_box(), diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index a507077bef77e..f949a8796c7e0 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -86,8 +86,8 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { ty::TyAdt(def, _) => { self.check_def_id(item, def.did); } - ty::TyTrait(ref data) => { - self.check_def_id(item, data.principal.def_id()); + ty::TyTrait(ref data) if data.principal().is_some() => { + self.check_def_id(item, data.principal().unwrap().def_id()); } ty::TyBox(..) => { match self.tcx.lang_items.require_owned_box() { diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index e5be7f63067a8..305b15caa69a1 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -182,14 +182,14 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> { // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. - if !self.tcx.is_object_safe(data.principal.def_id()) { + if data.principal().is_none() || !self.tcx.is_object_safe(data.principal().unwrap().def_id()) { // This is an error, but it will be // reported by wfcheck. Ignore it // here. This is tested by // `coherence-impl-trait-for-trait-object-safe.rs`. } else { let mut supertrait_def_ids = - traits::supertrait_def_ids(self.tcx, data.principal.def_id()); + traits::supertrait_def_ids(self.tcx, data.principal().unwrap().def_id()); if supertrait_def_ids.any(|d| d == trait_def_id) { span_err!(self.tcx.sess, item.span, diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 686d1a4a7716d..77ade4660693a 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -376,7 +376,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let contra = self.contravariant(variance); self.add_constraints_from_region(generics, data.region_bound, contra); - let poly_trait_ref = data.principal.with_self_ty(self.tcx(), self.tcx().types.err); + let poly_trait_ref = data.principal().unwrap().with_self_ty(self.tcx(), self.tcx().types.err); self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance); for projection in &data.projection_bounds { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e233613ee629e..f32ee29c0a0be 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1877,30 +1877,34 @@ impl<'tcx> Clean for ty::Ty<'tcx> { } } ty::TyTrait(ref obj) => { - let did = obj.principal.def_id(); - inline::record_extern_fqn(cx, did, TypeKind::Trait); - - let mut typarams = vec![]; - obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b))); - for bb in &obj.builtin_bounds { - typarams.push(bb.clean(cx)); - } + if let Some(principal) = obj.principal() { + let did = principal.def_id(); + inline::record_extern_fqn(cx, did, TypeKind::Trait); + + let mut typarams = vec![]; + obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b))); + for bb in &obj.builtin_bounds { + typarams.push(bb.clean(cx)); + } - let mut bindings = vec![]; - for &ty::Binder(ref pb) in &obj.projection_bounds { - bindings.push(TypeBinding { - name: pb.item_name.clean(cx), - ty: pb.ty.clean(cx) - }); - } + let mut bindings = vec![]; + for &ty::Binder(ref pb) in &obj.projection_bounds { + bindings.push(TypeBinding { + name: pb.item_name.clean(cx), + ty: pb.ty.clean(cx) + }); + } - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), - Some(did), false, bindings, obj.principal.0.substs); - ResolvedPath { - path: path, - typarams: Some(typarams), - did: did, - is_generic: false, + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), + Some(did), false, bindings, obj.principal.0.substs); + ResolvedPath { + path: path, + typarams: Some(typarams), + did: did, + is_generic: false, + } + } else { + Never } } ty::TyTuple(ref t) => Tuple(t.clean(cx)), From 607af7218b31ed00c8f613deedf8f4f7ae59cd13 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Sun, 13 Nov 2016 15:25:54 -0700 Subject: [PATCH 2/7] Refactor BuiltinBounds to Vec on TraitObject. --- src/librustc/traits/select.rs | 46 ++++++++++++++--------------- src/librustc/ty/relate.rs | 6 +++- src/librustc/ty/structural_impls.rs | 2 +- src/librustc/ty/sty.rs | 34 +++++++++++++-------- src/librustc/ty/util.rs | 4 ++- src/librustc/ty/wf.rs | 25 +++++++++------- src/librustc/util/ppaux.rs | 26 +++++++++------- src/librustc_typeck/astconv.rs | 36 +++++++++++----------- src/librustc_typeck/collect.rs | 8 ++--- src/librustdoc/clean/mod.rs | 24 +++++++++++++-- 10 files changed, 126 insertions(+), 85 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index f79a212a473cd..3ae0252e99020 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -41,6 +41,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use traits; use ty::fast_reject; use ty::relate::TypeRelation; +use middle::lang_items; use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::snapshot_vec::{SnapshotVecDelegate, SnapshotVec}; @@ -49,6 +50,7 @@ use std::fmt; use std::marker::PhantomData; use std::mem; use std::rc::Rc; +use std::iter; use syntax::abi::Abi; use hir; use util::nodemap::FxHashMap; @@ -1516,16 +1518,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty()); let poly_trait_ref = match self_ty.sty { ty::TyTrait(ref data) => { - match this.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { - Some(bound @ ty::BoundSend) | Some(bound @ ty::BoundSync) => { - if data.builtin_bounds.contains(&bound) { - debug!("assemble_candidates_from_object_ty: matched builtin bound, \ - pushing candidate"); - candidates.vec.push(BuiltinObjectCandidate); - return; - } - } - _ => {} + if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { + debug!("assemble_candidates_from_object_ty: matched builtin bound, \ + pushing candidate"); + candidates.vec.push(BuiltinObjectCandidate); + return; } match data.principal() { @@ -1616,7 +1613,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // #2 (region bounds). match (data_a.principal(), data_b.principal()) { (Some(ref a), Some(ref b)) => a.def_id() == b.def_id() && - data_a.builtin_bounds.is_superset(&data_b.builtin_bounds), + data_b.auto_traits() + // All of a's auto traits need to be in b's auto traits. + .all(|b| data_a.auto_traits().any(|a| a == b)), _ => false } } @@ -2481,7 +2480,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let new_trait = tcx.mk_trait(ty::TraitObject::new( data_a.principal(), data_b.region_bound, - data_b.builtin_bounds, + data_b.auto_traits().collect(), data_a.projection_bounds.clone(), )); let origin = TypeOrigin::Misc(obligation.cause.span); @@ -2504,10 +2503,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // T -> Trait. (_, &ty::TyTrait(ref data)) => { let mut object_dids = - data.builtin_bounds.iter().flat_map(|bound| { - tcx.lang_items.from_builtin_kind(bound).ok() - }) - .chain(data.principal().map(|ref p| p.def_id())); + data.auto_traits().chain(data.principal().map(|ref p| p.def_id())); if let Some(did) = object_dids.find(|did| { !tcx.is_object_safe(*did) }) { @@ -2527,19 +2523,21 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { push(data.principal().unwrap().with_self_ty(tcx, source).to_predicate()); // We can only make objects from sized types. - let mut builtin_bounds = data.builtin_bounds; - builtin_bounds.insert(ty::BoundSized); + let trait_refs = data.auto_traits() + .chain(iter::once( + tcx.lang_items.require(lang_items::SizedTraitLangItem) + .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])))) + .map(|did| ty::TraitRef { + def_id: did, + substs: tcx.mk_substs_trait(source, &[]), + }); // Create additional obligations for all the various builtin // bounds attached to the object cast. (In other words, if the // object type is Foo+Send, this would create an obligation // for the Send check.) - for bound in &builtin_bounds { - if let Ok(tr) = tcx.trait_ref_for_builtin_bound(bound, source) { - push(tr.to_predicate()); - } else { - return Err(Unimplemented); - } + for tr in trait_refs { + push(tr.to_predicate()); } // Create obligations for the projection predicates. diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index a70cfabac8738..569791a0776bf 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -428,7 +428,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, |relation| relation.relate_with_variance(ty::Contravariant, &a_obj.region_bound, &b_obj.region_bound))?; - let nb = relation.relate(&a_obj.builtin_bounds, &b_obj.builtin_bounds)?; + let nb = if !a_obj.auto_traits().eq(b_obj.auto_traits()) { + return Err(TypeError::Sorts(expected_found(relation, &a, &b))); + } else { + a_obj.auto_traits().collect() + }; let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?; Ok(tcx.mk_trait(ty::TraitObject::new(principal, r, nb, pb))) } diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 883f43258d899..3064e337039d5 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -432,7 +432,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { ty::TraitObject::new( self.principal().map(|p| p.fold_with(folder)), self.region_bound.fold_with(folder), - self.builtin_bounds, + self.auto_traits().collect(), self.projection_bounds.fold_with(folder), ) } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 454dedd937b7a..22a7423b17765 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -279,18 +279,18 @@ impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx> { pub struct TraitObject<'tcx> { principal: Option>, pub region_bound: &'tcx ty::Region, - pub builtin_bounds: BuiltinBounds, + auto_traits: Vec, pub projection_bounds: Vec>, } impl<'tcx> TraitObject<'tcx> { pub fn new(principal: Option>, region_bound: &'tcx ty::Region, - builtin_bounds: BuiltinBounds, projection_bounds: Vec>) + auto_traits: Vec, projection_bounds: Vec>) -> Self { TraitObject { principal: principal, region_bound: region_bound, - builtin_bounds: builtin_bounds, + auto_traits: auto_traits, projection_bounds: projection_bounds, } } @@ -298,6 +298,10 @@ impl<'tcx> TraitObject<'tcx> { pub fn principal(&self) -> Option> { self.principal } + + pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { + self.auto_traits.iter().cloned() + } } /// A complete reference to a trait. These take numerous guises in syntax, @@ -833,18 +837,22 @@ impl CLike for BuiltinBound { impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn try_add_builtin_trait(self, - trait_def_id: DefId, - builtin_bounds: &mut EnumSet) + id: DefId, + auto_traits: &mut Vec) -> bool { - //! Checks whether `trait_ref` refers to one of the builtin - //! traits, like `Send`, and adds the corresponding - //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref` - //! is a builtin trait. - - match self.lang_items.to_builtin_kind(trait_def_id) { - Some(bound) => { builtin_bounds.insert(bound); true } - None => false + //! Checks whether `id` refers to one of the builtin + //! traits, like `Send`, and adds it to `auto_traits` if so. + //! Returns true if `idf` refers to a builtin trait. + + if Some(id) == self.lang_items.send_trait() || + Some(id) == self.lang_items.sized_trait() || + Some(id) == self.lang_items.copy_trait() || + Some(id) == self.lang_items.sync_trait() { + auto_traits.push(id); + true + } else { + false } } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index bd7d72d3ef398..7253b88981f1b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -535,7 +535,9 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc if let Some(ref p) = data.principal() { self.def_id(p.def_id()); } - self.hash(data.builtin_bounds); + for d in data.auto_traits() { + self.def_id(d); + } } TyTuple(tys) => { self.hash(tys.len()); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 25015557ad4df..b31046abf86a3 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -298,7 +298,6 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// is WF. Returns false if `ty0` is an unresolved type variable, /// in which case we are not able to simplify at all. fn compute(&mut self, ty0: Ty<'tcx>) -> bool { - let tcx = self.infcx.tcx; let mut subtys = ty0.walk(); while let Some(ty) = subtys.next() { match ty.sty { @@ -391,15 +390,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let cause = self.cause(traits::MiscObligation); let component_traits = - data.builtin_bounds.iter().flat_map(|bound| { - tcx.lang_items.from_builtin_kind(bound).ok() - }) - .chain(data.principal().map(|ref p| p.def_id())); + data.auto_traits().chain(data.principal().map(|ref p| p.def_id())); self.out.extend( - component_traits.map(|did| { traits::Obligation::new( + component_traits.map(|did| traits::Obligation::new( cause.clone(), ty::Predicate::ObjectSafe(did) - )}) + )) ); } @@ -493,7 +489,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let implicit_bounds = object_region_bounds(self.infcx.tcx, data.principal().unwrap(), - data.builtin_bounds); + data.auto_traits()); let explicit_bound = data.region_bound; @@ -512,18 +508,25 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// they declare `trait SomeTrait : 'static`, for example, then /// `'static` would appear in the list. The hard work is done by /// `ty::required_region_bounds`, see that for more information. -pub fn object_region_bounds<'a, 'gcx, 'tcx>( +pub fn object_region_bounds<'a, 'gcx, 'tcx, I>( tcx: TyCtxt<'a, 'gcx, 'tcx>, principal: ty::PolyExistentialTraitRef<'tcx>, - others: ty::BuiltinBounds) + others: I) -> Vec<&'tcx ty::Region> + where I: Iterator { // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically // a skolemized type. let open_ty = tcx.mk_infer(ty::FreshTy(0)); - let mut predicates = others.to_predicates(tcx, open_ty); + let mut predicates = others.map(|d| { + let trait_ref = ty::TraitRef { + def_id: d, + substs: tcx.mk_substs_trait(open_ty, &[]) + }; + trait_ref.to_predicate() + }).collect::>(); predicates.push(principal.with_self_ty(tcx, open_ty).to_predicate()); tcx.required_region_bounds(open_ty, predicates) diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index c87f3ba0a59a5..a3fa805699c9e 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -349,13 +349,15 @@ impl<'tcx> fmt::Display for ty::TraitObject<'tcx> { }).collect(); let tap = ty::Binder(TraitAndProjections(principal, projections)); - in_binder(f, tcx, &ty::Binder(""), Some(tap)) - })?; + in_binder(f, tcx, &ty::Binder(""), Some(tap))?; - // Builtin bounds. - for bound in &self.builtin_bounds { - write!(f, " + {:?}", bound)?; - } + // Builtin bounds. + for did in self.auto_traits() { + write!(f, " + {}", tcx.item_path_str(did))?; + } + + Ok(()) + })?; // FIXME: It'd be nice to compute from context when this bound // is implied, but that's non-trivial -- we'd perhaps have to @@ -474,10 +476,14 @@ impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> { write!(f, "{}", region_str)?; } - for bound in &self.builtin_bounds { - maybe_continue(f)?; - write!(f, "{:?}", bound)?; - } + ty::tls::with(|tcx| { + for did in self.auto_traits() { + maybe_continue(f)?; + write!(f, " + {}", tcx.item_path_str(did))?; + } + + Ok(()) + })?; for projection_bound in &self.projection_bounds { maybe_continue(f)?; diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 9cf6f555744c1..bffd85c57f705 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1043,7 +1043,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_segment, &mut projection_bounds); - let PartitionedBounds { builtin_bounds, + let PartitionedBounds { auto_traits, trait_bounds, region_bounds } = partitioned_bounds; @@ -1076,7 +1076,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { self.compute_object_lifetime_bound(span, ®ion_bounds, existential_principal, - builtin_bounds); + &auto_traits); let region_bound = match region_bound { Some(r) => r, @@ -1138,7 +1138,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let ty = tcx.mk_trait(ty::TraitObject::new( Some(existential_principal), region_bound, - builtin_bounds, + auto_traits, existential_projections )); debug!("trait_object_type: {:?}", ty); @@ -1923,16 +1923,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span: Span, explicit_region_bounds: &[&hir::Lifetime], principal_trait_ref: ty::PolyExistentialTraitRef<'tcx>, - builtin_bounds: ty::BuiltinBounds) + auto_traits: &[DefId]) -> Option<&'tcx ty::Region> // if None, use the default { let tcx = self.tcx(); debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \ - principal_trait_ref={:?}, builtin_bounds={:?})", + principal_trait_ref={:?}, auto_traits={:?})", explicit_region_bounds, principal_trait_ref, - builtin_bounds); + auto_traits); if explicit_region_bounds.len() > 1 { span_err!(tcx.sess, explicit_region_bounds[1].span, E0226, @@ -1953,7 +1953,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = - object_region_bounds(tcx, principal_trait_ref, builtin_bounds); + object_region_bounds(tcx, principal_trait_ref, auto_traits.into_iter().cloned()); // If there are no derived region bounds, then report back that we // can find no region bound. The caller will use the default. @@ -1980,7 +1980,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } pub struct PartitionedBounds<'a> { - pub builtin_bounds: ty::BuiltinBounds, + pub auto_traits: Vec, pub trait_bounds: Vec<&'a hir::PolyTraitRef>, pub region_bounds: Vec<&'a hir::Lifetime>, } @@ -1992,7 +1992,7 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ast_bounds: &'b [hir::TyParamBound]) -> PartitionedBounds<'b> { - let mut builtin_bounds = ty::BuiltinBounds::empty(); + let mut auto_traits = Vec::new(); let mut region_bounds = Vec::new(); let mut trait_bounds = Vec::new(); for ast_bound in ast_bounds { @@ -2000,8 +2000,7 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => { match b.trait_ref.path.def { Def::Trait(trait_did) => { - if tcx.try_add_builtin_trait(trait_did, - &mut builtin_bounds) { + if tcx.try_add_builtin_trait(trait_did, &mut auto_traits) { let segments = &b.trait_ref.path.segments; let parameters = &segments[segments.len() - 1].parameters; if !parameters.types().is_empty() { @@ -2030,7 +2029,7 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } PartitionedBounds { - builtin_bounds: builtin_bounds, + auto_traits: auto_traits, trait_bounds: trait_bounds, region_bounds: region_bounds, } @@ -2105,7 +2104,7 @@ fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected #[derive(PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { pub region_bounds: Vec<&'tcx ty::Region>, - pub builtin_bounds: ty::BuiltinBounds, + pub auto_traits: Vec, pub trait_bounds: Vec>, pub projection_bounds: Vec>, } @@ -2116,11 +2115,12 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { { let mut vec = Vec::new(); - for builtin_bound in &self.builtin_bounds { - match tcx.trait_ref_for_builtin_bound(builtin_bound, param_ty) { - Ok(trait_ref) => { vec.push(trait_ref.to_predicate()); } - Err(ErrorReported) => { } - } + for trait_did in &self.auto_traits { + let trait_ref = ty::TraitRef { + def_id: *trait_did, + substs: tcx.mk_substs_trait(param_ty, &[]), + }; + vec.push(trait_ref.to_predicate()); } for ®ion_bound in &self.region_bounds { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0dcc0bcc316ce..0f8fe32c8982e 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1586,7 +1586,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // Add the Sized bound, unless the type parameter is marked as `?Sized`. fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, - bounds: &mut ty::BuiltinBounds, + bounds: &mut Vec, ast_bounds: &[hir::TyParamBound], span: Span) { @@ -1908,13 +1908,13 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, { let tcx = astconv.tcx(); let PartitionedBounds { - mut builtin_bounds, + mut auto_traits, trait_bounds, region_bounds } = partition_bounds(tcx, span, &ast_bounds); if let SizedByDefault::Yes = sized_by_default { - add_unsized_bound(astconv, &mut builtin_bounds, ast_bounds, span); + add_unsized_bound(astconv, &mut auto_traits, ast_bounds, span); } let mut projection_bounds = vec![]; @@ -1935,7 +1935,7 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, Bounds { region_bounds: region_bounds, - builtin_bounds: builtin_bounds, + auto_traits: auto_traits, trait_bounds: trait_bounds, projection_bounds: projection_bounds, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f32ee29c0a0be..6b0f0ae12975c 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1883,8 +1883,28 @@ impl<'tcx> Clean for ty::Ty<'tcx> { let mut typarams = vec![]; obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b))); - for bb in &obj.builtin_bounds { - typarams.push(bb.clean(cx)); + for did in obj.auto_traits() { + let tcx = match cx.tcx_opt() { + Some(tcx) => tcx, + None => { + typarams.push(RegionBound(Lifetime::statik())); + continue; + } + }; + let empty = tcx.intern_substs(&[]); + let path = external_path(cx, &tcx.item_name(did).as_str(), + Some(did), false, vec![], empty); + inline::record_extern_fqn(cx, did, TypeKind::Trait); + let bound = TraitBound(PolyTrait { + trait_: ResolvedPath { + path: path, + typarams: None, + did: did, + is_generic: false, + }, + lifetimes: vec![] + }, hir::TraitBoundModifier::None); + typarams.push(bound); } let mut bindings = vec![]; From 64e97d9b33ac7a38ec9f0ae1575771cdad4afac0 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Sun, 13 Nov 2016 19:42:15 -0700 Subject: [PATCH 3/7] Remove BuiltinBound and BuiltinBounds. --- src/librustc/infer/mod.rs | 6 +- src/librustc/lib.rs | 1 - src/librustc/middle/lang_items.rs | 25 ------- src/librustc/traits/error_reporting.rs | 10 --- src/librustc/traits/fulfill.rs | 21 +++--- src/librustc/traits/mod.rs | 45 ++++++------ src/librustc/traits/select.rs | 16 ++--- src/librustc/traits/structural_impls.rs | 5 -- src/librustc/traits/util.rs | 31 -------- src/librustc/ty/error.rs | 14 ---- src/librustc/ty/mod.rs | 6 -- src/librustc/ty/relate.rs | 17 ----- src/librustc/ty/structural_impls.rs | 11 --- src/librustc/ty/sty.rs | 70 +------------------ src/librustc/ty/util.rs | 16 +++-- src/librustc/ty/wf.rs | 16 ++--- src/librustc/util/ppaux.rs | 13 ---- src/librustc_mir/transform/qualify_consts.rs | 7 +- src/librustc_typeck/check/cast.rs | 5 +- src/librustc_typeck/check/closure.rs | 3 +- src/librustc_typeck/check/method/suggest.rs | 3 +- src/librustc_typeck/check/mod.rs | 21 +++--- src/librustc_typeck/check/wfcheck.rs | 19 ++--- src/librustc_typeck/coherence/overlap.rs | 6 +- src/librustc_typeck/variance/constraints.rs | 3 +- src/librustdoc/clean/mod.rs | 57 +++++---------- src/test/compile-fail/bad-sized.rs | 4 +- src/test/compile-fail/const-unsized.rs | 8 +-- src/test/compile-fail/issue-32963.rs | 2 +- .../compile-fail/trait-bounds-cant-coerce.rs | 8 +-- .../trait-bounds-not-on-bare-trait.rs | 2 +- 31 files changed, 138 insertions(+), 333 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 6ae104d79122b..9c63eac34e440 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -24,6 +24,7 @@ use middle::free_region::FreeRegionMap; use middle::mem_categorization as mc; use middle::mem_categorization::McResult; use middle::region::CodeExtent; +use middle::lang_items; use mir::tcx::LvalueTy; use ty::subst::{Kind, Subst, Substs}; use ty::adjustment; @@ -1492,11 +1493,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } + let copy_def_id = self.tcx.lang_items.require(lang_items::CopyTraitLangItem) + .unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..])); + // this can get called from typeck (by euv), and moves_by_default // rightly refuses to work with inference variables, but // moves_by_default has a cache, which we want to use in other // cases. - !traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span) + !traits::type_known_to_meet_bound(self, ty, copy_def_id, span) } pub fn node_method_ty(&self, method_call: ty::MethodCall) diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index 0942ce79a6b49..c0ea8d6b1e38b 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -32,7 +32,6 @@ #![feature(const_fn)] #![feature(core_intrinsics)] #![cfg_attr(stage0, feature(dotdot_in_tuple_patterns))] -#![feature(enumset)] #![cfg_attr(stage0, feature(item_like_imports))] #![feature(libc)] #![feature(nonzero)] diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 5af9a2f02742e..8d02d63e3a4bb 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -90,31 +90,6 @@ impl LanguageItems { self.require(OwnedBoxLangItem) } - pub fn from_builtin_kind(&self, bound: ty::BuiltinBound) - -> Result - { - match bound { - ty::BoundSend => self.require(SendTraitLangItem), - ty::BoundSized => self.require(SizedTraitLangItem), - ty::BoundCopy => self.require(CopyTraitLangItem), - ty::BoundSync => self.require(SyncTraitLangItem), - } - } - - pub fn to_builtin_kind(&self, id: DefId) -> Option { - if Some(id) == self.send_trait() { - Some(ty::BoundSend) - } else if Some(id) == self.sized_trait() { - Some(ty::BoundSized) - } else if Some(id) == self.copy_trait() { - Some(ty::BoundCopy) - } else if Some(id) == self.sync_trait() { - Some(ty::BoundSync) - } else { - None - } - } - pub fn fn_trait_kind(&self, id: DefId) -> Option { let def_id_kinds = [ (self.fn_trait(), ty::ClosureKind::Fn), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 21009711cb18a..4ac4c31386e71 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -905,16 +905,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ObligationCauseCode::StructInitializerSized => { err.note("structs must have a statically known size to be initialized"); } - ObligationCauseCode::ClosureCapture(var_id, _, builtin_bound) => { - let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap(); - let trait_name = tcx.item_path_str(def_id); - let name = tcx.local_var_name_str(var_id); - err.note( - &format!("the closure that captures `{}` requires that all captured variables \ - implement the trait `{}`", - name, - trait_name)); - } ObligationCauseCode::FieldSized => { err.note("only the last field of a struct may have a dynamically sized type"); } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index f406580286da9..9ff4048f73e77 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -17,8 +17,8 @@ use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProce use std::marker::PhantomData; use std::mem; use syntax::ast; -use util::common::ErrorReported; use util::nodemap::{FxHashSet, NodeMap}; +use hir::def_id::DefId; use super::CodeAmbiguity; use super::CodeProjectionError; @@ -230,18 +230,21 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { normalized.value } - pub fn register_builtin_bound(&mut self, + pub fn register_bound(&mut self, infcx: &InferCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>, - builtin_bound: ty::BuiltinBound, + def_id: DefId, cause: ObligationCause<'tcx>) { - match infcx.tcx.predicate_for_builtin_bound(cause, builtin_bound, 0, ty) { - Ok(predicate) => { - self.register_predicate_obligation(infcx, predicate); - } - Err(ErrorReported) => { } - } + let trait_ref = ty::TraitRef { + def_id: def_id, + substs: infcx.tcx.mk_substs_trait(ty, &[]), + }; + self.register_predicate_obligation(infcx, Obligation { + cause: cause, + recursion_depth: 0, + predicate: trait_ref.to_predicate() + }); } pub fn register_region_obligation(&mut self, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index a5fdaed971257..bdd0ee75eb195 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -19,7 +19,7 @@ use hir; use hir::def_id::DefId; use middle::free_region::FreeRegionMap; use ty::subst::Substs; -use ty::{self, Ty, TyCtxt, TypeFoldable}; +use ty::{self, Ty, TyCtxt, TypeFoldable, ToPredicate}; use infer::InferCtxt; use std::rc::Rc; @@ -125,10 +125,6 @@ pub enum ObligationCauseCode<'tcx> { ReturnType, // Return type must be Sized RepeatVec, // [T,..n] --> T must be Copy - // Captures of variable the given id by a closure (span is the - // span of the closure) - ClosureCapture(ast::NodeId, Span, ty::BuiltinBound), - // Types of fields (other than the last) in a struct must be sized. FieldSized, @@ -369,27 +365,30 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, /// `bound` or is not known to meet bound (note that this is /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). -pub fn type_known_to_meet_builtin_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, +pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>, - bound: ty::BuiltinBound, + def_id: DefId, span: Span) -> bool { - debug!("type_known_to_meet_builtin_bound(ty={:?}, bound={:?})", + debug!("type_known_to_meet_bound(ty={:?}, bound={:?})", ty, - bound); - - let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); - let obligation = - infcx.tcx.predicate_for_builtin_bound(cause, bound, 0, ty); - let obligation = match obligation { - Ok(o) => o, - Err(..) => return false + infcx.tcx.item_path_str(def_id)); + + let trait_ref = ty::TraitRef { + def_id: def_id, + substs: infcx.tcx.mk_substs_trait(ty, &[]), }; + let obligation = Obligation { + cause: ObligationCause::misc(span, ast::DUMMY_NODE_ID), + recursion_depth: 0, + predicate: trait_ref.to_predicate(), + }; + let result = SelectionContext::new(infcx) .evaluate_obligation_conservatively(&obligation); - debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} => {:?}", - ty, bound, result); + debug!("type_known_to_meet_ty={:?} bound={} => {:?}", + ty, infcx.tcx.item_path_str(def_id), result); if result && (ty.has_infer_types() || ty.has_closure_types()) { // Because of inference "guessing", selection can sometimes claim @@ -404,22 +403,22 @@ pub fn type_known_to_meet_builtin_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'g // anyhow). let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID); - fulfill_cx.register_builtin_bound(infcx, ty, bound, cause); + fulfill_cx.register_bound(infcx, ty, def_id, cause); // Note: we only assume something is `Copy` if we can // *definitively* show that it implements `Copy`. Otherwise, // assume it is move; linear is always ok. match fulfill_cx.select_all_or_error(infcx) { Ok(()) => { - debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} success", + debug!("type_known_to_meet_bound: ty={:?} bound={} success", ty, - bound); + infcx.tcx.item_path_str(def_id)); true } Err(e) => { - debug!("type_known_to_meet_builtin_bound: ty={:?} bound={:?} errors={:?}", + debug!("type_known_to_meet_bound: ty={:?} bound={} errors={:?}", ty, - bound, + infcx.tcx.item_path_str(def_id), e); false } diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 3ae0252e99020..11b23d699de2f 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1093,8 +1093,9 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // Other bounds. Consider both in-scope bounds from fn decl // and applicable impls. There is a certain set of precedence rules here. - match self.tcx().lang_items.to_builtin_kind(obligation.predicate.def_id()) { - Some(ty::BoundCopy) => { + let def_id = obligation.predicate.def_id(); + match obligation.predicate.def_id() { + _ if self.tcx().lang_items.copy_trait() == Some(def_id) => { debug!("obligation self ty is {:?}", obligation.predicate.0.self_ty()); @@ -1106,7 +1107,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let copy_conditions = self.copy_conditions(obligation); self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?; } - Some(ty::BoundSized) => { + _ if self.tcx().lang_items.sized_trait() == Some(def_id) => { // Sized is never implementable by end-users, it is // always automatically computed. let sized_conditions = self.sized_conditions(obligation); @@ -1114,14 +1115,12 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &mut candidates)?; } - None if self.tcx().lang_items.unsize_trait() == - Some(obligation.predicate.def_id()) => { + _ if self.tcx().lang_items.unsize_trait() == Some(def_id) => { self.assemble_candidates_for_unsizing(obligation, &mut candidates); } - Some(ty::BoundSend) | - Some(ty::BoundSync) | - None => { + // For non-builtins and Send/Sync + _ => { self.assemble_closure_candidates(obligation, &mut candidates)?; self.assemble_fn_pointer_candidates(obligation, &mut candidates)?; self.assemble_candidates_from_impls(obligation, &mut candidates)?; @@ -2483,7 +2482,6 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { data_b.auto_traits().collect(), data_a.projection_bounds.clone(), )); - let origin = TypeOrigin::Misc(obligation.cause.span); let InferOk { obligations, .. } = self.infcx.sub_types(false, &obligation.cause, new_trait, target) .map_err(|_| Unimplemented)?; diff --git a/src/librustc/traits/structural_impls.rs b/src/librustc/traits/structural_impls.rs index d03ba5b0a31f1..dedb126d7ff6d 100644 --- a/src/librustc/traits/structural_impls.rs +++ b/src/librustc/traits/structural_impls.rs @@ -190,9 +190,6 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { super::VariableType(id) => Some(super::VariableType(id)), super::ReturnType => Some(super::ReturnType), super::RepeatVec => Some(super::RepeatVec), - super::ClosureCapture(node_id, span, bound) => { - Some(super::ClosureCapture(node_id, span, bound)) - } super::FieldSized => Some(super::FieldSized), super::ConstSized => Some(super::ConstSized), super::SharedStatic => Some(super::SharedStatic), @@ -507,7 +504,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::VariableType(_) | super::ReturnType | super::RepeatVec | - super::ClosureCapture(..) | super::FieldSized | super::ConstSized | super::SharedStatic | @@ -552,7 +548,6 @@ impl<'tcx> TypeFoldable<'tcx> for traits::ObligationCauseCode<'tcx> { super::VariableType(_) | super::ReturnType | super::RepeatVec | - super::ClosureCapture(..) | super::FieldSized | super::ConstSized | super::SharedStatic | diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs index b94597d475927..321936fe54be1 100644 --- a/src/librustc/traits/util.rs +++ b/src/librustc/traits/util.rs @@ -12,7 +12,6 @@ use hir::def_id::DefId; use ty::subst::{Subst, Substs}; use ty::{self, Ty, TyCtxt, ToPredicate, ToPolyTraitRef}; use ty::outlives::Component; -use util::common::ErrorReported; use util::nodemap::FxHashSet; use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized}; @@ -408,25 +407,6 @@ pub fn predicate_for_trait_ref<'tcx>( } impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn trait_ref_for_builtin_bound(self, - builtin_bound: ty::BuiltinBound, - param_ty: Ty<'tcx>) - -> Result, ErrorReported> - { - match self.lang_items.from_builtin_kind(builtin_bound) { - Ok(def_id) => { - Ok(ty::TraitRef { - def_id: def_id, - substs: self.mk_substs_trait(param_ty, &[]) - }) - } - Err(e) => { - self.sess.err(&e); - Err(ErrorReported) - } - } - } - pub fn predicate_for_trait_def(self, cause: ObligationCause<'tcx>, trait_def_id: DefId, @@ -442,17 +422,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { predicate_for_trait_ref(cause, trait_ref, recursion_depth) } - pub fn predicate_for_builtin_bound(self, - cause: ObligationCause<'tcx>, - builtin_bound: ty::BuiltinBound, - recursion_depth: usize, - param_ty: Ty<'tcx>) - -> Result, ErrorReported> - { - let trait_ref = self.trait_ref_for_builtin_bound(builtin_bound, param_ty)?; - Ok(predicate_for_trait_ref(cause, trait_ref, recursion_depth)) - } - /// Cast a trait reference into a reference to one of its super /// traits; returns `None` if `target_trait_def_id` is not a /// supertrait. diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 8bdcc93fa2114..8ef13e62901a6 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -45,7 +45,6 @@ pub enum TypeError<'tcx> { IntMismatch(ExpectedFound), FloatMismatch(ExpectedFound), Traits(ExpectedFound), - BuiltinBoundsMismatch(ExpectedFound), VariadicMismatch(ExpectedFound), CyclicTy, ProjectionNameMismatched(ExpectedFound), @@ -135,19 +134,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { format!("trait `{}`", tcx.item_path_str(values.found))) }), - BuiltinBoundsMismatch(values) => { - if values.expected.is_empty() { - write!(f, "expected no bounds, found `{}`", - values.found) - } else if values.found.is_empty() { - write!(f, "expected bounds `{}`, found no bounds", - values.expected) - } else { - write!(f, "expected bounds `{}`, found bounds `{}`", - values.expected, - values.found) - } - } IntMismatch(ref values) => { write!(f, "expected `{:?}`, found `{:?}`", values.expected, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 844fc58cec37b..4544cda0ae9ae 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -53,7 +53,6 @@ use hir; use hir::itemlikevisit::ItemLikeVisitor; pub use self::sty::{Binder, DebruijnIndex}; -pub use self::sty::{BuiltinBound, BuiltinBounds}; pub use self::sty::{BareFnTy, FnSig, PolyFnSig}; pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject}; pub use self::sty::{ClosureSubsts, TypeAndMut}; @@ -68,11 +67,6 @@ pub use self::sty::InferTy::*; pub use self::sty::Region::*; pub use self::sty::TypeVariants::*; -pub use self::sty::BuiltinBound::Send as BoundSend; -pub use self::sty::BuiltinBound::Sized as BoundSized; -pub use self::sty::BuiltinBound::Copy as BoundCopy; -pub use self::sty::BuiltinBound::Sync as BoundSync; - pub use self::contents::TypeContents; pub use self::context::{TyCtxt, tls}; pub use self::context::{CtxtArenas, Lift, Tables}; diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 569791a0776bf..02704e94fee98 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -302,23 +302,6 @@ impl<'tcx> Relate<'tcx> for Vec> { } } -impl<'tcx> Relate<'tcx> for ty::BuiltinBounds { - fn relate<'a, 'gcx, R>(relation: &mut R, - a: &ty::BuiltinBounds, - b: &ty::BuiltinBounds) - -> RelateResult<'tcx, ty::BuiltinBounds> - where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a - { - // Two sets of builtin bounds are only relatable if they are - // precisely the same (but see the coercion code). - if a != b { - Err(TypeError::BuiltinBoundsMismatch(expected_found(relation, a, b))) - } else { - Ok(*a) - } - } -} - impl<'tcx> Relate<'tcx> for ty::TraitRef<'tcx> { fn relate<'a, 'gcx, R>(relation: &mut R, a: &ty::TraitRef<'tcx>, diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 3064e337039d5..e890d750a7b50 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -315,7 +315,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { IntMismatch(x) => IntMismatch(x), FloatMismatch(x) => FloatMismatch(x), Traits(x) => Traits(x), - BuiltinBoundsMismatch(x) => BuiltinBoundsMismatch(x), VariadicMismatch(x) => VariadicMismatch(x), CyclicTy => CyclicTy, ProjectionNameMismatched(x) => ProjectionNameMismatched(x), @@ -703,16 +702,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::adjustment::AutoBorrow<'tcx> { } } -impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self { - *self - } - - fn super_visit_with>(&self, _visitor: &mut V) -> bool { - false - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { ty::TypeParameterDef { diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 22a7423b17765..e6411ca1e4f68 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -14,13 +14,10 @@ use hir::def_id::DefId; use middle::region; use ty::subst::Substs; -use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TypeFoldable}; +use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{Slice, TyS}; -use util::common::ErrorReported; -use collections::enum_set::{self, EnumSet, CLike}; use std::fmt; -use std::ops; use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::symbol::{keywords, InternedString}; @@ -770,71 +767,6 @@ impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { } } -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] -pub struct BuiltinBounds(EnumSet); - -impl<'a, 'gcx, 'tcx> BuiltinBounds { - pub fn empty() -> BuiltinBounds { - BuiltinBounds(EnumSet::new()) - } - - pub fn iter(&self) -> enum_set::Iter { - self.into_iter() - } - - pub fn to_predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - self_ty: Ty<'tcx>) - -> Vec> { - self.iter().filter_map(|builtin_bound| - match tcx.trait_ref_for_builtin_bound(builtin_bound, self_ty) { - Ok(trait_ref) => Some(trait_ref.to_predicate()), - Err(ErrorReported) => { None } - } - ).collect() - } -} - -impl ops::Deref for BuiltinBounds { - type Target = EnumSet; - fn deref(&self) -> &Self::Target { &self.0 } -} - -impl ops::DerefMut for BuiltinBounds { - fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } -} - -impl<'a> IntoIterator for &'a BuiltinBounds { - type Item = BuiltinBound; - type IntoIter = enum_set::Iter; - fn into_iter(self) -> Self::IntoIter { - (**self).into_iter() - } -} - -#[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash, - Debug, Copy)] -pub enum BuiltinBound { - Send = 0, - Sized = 1, - Copy = 2, - Sync = 3, -} - -impl CLike for BuiltinBound { - fn to_usize(&self) -> usize { - *self as usize - } - fn from_usize(v: usize) -> BuiltinBound { - match v { - 0 => BuiltinBound::Send, - 1 => BuiltinBound::Sized, - 2 => BuiltinBound::Copy, - 3 => BuiltinBound::Sync, - _ => bug!("{} is not a valid BuiltinBound", v) - } - } -} - impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn try_add_builtin_trait(self, id: DefId, diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 7253b88981f1b..350426e7f3e82 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -21,6 +21,7 @@ use ty::fold::TypeVisitor; use ty::layout::{Layout, LayoutError}; use ty::TypeVariants::*; use util::nodemap::FxHashMap; +use middle::lang_items; use rustc_const_math::{ConstInt, ConstIsize, ConstUsize}; @@ -599,7 +600,7 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc impl<'a, 'tcx> ty::TyS<'tcx> { fn impls_bound(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: &ParameterEnvironment<'tcx>, - bound: ty::BuiltinBound, + def_id: DefId, cache: &RefCell, bool>>, span: Span) -> bool { @@ -611,7 +612,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { let result = tcx.infer_ctxt(None, Some(param_env.clone()), Reveal::ExactMatch) .enter(|infcx| { - traits::type_known_to_meet_builtin_bound(&infcx, self, bound, span) + traits::type_known_to_meet_bound(&infcx, self, def_id, span) }); if self.has_param_types() || self.has_self_ty() { cache.borrow_mut().insert(self, result); @@ -644,8 +645,10 @@ impl<'a, 'tcx> ty::TyS<'tcx> { TyClosure(..) | TyAdt(..) | TyAnon(..) | TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None }.unwrap_or_else(|| { - !self.impls_bound(tcx, param_env, ty::BoundCopy, ¶m_env.is_copy_cache, span) - }); + !self.impls_bound(tcx, param_env, + tcx.lang_items.require(lang_items::CopyTraitLangItem) + .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])), + ¶m_env.is_copy_cache, span) }); if !self.has_param_types() && !self.has_self_ty() { self.flags.set(self.flags.get() | if result { @@ -686,8 +689,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> { TyAdt(..) | TyProjection(..) | TyParam(..) | TyInfer(..) | TyAnon(..) | TyError => None }.unwrap_or_else(|| { - self.impls_bound(tcx, param_env, ty::BoundSized, ¶m_env.is_sized_cache, span) - }); + self.impls_bound(tcx, param_env, tcx.lang_items.require(lang_items::SizedTraitLangItem) + .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])), + ¶m_env.is_copy_cache, span) }); if !self.has_param_types() && !self.has_self_ty() { self.flags.set(self.flags.get() | if result { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index b31046abf86a3..d0bc2f0797705 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -17,7 +17,7 @@ use ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable}; use std::iter::once; use syntax::ast; use syntax_pos::Span; -use util::common::ErrorReported; +use middle::lang_items; /// Returns the set of obligations needed to make `ty` well-formed. /// If `ty` contains unresolved inference variables, this may include @@ -282,14 +282,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) { if !subty.has_escaping_regions() { let cause = self.cause(cause); - match self.infcx.tcx.trait_ref_for_builtin_bound(ty::BoundSized, subty) { - Ok(trait_ref) => { - self.out.push( - traits::Obligation::new(cause, - trait_ref.to_predicate())); - } - Err(ErrorReported) => { } - } + let trait_ref = ty::TraitRef { + def_id: self.infcx.tcx.lang_items.require(lang_items::SizedTraitLangItem) + .unwrap_or_else(|msg| self.infcx.tcx.sess.fatal(&msg[..])), + substs: self.infcx.tcx.mk_substs_trait(subty, &[]), + }; + self.out.push(traits::Obligation::new(cause, trait_ref.to_predicate())); } } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a3fa805699c9e..242342a7f93d6 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -683,19 +683,6 @@ impl<'tcx> fmt::Display for ty::FnSig<'tcx> { } } -impl fmt::Display for ty::BuiltinBounds { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut bounds = self.iter(); - if let Some(bound) = bounds.next() { - write!(f, "{:?}", bound)?; - for bound in bounds { - write!(f, " + {:?}", bound)?; - } - } - Ok(()) - } -} - impl fmt::Debug for ty::TyVid { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "_#{}t", self.index) diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 4ff2beb3fdb77..9cd92cf1fdcf7 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -29,6 +29,7 @@ use rustc::mir::traversal::ReversePostorder; use rustc::mir::transform::{Pass, MirPass, MirSource}; use rustc::mir::visit::{LvalueContext, Visitor}; use rustc::util::nodemap::DefIdMap; +use rustc::middle::lang_items; use syntax::abi::Abi; use syntax::feature_gate::UnstableFeatures; use syntax_pos::Span; @@ -1046,7 +1047,11 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|infcx| { let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); - fulfillment_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause); + fulfillment_cx.register_bound(&infcx, ty, + tcx.lang_items + .require(lang_items::SyncTraitLangItem) + .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])), + cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { infcx.report_fulfillment_errors(&err); } diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 3e1a3c870ca0d..197e7793f4b2a 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -46,6 +46,7 @@ use rustc::hir; use rustc::traits; use rustc::ty::{self, Ty, TypeFoldable}; use rustc::ty::cast::{CastKind, CastTy}; +use rustc::middle::lang_items; use syntax::ast; use syntax_pos::Span; use util::common::ErrorReported; @@ -543,6 +544,8 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool { - traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundSized, span) + let lang_item = self.tcx.lang_items.require(lang_items::SizedTraitLangItem) + .unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..])); + traits::type_known_to_meet_bound(self, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 4627c166fc6f3..be6d65bf511fd 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -119,7 +119,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { self.deduce_sig_from_projection(&pb) }) .next(); - let kind = self.tcx.lang_items.fn_trait_kind(object_type.principal().unwrap().def_id()); + let kind = + self.tcx.lang_items.fn_trait_kind(object_type.principal().unwrap().def_id()); (sig, kind) } ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index eb6e84c7922ce..508b0e820cef1 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -379,7 +379,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match ty.sty { ty::TyAdt(def, _) => def.did.is_local(), - ty::TyTrait(ref tr) => tr.principal().map(|p| p.def_id().is_local()).unwrap_or(false), + ty::TyTrait(ref tr) => tr.principal().map(|p| + p.def_id().is_local()).unwrap_or(false), ty::TyParam(_) => true, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 2babb81bc407a..c921936800b38 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -123,6 +123,7 @@ use rustc::hir::intravisit::{self, Visitor}; use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::{self, PatKind}; use rustc::hir::print as pprust; +use rustc::middle::lang_items; use rustc_back::slice; use rustc_const_eval::eval_length; @@ -1805,11 +1806,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { ty: Ty<'tcx>, span: Span, code: traits::ObligationCauseCode<'tcx>, - bound: ty::BuiltinBound) + def_id: DefId) { - self.register_builtin_bound( + self.register_bound( ty, - bound, + def_id, traits::ObligationCause::new(span, self.body_id, code)); } @@ -1818,16 +1819,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, code: traits::ObligationCauseCode<'tcx>) { - self.require_type_meets(ty, span, code, ty::BoundSized); + let lang_item = self.tcx.lang_items.require(lang_items::SizedTraitLangItem) + .unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..])); + self.require_type_meets(ty, span, code, lang_item); } - pub fn register_builtin_bound(&self, + pub fn register_bound(&self, ty: Ty<'tcx>, - builtin_bound: ty::BuiltinBound, + def_id: DefId, cause: traits::ObligationCause<'tcx>) { self.fulfillment_cx.borrow_mut() - .register_builtin_bound(self, ty, builtin_bound, cause); + .register_bound(self, ty, def_id, cause); } pub fn register_predicate(&self, @@ -3899,7 +3902,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if count > 1 { // For [foo, ..n] where n > 1, `foo` must have // Copy type: - self.require_type_meets(t, expr.span, traits::RepeatVec, ty::BoundCopy); + let lang_item = self.tcx.lang_items.require(lang_items::CopyTraitLangItem) + .unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..])); + self.require_type_meets(t, expr.span, traits::RepeatVec, lang_item); } if element_ty.references_error() { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 1ad81660f836a..57859f9c84cb6 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -18,6 +18,7 @@ use middle::region::{CodeExtent}; use rustc::traits::{self, ObligationCauseCode}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::{FxHashSet, FxHashMap}; +use rustc::middle::lang_items; use syntax::ast; use syntax_pos::Span; @@ -118,12 +119,13 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { let trait_ref = ccx.tcx.impl_trait_ref(ccx.tcx.map.local_def_id(item.id)).unwrap(); ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id); - match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) { - Some(ty::BoundSend) | Some(ty::BoundSync) => {} - Some(_) | None => { - if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) { - error_192(ccx, item.span); - } + let sync_trait = ccx.tcx.lang_items.require(lang_items::SyncTraitLangItem) + .unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..])); + let send_trait = ccx.tcx.lang_items.require(lang_items::SendTraitLangItem) + .unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..])); + if trait_ref.def_id != sync_trait && trait_ref.def_id != send_trait { + if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) { + error_192(ccx, item.span); } } } @@ -241,9 +243,10 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { // For DST, all intermediate types must be sized. let unsized_len = if all_sized || variant.fields.is_empty() { 0 } else { 1 }; for field in &variant.fields[..variant.fields.len() - unsized_len] { - fcx.register_builtin_bound( + fcx.register_bound( field.ty, - ty::BoundSized, + fcx.tcx.lang_items.require(lang_items::SizedTraitLangItem) + .unwrap_or_else(|msg| fcx.tcx.sess.fatal(&msg[..])), traits::ObligationCause::new(field.span, fcx.body_id, traits::FieldSized)); diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 305b15caa69a1..5ae233f647939 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -182,14 +182,16 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> { // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. - if data.principal().is_none() || !self.tcx.is_object_safe(data.principal().unwrap().def_id()) { + if data.principal().is_none() || + !self.tcx.is_object_safe(data.principal().unwrap().def_id()) { // This is an error, but it will be // reported by wfcheck. Ignore it // here. This is tested by // `coherence-impl-trait-for-trait-object-safe.rs`. } else { let mut supertrait_def_ids = - traits::supertrait_def_ids(self.tcx, data.principal().unwrap().def_id()); + traits::supertrait_def_ids(self.tcx, + data.principal().unwrap().def_id()); if supertrait_def_ids.any(|d| d == trait_def_id) { span_err!(self.tcx.sess, item.span, diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 77ade4660693a..076d024c1e1bb 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -376,7 +376,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { let contra = self.contravariant(variance); self.add_constraints_from_region(generics, data.region_bound, contra); - let poly_trait_ref = data.principal().unwrap().with_self_ty(self.tcx(), self.tcx().types.err); + let poly_trait_ref = data.principal().unwrap().with_self_ty(self.tcx(), + self.tcx().types.err); self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance); for projection in &data.projection_bounds { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6b0f0ae12975c..9d98cdd3f0377 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -30,6 +30,7 @@ use syntax_pos::{self, DUMMY_SP, Pos}; use rustc_trans::back::link; use rustc::middle::privacy::AccessLevels; use rustc::middle::resolve_lifetime::DefRegion::*; +use rustc::middle::lang_items; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def_id::{self, DefId, DefIndex, CRATE_DEF_INDEX}; use rustc::hir::print as pprust; @@ -593,12 +594,21 @@ pub enum TyParamBound { impl TyParamBound { fn maybe_sized(cx: &DocContext) -> TyParamBound { - use rustc::hir::TraitBoundModifier as TBM; - let mut sized_bound = ty::BoundSized.clean(cx); - if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound { - *tbm = TBM::Maybe - }; - sized_bound + let did = cx.tcx().lang_items.require(lang_items::SizedTraitLangItem) + .unwrap_or_else(|msg| cx.tcx().sess.fatal(&msg[..])); + let empty = cx.tcx().intern_substs(&[]); + let path = external_path(cx, &cx.tcx().item_name(did).as_str(), + Some(did), false, vec![], empty); + inline::record_extern_fqn(cx, did, TypeKind::Trait); + TraitBound(PolyTrait { + trait_: ResolvedPath { + path: path, + typarams: None, + did: did, + is_generic: false, + }, + lifetimes: vec![] + }, hir::TraitBoundModifier::Maybe) } fn is_sized_bound(&self, cx: &DocContext) -> bool { @@ -675,37 +685,6 @@ fn external_path(cx: &DocContext, name: &str, trait_did: Option, has_self } } -impl Clean for ty::BuiltinBound { - fn clean(&self, cx: &DocContext) -> TyParamBound { - let tcx = cx.tcx; - let empty = tcx.intern_substs(&[]); - let (did, path) = match *self { - ty::BoundSend => - (tcx.lang_items.send_trait().unwrap(), - external_path(cx, "Send", None, false, vec![], empty)), - ty::BoundSized => - (tcx.lang_items.sized_trait().unwrap(), - external_path(cx, "Sized", None, false, vec![], empty)), - ty::BoundCopy => - (tcx.lang_items.copy_trait().unwrap(), - external_path(cx, "Copy", None, false, vec![], empty)), - ty::BoundSync => - (tcx.lang_items.sync_trait().unwrap(), - external_path(cx, "Sync", None, false, vec![], empty)), - }; - inline::record_extern_fqn(cx, did, TypeKind::Trait); - TraitBound(PolyTrait { - trait_: ResolvedPath { - path: path, - typarams: None, - did: did, - is_generic: false, - }, - lifetimes: vec![] - }, hir::TraitBoundModifier::None) - } -} - impl<'tcx> Clean for ty::TraitRef<'tcx> { fn clean(&self, cx: &DocContext) -> TyParamBound { inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait); @@ -1915,8 +1894,8 @@ impl<'tcx> Clean for ty::Ty<'tcx> { }); } - let path = external_path(cx, &cx.tcx.item_name(did).as_str(), - Some(did), false, bindings, obj.principal.0.substs); + let path = external_path(cx, &cx.tcx().item_name(did).as_str(), Some(did), + false, bindings, principal.0.substs); ResolvedPath { path: path, typarams: Some(typarams), diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index e9d0b986c1176..59a039057f37f 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -12,8 +12,8 @@ trait Trait {} pub fn main() { let x: Vec = Vec::new(); - //~^ ERROR `Trait + Sized: std::marker::Sized` is not satisfied + //~^ ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied //~| ERROR the trait `std::marker::Sized` cannot be made into an object - //~| ERROR `Trait + Sized: std::marker::Sized` is not satisfied + //~| ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied //~| ERROR the trait `std::marker::Sized` cannot be made into an object } diff --git a/src/test/compile-fail/const-unsized.rs b/src/test/compile-fail/const-unsized.rs index 226b567c546e5..23cff4ac6ad6c 100644 --- a/src/test/compile-fail/const-unsized.rs +++ b/src/test/compile-fail/const-unsized.rs @@ -11,8 +11,8 @@ use std::fmt::Debug; const CONST_0: Debug+Sync = *(&0 as &(Debug+Sync)); -//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied -//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static` +//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied +//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn //~| NOTE does not have a constant size known at compile-time //~| NOTE constant expressions must have a statically known size @@ -23,8 +23,8 @@ const CONST_FOO: str = *"foo"; //~| NOTE constant expressions must have a statically known size static STATIC_1: Debug+Sync = *(&1 as &(Debug+Sync)); -//~^ ERROR `std::fmt::Debug + Sync + 'static: std::marker::Sized` is not satisfied -//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + Sync + 'static` +//~^ ERROR `std::fmt::Debug + std::marker::Sync + 'static: std::marker::Sized` is not satisfied +//~| NOTE the trait `std::marker::Sized` is not implemented for `std::fmt::Debug + std::marker::Syn //~| NOTE does not have a constant size known at compile-time //~| NOTE constant expressions must have a statically known size diff --git a/src/test/compile-fail/issue-32963.rs b/src/test/compile-fail/issue-32963.rs index 8ba95d14931e0..14ab0dd5f631c 100644 --- a/src/test/compile-fail/issue-32963.rs +++ b/src/test/compile-fail/issue-32963.rs @@ -16,6 +16,6 @@ fn size_of_copy() -> usize { mem::size_of::() } fn main() { size_of_copy::(); - //~^ ERROR `Misc + Copy: std::marker::Copy` is not satisfied + //~^ ERROR the trait bound `Misc + std::marker::Copy: std::marker::Copy` is not satisfied //~| ERROR the trait `std::marker::Copy` cannot be made into an object } diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs index 1fff812af5b8d..0bfa328751ac1 100644 --- a/src/test/compile-fail/trait-bounds-cant-coerce.rs +++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs @@ -21,10 +21,10 @@ fn c(x: Box) { } fn d(x: Box) { - a(x); //~ ERROR mismatched types - //~| expected type `Box` - //~| found type `Box` - //~| expected bounds `Send`, found no bounds + a(x); //~ ERROR mismatched types [E0308] + //~| NOTE expected type `Box` + //~| NOTE found type `Box` + //~| NOTE expected trait Foo, found a different trait Foo } fn main() { } diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs index fd46d1a62962c..983c66ec1c40f 100644 --- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs +++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs @@ -15,7 +15,7 @@ trait Foo { // This should emit the less confusing error, not the more confusing one. fn foo(_x: Foo + Send) { - //~^ ERROR `Foo + Send + 'static: std::marker::Sized` is not satisfied + //~^ ERROR the trait bound `Foo + std::marker::Send + 'static: std::marker::Sized` is not } fn main() { } From bb35d50cad5f452e80ff88ee957962966c28a9f6 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Wed, 16 Nov 2016 09:21:49 -0700 Subject: [PATCH 4/7] Refactor TyTrait to contain a interned ExistentialPredicate slice. Renames TyTrait to TyDynamic. --- mk/crates.mk | 2 +- src/librustc/infer/freshen.rs | 2 +- src/librustc/traits/coherence.rs | 4 +- src/librustc/traits/error_reporting.rs | 2 +- src/librustc/traits/fulfill.rs | 8 +- src/librustc/traits/mod.rs | 8 +- src/librustc/traits/project.rs | 4 +- src/librustc/traits/select.rs | 144 ++++++------- src/librustc/ty/contents.rs | 2 +- src/librustc/ty/context.rs | 74 +++++-- src/librustc/ty/error.rs | 9 +- src/librustc/ty/fast_reject.rs | 2 +- src/librustc/ty/flags.rs | 19 +- src/librustc/ty/item_path.rs | 2 +- src/librustc/ty/layout.rs | 4 +- src/librustc/ty/mod.rs | 4 +- src/librustc/ty/outlives.rs | 2 +- src/librustc/ty/relate.rs | 54 +++-- src/librustc/ty/structural_impls.rs | 40 ++-- src/librustc/ty/sty.rs | 194 +++++++++++++----- src/librustc/ty/util.rs | 8 +- src/librustc/ty/walk.rs | 21 +- src/librustc/ty/wf.rs | 37 ++-- src/librustc/util/ppaux.rs | 125 +++-------- src/librustc_lint/types.rs | 2 +- src/librustc_metadata/decoder.rs | 9 + src/librustc_trans/base.rs | 8 +- src/librustc_trans/collector.rs | 28 +-- src/librustc_trans/context.rs | 7 +- src/librustc_trans/debuginfo/metadata.rs | 6 +- src/librustc_trans/debuginfo/type_names.rs | 2 +- src/librustc_trans/glue.rs | 4 +- src/librustc_trans/meth.rs | 34 +-- src/librustc_trans/trans_item.rs | 4 +- src/librustc_trans/type_of.rs | 6 +- src/librustc_typeck/astconv.rs | 109 +++++----- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/cast.rs | 7 +- src/librustc_typeck/check/closure.rs | 9 +- src/librustc_typeck/check/dropck.rs | 4 +- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 8 +- src/librustc_typeck/check/method/suggest.rs | 4 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/check/regionck.rs | 5 +- src/librustc_typeck/check/wfcheck.rs | 11 +- src/librustc_typeck/coherence/mod.rs | 4 +- src/librustc_typeck/coherence/orphan.rs | 2 +- src/librustc_typeck/coherence/overlap.rs | 11 +- src/librustc_typeck/collect.rs | 3 +- src/librustc_typeck/diagnostics.rs | 4 +- src/librustc_typeck/variance/constraints.rs | 13 +- src/librustdoc/clean/mod.rs | 27 +-- src/test/compile-fail/E0225.rs | 4 +- src/test/compile-fail/bad-sized.rs | 7 +- src/test/compile-fail/issue-22560.rs | 2 +- src/test/compile-fail/issue-32963.rs | 4 +- .../compile-fail/trait-bounds-cant-coerce.rs | 2 +- src/test/run-pass/auxiliary/issue13507.rs | 2 +- 59 files changed, 614 insertions(+), 515 deletions(-) diff --git a/mk/crates.mk b/mk/crates.mk index 7ae5846c54b99..cf985a0d980b4 100644 --- a/mk/crates.mk +++ b/mk/crates.mk @@ -140,7 +140,7 @@ DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \ DEPS_rustc_incremental := rustc syntax_pos serialize rustc_data_structures DEPS_rustc_save_analysis := rustc log syntax syntax_pos serialize DEPS_rustc_typeck := rustc syntax syntax_pos rustc_platform_intrinsics rustc_const_math \ - rustc_const_eval rustc_errors + rustc_const_eval rustc_errors rustc_data_structures DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts test \ rustc_lint rustc_const_eval syntax_pos rustc_data_structures diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 30e18a4c569b2..19183892e4b0c 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -165,7 +165,7 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::TyRef(..) | ty::TyFnDef(..) | ty::TyFnPtr(_) | - ty::TyTrait(..) | + ty::TyDynamic(..) | ty::TyClosure(..) | ty::TyNever | ty::TyTuple(..) | diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index d4e217fb710cc..58cb52e897786 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -227,7 +227,7 @@ fn fundamental_ty(tcx: TyCtxt, ty: Ty) -> bool { match ty.sty { ty::TyBox(..) | ty::TyRef(..) => true, ty::TyAdt(def, _) => def.is_fundamental(), - ty::TyTrait(ref data) => { + ty::TyDynamic(ref data, ..) => { data.principal().map_or(false, |p| tcx.has_attr(p.def_id(), "fundamental")) } _ => false @@ -270,7 +270,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> krate == Some(LOCAL_CRATE) } - ty::TyTrait(ref tt) => { + ty::TyDynamic(ref tt, ..) => { tt.principal().map_or(false, |p| p.def_id().is_local()) } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 4ac4c31386e71..2e8e45468ddcb 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -156,7 +156,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::TyBox(..) | ty::TyRef(..) | ty::TyRawPtr(..) => Some(5), ty::TyArray(..) | ty::TySlice(..) => Some(6), ty::TyFnDef(..) | ty::TyFnPtr(..) => Some(7), - ty::TyTrait(..) => Some(8), + ty::TyDynamic(..) => Some(8), ty::TyClosure(..) => Some(9), ty::TyTuple(..) => Some(10), ty::TyProjection(..) => Some(11), diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 9ff4048f73e77..23c28037a3c2d 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -231,10 +231,10 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { } pub fn register_bound(&mut self, - infcx: &InferCtxt<'a, 'gcx, 'tcx>, - ty: Ty<'tcx>, - def_id: DefId, - cause: ObligationCause<'tcx>) + infcx: &InferCtxt<'a, 'gcx, 'tcx>, + ty: Ty<'tcx>, + def_id: DefId, + cause: ObligationCause<'tcx>) { let trait_ref = ty::TraitRef { def_id: def_id, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index bdd0ee75eb195..5c5bf130c3ba4 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -366,10 +366,10 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>, /// conservative towards *no impl*, which is the opposite of the /// `evaluate` methods). pub fn type_known_to_meet_bound<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>, - ty: Ty<'tcx>, - def_id: DefId, - span: Span) - -> bool + ty: Ty<'tcx>, + def_id: DefId, + span: Span) +-> bool { debug!("type_known_to_meet_bound(ty={:?}, bound={:?})", ty, diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index 76bead99343a7..27b7adf0ef34a 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -1123,7 +1123,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( debug!("confirm_object_candidate(object_ty={:?})", object_ty); let data = match object_ty.sty { - ty::TyTrait(ref data) => data, + ty::TyDynamic(ref data, ..) => data, _ => { span_bug!( obligation.cause.span, @@ -1131,7 +1131,7 @@ fn confirm_object_candidate<'cx, 'gcx, 'tcx>( object_ty) } }; - let env_predicates = data.projection_bounds.iter().map(|p| { + let env_predicates = data.projection_bounds().map(|p| { p.with_self_ty(selcx.tcx(), object_ty).to_predicate() }).collect(); let env_predicate = { diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 11b23d699de2f..a23b021cd4f4a 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -50,7 +50,6 @@ use std::fmt; use std::marker::PhantomData; use std::mem; use std::rc::Rc; -use std::iter; use syntax::abi::Abi; use hir; use util::nodemap::FxHashMap; @@ -1094,38 +1093,30 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // and applicable impls. There is a certain set of precedence rules here. let def_id = obligation.predicate.def_id(); - match obligation.predicate.def_id() { - _ if self.tcx().lang_items.copy_trait() == Some(def_id) => { - debug!("obligation self ty is {:?}", - obligation.predicate.0.self_ty()); - - // User-defined copy impls are permitted, but only for - // structs and enums. - self.assemble_candidates_from_impls(obligation, &mut candidates)?; - - // For other types, we'll use the builtin rules. - let copy_conditions = self.copy_conditions(obligation); - self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?; - } - _ if self.tcx().lang_items.sized_trait() == Some(def_id) => { - // Sized is never implementable by end-users, it is - // always automatically computed. - let sized_conditions = self.sized_conditions(obligation); - self.assemble_builtin_bound_candidates(sized_conditions, - &mut candidates)?; - } - - _ if self.tcx().lang_items.unsize_trait() == Some(def_id) => { - self.assemble_candidates_for_unsizing(obligation, &mut candidates); - } - - // For non-builtins and Send/Sync - _ => { - self.assemble_closure_candidates(obligation, &mut candidates)?; - self.assemble_fn_pointer_candidates(obligation, &mut candidates)?; - self.assemble_candidates_from_impls(obligation, &mut candidates)?; - self.assemble_candidates_from_object_ty(obligation, &mut candidates); - } + if self.tcx().lang_items.copy_trait() == Some(def_id) { + debug!("obligation self ty is {:?}", + obligation.predicate.0.self_ty()); + + // User-defined copy impls are permitted, but only for + // structs and enums. + self.assemble_candidates_from_impls(obligation, &mut candidates)?; + + // For other types, we'll use the builtin rules. + let copy_conditions = self.copy_conditions(obligation); + self.assemble_builtin_bound_candidates(copy_conditions, &mut candidates)?; + } else if self.tcx().lang_items.sized_trait() == Some(def_id) { + // Sized is never implementable by end-users, it is + // always automatically computed. + let sized_conditions = self.sized_conditions(obligation); + self.assemble_builtin_bound_candidates(sized_conditions, + &mut candidates)?; + } else if self.tcx().lang_items.unsize_trait() == Some(def_id) { + self.assemble_candidates_for_unsizing(obligation, &mut candidates); + } else { + self.assemble_closure_candidates(obligation, &mut candidates)?; + self.assemble_fn_pointer_candidates(obligation, &mut candidates)?; + self.assemble_candidates_from_impls(obligation, &mut candidates)?; + self.assemble_candidates_from_object_ty(obligation, &mut candidates); } self.assemble_candidates_from_projected_tys(obligation, &mut candidates); @@ -1446,7 +1437,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { if self.tcx().trait_has_default_impl(def_id) { match self_ty.sty { - ty::TyTrait(..) => { + ty::TyDynamic(..) => { // For object types, we don't know what the closed // over types are. For most traits, this means we // conservatively say nothing; a candidate may be @@ -1516,7 +1507,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // any LBR. let self_ty = this.tcx().erase_late_bound_regions(&obligation.self_ty()); let poly_trait_ref = match self_ty.sty { - ty::TyTrait(ref data) => { + ty::TyDynamic(ref data, ..) => { if data.auto_traits().any(|did| did == obligation.predicate.def_id()) { debug!("assemble_candidates_from_object_ty: matched builtin bound, \ pushing candidate"); @@ -1525,7 +1516,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } match data.principal() { - Some(ref p) => p.with_self_ty(this.tcx(), self_ty), + Some(p) => p.with_self_ty(this.tcx(), self_ty), None => return, } } @@ -1598,7 +1589,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let may_apply = match (&source.sty, &target.sty) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). - (&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => { + (&ty::TyDynamic(ref data_a, ..), &ty::TyDynamic(ref data_b, ..)) => { // Upcasts permit two things: // // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo` @@ -1611,7 +1602,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // We always upcast when we can because of reason // #2 (region bounds). match (data_a.principal(), data_b.principal()) { - (Some(ref a), Some(ref b)) => a.def_id() == b.def_id() && + (Some(a), Some(b)) => a.def_id() == b.def_id() && data_b.auto_traits() // All of a's auto traits need to be in b's auto traits. .all(|b| data_a.auto_traits().any(|a| a == b)), @@ -1620,7 +1611,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } // T -> Trait. - (_, &ty::TyTrait(_)) => true, + (_, &ty::TyDynamic(..)) => true, // Ambiguous handling is below T -> Trait, because inference // variables can still implement Unsize and nested @@ -1772,7 +1763,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Where(ty::Binder(Vec::new())) } - ty::TyStr | ty::TySlice(_) | ty::TyTrait(..) => Never, + ty::TyStr | ty::TySlice(_) | ty::TyDynamic(..) => Never, ty::TyTuple(tys) => { Where(ty::Binder(tys.last().into_iter().cloned().collect())) @@ -1818,7 +1809,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Where(ty::Binder(Vec::new())) } - ty::TyBox(_) | ty::TyTrait(..) | ty::TyStr | ty::TySlice(..) | + ty::TyBox(_) | ty::TyDynamic(..) | ty::TyStr | ty::TySlice(..) | ty::TyClosure(..) | ty::TyRef(_, ty::TypeAndMut { ty: _, mutbl: hir::MutMutable }) => { Never @@ -1883,7 +1874,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Vec::new() } - ty::TyTrait(..) | + ty::TyDynamic(..) | ty::TyParam(..) | ty::TyProjection(..) | ty::TyAnon(..) | @@ -2169,11 +2160,11 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // OK to skip binder, it is reintroduced below let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty()); match self_ty.sty { - ty::TyTrait(ref data) => { + ty::TyDynamic(ref data, ..) => { // OK to skip the binder, it is reintroduced below let principal = data.principal().unwrap(); let input_types = principal.input_types(); - let assoc_types = data.projection_bounds.iter() + let assoc_types = data.projection_bounds() .map(|pb| pb.skip_binder().ty); let all_types: Vec<_> = input_types.chain(assoc_types) .collect(); @@ -2305,7 +2296,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // case that results. -nmatsakis let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder()); let poly_trait_ref = match self_ty.sty { - ty::TyTrait(ref data) => { + ty::TyDynamic(ref data, ..) => { data.principal().unwrap().with_self_ty(self.tcx(), self_ty) } _ => { @@ -2474,14 +2465,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let mut nested = vec![]; match (&source.sty, &target.sty) { // Trait+Kx+'a -> Trait+Ky+'b (upcasts). - (&ty::TyTrait(ref data_a), &ty::TyTrait(ref data_b)) => { + (&ty::TyDynamic(ref data_a, r_a), &ty::TyDynamic(ref data_b, r_b)) => { // See assemble_candidates_for_unsizing for more info. - let new_trait = tcx.mk_trait(ty::TraitObject::new( - data_a.principal(), - data_b.region_bound, - data_b.auto_traits().collect(), - data_a.projection_bounds.clone(), - )); + // Binders reintroduced below in call to mk_existential_predicates. + let principal = data_a.skip_binder().principal(); + let iter = principal.into_iter().map(ty::ExistentialPredicate::Trait) + .chain(data_a.skip_binder().projection_bounds() + .map(|x| ty::ExistentialPredicate::Projection(x))) + .chain(data_b.auto_traits().map(ty::ExistentialPredicate::AutoTrait)); + let new_trait = tcx.mk_dynamic( + ty::Binder(tcx.mk_existential_predicates(iter)), r_b); let InferOk { obligations, .. } = self.infcx.sub_types(false, &obligation.cause, new_trait, target) .map_err(|_| Unimplemented)?; @@ -2491,17 +2484,16 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { let cause = ObligationCause::new(obligation.cause.span, obligation.cause.body_id, ObjectCastObligation(target)); - let outlives = ty::OutlivesPredicate(data_a.region_bound, - data_b.region_bound); + let outlives = ty::OutlivesPredicate(r_a, r_b); nested.push(Obligation::with_depth(cause, obligation.recursion_depth + 1, ty::Binder(outlives).to_predicate())); } // T -> Trait. - (_, &ty::TyTrait(ref data)) => { + (_, &ty::TyDynamic(ref data, r)) => { let mut object_dids = - data.auto_traits().chain(data.principal().map(|ref p| p.def_id())); + data.auto_traits().chain(data.principal().map(|p| p.def_id())); if let Some(did) = object_dids.find(|did| { !tcx.is_object_safe(*did) }) { @@ -2517,35 +2509,27 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { predicate)); }; - // Create the obligation for casting from T to Trait. - push(data.principal().unwrap().with_self_ty(tcx, source).to_predicate()); - - // We can only make objects from sized types. - let trait_refs = data.auto_traits() - .chain(iter::once( - tcx.lang_items.require(lang_items::SizedTraitLangItem) - .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])))) - .map(|did| ty::TraitRef { - def_id: did, - substs: tcx.mk_substs_trait(source, &[]), - }); - - // Create additional obligations for all the various builtin - // bounds attached to the object cast. (In other words, if the - // object type is Foo+Send, this would create an obligation - // for the Send check.) - for tr in trait_refs { - push(tr.to_predicate()); + // Create obligations: + // - Casting T to Trait + // - For all the various builtin bounds attached to the object cast. (In other + // words, if the object type is Foo+Send, this would create an obligation for the + // Send check.) + // - Projection predicates + for predicate in data.iter() { + push(predicate.with_self_ty(tcx, source)); } - // Create obligations for the projection predicates. - for bound in &data.projection_bounds { - push(bound.with_self_ty(tcx, source).to_predicate()); - } + // We can only make objects from sized types. + let tr = ty::TraitRef { + def_id: tcx.lang_items.require(lang_items::SizedTraitLangItem) + .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])), + substs: tcx.mk_substs_trait(source, &[]), + }; + push(tr.to_predicate()); // If the type is `Foo+'a`, ensures that the type // being cast to `Foo+'a` outlives `'a`: - let outlives = ty::OutlivesPredicate(source, data.region_bound); + let outlives = ty::OutlivesPredicate(source, r); push(ty::Binder(outlives).to_predicate()); } diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs index 9f80c2487fb2c..8c3cb79294880 100644 --- a/src/librustc/ty/contents.rs +++ b/src/librustc/ty/contents.rs @@ -195,7 +195,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { tc_ty(tcx, typ, cache).owned_pointer() } - ty::TyTrait(_) => { + ty::TyDynamic(..) => { TC::All - TC::InteriorParam } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index ea81c85ba6a53..c23ee489a28f4 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -29,7 +29,7 @@ use ty::{self, TraitRef, Ty, TypeAndMut}; use ty::{TyS, TypeVariants, Slice}; use ty::{AdtKind, AdtDef, ClosureSubsts, Region}; use hir::FreevarMap; -use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, TraitObject}; +use ty::{BareFnTy, InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; use ty::TypeVariants::*; use ty::layout::{Layout, TargetDataLayout}; @@ -47,6 +47,7 @@ use std::mem; use std::ops::Deref; use std::rc::Rc; use std::iter; +use std::cmp::Ordering; use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::symbol::{Symbol, keywords}; @@ -63,6 +64,7 @@ pub struct CtxtArenas<'tcx> { region: TypedArena, stability: TypedArena, layout: TypedArena, + existential_predicates: TypedArena>, // references generics: TypedArena>, @@ -81,6 +83,7 @@ impl<'tcx> CtxtArenas<'tcx> { region: TypedArena::new(), stability: TypedArena::new(), layout: TypedArena::new(), + existential_predicates: TypedArena::new(), generics: TypedArena::new(), trait_def: TypedArena::new(), @@ -103,6 +106,7 @@ pub struct CtxtInterners<'tcx> { region: RefCell>>, stability: RefCell>, layout: RefCell>, + existential_predicates: RefCell>>>>, } impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { @@ -115,7 +119,8 @@ impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { bare_fn: RefCell::new(FxHashSet()), region: RefCell::new(FxHashSet()), stability: RefCell::new(FxHashSet()), - layout: RefCell::new(FxHashSet()) + layout: RefCell::new(FxHashSet()), + existential_predicates: RefCell::new(FxHashSet()), } } @@ -958,6 +963,27 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { } } +impl<'a, 'tcx> Lift<'tcx> for &'a Slice> { + type Lifted = &'tcx Slice>; + fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) + -> Option<&'tcx Slice>> { + if self.is_empty() { + return Some(Slice::empty()); + } + if let Some(&Interned(eps)) = tcx.interners.existential_predicates.borrow().get(&self[..]) { + if *self as *const _ == eps as *const _ { + return Some(eps); + } + } + // Also try in the global tcx if we're not that. + if !tcx.is_global() { + self.lift_to_tcx(tcx.global_tcx()) + } else { + None + } + } +} + impl<'a, 'tcx> Lift<'tcx> for &'a BareFnTy<'a> { type Lifted = &'tcx BareFnTy<'tcx>; fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) @@ -1126,7 +1152,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { sty_debug_print!( self, TyAdt, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, - TyTrait, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon); + TyDynamic, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon); println!("Substs interner: #{}", self.interners.substs.borrow().len()); println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len()); @@ -1200,6 +1226,13 @@ impl<'tcx> Borrow for Interned<'tcx, Region> { } } +impl<'tcx: 'lcx, 'lcx> Borrow<[ExistentialPredicate<'lcx>]> + for Interned<'tcx, Slice>> { + fn borrow<'a>(&'a self) -> &'a [ExistentialPredicate<'lcx>] { + &self.0[..] + } +} + macro_rules! intern_method { ($lt_tcx:tt, $name:ident: $method:ident($alloc:ty, $alloc_method:ident, @@ -1297,6 +1330,7 @@ macro_rules! slice_interners { } slice_interners!( + existential_predicates: _intern_existential_predicates(ExistentialPredicate), type_list: _intern_type_list(Ty), substs: _intern_substs(Kind) ); @@ -1437,24 +1471,27 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(TyFnPtr(fty)) } - pub fn mk_trait(self, mut obj: TraitObject<'tcx>) -> Ty<'tcx> { - obj.projection_bounds.sort_by_key(|b| b.sort_key(self)); - self.mk_ty(TyTrait(box obj)) + pub fn mk_dynamic( + self, + obj: ty::Binder<&'tcx Slice>>, + reg: &'tcx ty::Region + ) -> Ty<'tcx> { + self.mk_ty(TyDynamic(obj, reg)) } pub fn mk_projection(self, trait_ref: TraitRef<'tcx>, item_name: Name) - -> Ty<'tcx> { - // take a copy of substs so that we own the vectors inside - let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name }; - self.mk_ty(TyProjection(inner)) - } + -> Ty<'tcx> { + // take a copy of substs so that we own the vectors inside + let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name }; + self.mk_ty(TyProjection(inner)) + } pub fn mk_closure(self, closure_id: DefId, substs: &'tcx Substs<'tcx>) - -> Ty<'tcx> { + -> Ty<'tcx> { self.mk_closure_from_closure_substs(closure_id, ClosureSubsts { substs: substs }) @@ -1501,6 +1538,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_ty(TyAnon(def_id, substs)) } + pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>]) + -> &'tcx Slice> { + assert!(!eps.is_empty()); + assert!(eps.windows(2).all(|w| w[0].cmp(self, &w[1]) != Ordering::Greater)); + self._intern_existential_predicates(eps) + } + pub fn intern_type_list(self, ts: &[Ty<'tcx>]) -> &'tcx Slice> { if ts.len() == 0 { Slice::empty() @@ -1517,6 +1561,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } + pub fn mk_existential_predicates], + &'tcx Slice>>>(self, iter: I) + -> I::Output { + iter.intern_with(|xs| self.intern_existential_predicates(xs)) + } + pub fn mk_type_list], &'tcx Slice>>>(self, iter: I) -> I::Output { iter.intern_with(|xs| self.intern_type_list(xs)) diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 8ef13e62901a6..125ee0a02c814 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -49,7 +49,8 @@ pub enum TypeError<'tcx> { CyclicTy, ProjectionNameMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), - TyParamDefaultMismatch(ExpectedFound>) + TyParamDefaultMismatch(ExpectedFound>), + ExistentialMismatch(ExpectedFound<&'tcx ty::Slice>>), } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] @@ -164,6 +165,10 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { values.expected.ty, values.found.ty) } + ExistentialMismatch(ref values) => { + report_maybe_different(f, format!("trait `{}`", values.expected), + format!("trait `{}`", values.found)) + } } } } @@ -200,7 +205,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { } ty::TyFnDef(..) => format!("fn item"), ty::TyFnPtr(_) => "fn pointer".to_string(), - ty::TyTrait(ref inner) => { + ty::TyDynamic(ref inner, ..) => { inner.principal().map_or_else(|| "trait".to_string(), |p| format!("trait {}", tcx.item_path_str(p.def_id()))) } diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 3eab06dc674bf..9791ccb101380 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -59,7 +59,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyStr => Some(StrSimplifiedType), ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType), ty::TyRawPtr(_) => Some(PtrSimplifiedType), - ty::TyTrait(ref trait_info) => { + ty::TyDynamic(ref trait_info, ..) => { trait_info.principal().map(|p| TraitSimplifiedType(p.def_id())) } ty::TyRef(_, mt) => { diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 026bf64533c88..2bcbccb7d0505 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -121,16 +121,21 @@ impl FlagComputation { self.add_substs(substs); } - &ty::TyTrait(ref obj) => { + &ty::TyDynamic(ref obj, r) => { let mut computation = FlagComputation::new(); - computation.add_substs(obj.principal().unwrap().skip_binder().substs); - for projection_bound in &obj.projection_bounds { - let mut proj_computation = FlagComputation::new(); - proj_computation.add_existential_projection(&projection_bound.0); - self.add_bound_computation(&proj_computation); + for predicate in obj.skip_binder().iter() { + match *predicate { + ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs), + ty::ExistentialPredicate::Projection(p) => { + let mut proj_computation = FlagComputation::new(); + proj_computation.add_existential_projection(&p); + self.add_bound_computation(&proj_computation); + } + ty::ExistentialPredicate::AutoTrait(_) => {} + } } self.add_bound_computation(&computation); - self.add_region(obj.region_bound); + self.add_region(r); } &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => { diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index d1e6f5b8cd12e..440a3916786fa 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -316,7 +316,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option { match ty.sty { ty::TyAdt(adt_def, _) => Some(adt_def.did), - ty::TyTrait(ref data) => data.principal().map(|ref p| p.def_id()), + ty::TyDynamic(data, ..) => data.principal().map(|p| p.def_id()), ty::TyArray(subty, _) | ty::TySlice(subty) | diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index bc3c5d6ed4e20..8646bccf1e9ed 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -924,7 +924,7 @@ impl<'a, 'gcx, 'tcx> Layout { ty::TySlice(_) | ty::TyStr => { Int(dl.ptr_sized_integer()) } - ty::TyTrait(_) => Pointer, + ty::TyDynamic(..) => Pointer, _ => return Err(LayoutError::Unknown(unsized_part)) }; FatPointer { metadata: meta, non_zero: non_zero } @@ -963,7 +963,7 @@ impl<'a, 'gcx, 'tcx> Layout { non_zero: false } } - ty::TyTrait(_) => { + ty::TyDynamic(..) => { let mut unit = Struct::new(dl, false); unit.sized = false; Univariant { variant: unit, non_zero: false } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 4544cda0ae9ae..86fe14ea504b6 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -54,7 +54,7 @@ use hir::itemlikevisit::ItemLikeVisitor; pub use self::sty::{Binder, DebruijnIndex}; pub use self::sty::{BareFnTy, FnSig, PolyFnSig}; -pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitObject}; +pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, ExistentialPredicate}; pub use self::sty::{ClosureSubsts, TypeAndMut}; pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef}; pub use self::sty::{ExistentialTraitRef, PolyExistentialTraitRef}; @@ -1712,7 +1712,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> { vec![] } - TyStr | TyTrait(..) | TySlice(_) | TyError => { + TyStr | TyDynamic(..) | TySlice(_) | TyError => { // these are never sized - return the target type vec![ty] } diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index e3d13f593954f..eb384eec6a6f1 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -177,7 +177,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ty::TyTuple(..) | // ... ty::TyFnDef(..) | // OutlivesFunction (*) ty::TyFnPtr(_) | // OutlivesFunction (*) - ty::TyTrait(..) | // OutlivesObject, OutlivesFragment (*) + ty::TyDynamic(..) | // OutlivesObject, OutlivesFragment (*) ty::TyError => { // (*) Bare functions and traits are both binders. In the // RFC, this means we would add the bound regions to the diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 02704e94fee98..8cb1483107ff1 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -398,26 +398,15 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_adt(a_def, substs)) } - (&ty::TyTrait(ref a_obj), &ty::TyTrait(ref b_obj)) => - { - let principal = match (a_obj.principal(), b_obj.principal()) { - (Some(ref a_p), Some(ref b_p)) => Some(relation.relate(a_p, b_p)?), - (None, None) => None, - _ => return Err(TypeError::Sorts(expected_found(relation, &a, &b))), - }; - let r = - relation.with_cause( - Cause::ExistentialRegionBound, - |relation| relation.relate_with_variance(ty::Contravariant, - &a_obj.region_bound, - &b_obj.region_bound))?; - let nb = if !a_obj.auto_traits().eq(b_obj.auto_traits()) { - return Err(TypeError::Sorts(expected_found(relation, &a, &b))); - } else { - a_obj.auto_traits().collect() - }; - let pb = relation.relate(&a_obj.projection_bounds, &b_obj.projection_bounds)?; - Ok(tcx.mk_trait(ty::TraitObject::new(principal, r, nb, pb))) + (&ty::TyDynamic(ref a_obj, ref a_region), &ty::TyDynamic(ref b_obj, ref b_region)) => { + let region_bound = relation.with_cause(Cause::ExistentialRegionBound, + |relation| { + relation.relate_with_variance( + ty::Contravariant, + a_region, + b_region) + })?; + Ok(tcx.mk_dynamic(relation.relate(a_obj, b_obj)?, region_bound)) } (&ty::TyClosure(a_id, a_substs), @@ -513,6 +502,31 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, } } +impl<'tcx> Relate<'tcx> for &'tcx ty::Slice> { + fn relate<'a, 'gcx, R>(relation: &mut R, + a: &Self, + b: &Self) + -> RelateResult<'tcx, Self> + where R: TypeRelation<'a, 'gcx, 'tcx>, 'gcx: 'a+'tcx, 'tcx: 'a { + + if a.len() != b.len() { + return Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))); + } + + let tcx = relation.tcx(); + let v = a.iter().zip(b.iter()).map(|(ep_a, ep_b)| { + use ty::ExistentialPredicate::*; + match (*ep_a, *ep_b) { + (Trait(ref a), Trait(ref b)) => Ok(Trait(relation.relate(a, b)?)), + (Projection(ref a), Projection(ref b)) => Ok(Projection(relation.relate(a, b)?)), + (AutoTrait(ref a), AutoTrait(ref b)) if a == b => Ok(AutoTrait(*a)), + _ => Err(TypeError::ExistentialMismatch(expected_found(relation, a, b))) + } + }); + Ok(tcx.mk_existential_predicates(v)?) + } +} + impl<'tcx> Relate<'tcx> for ty::ClosureSubsts<'tcx> { fn relate<'a, 'gcx, R>(relation: &mut R, a: &ty::ClosureSubsts<'tcx>, diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index e890d750a7b50..88de3575274cc 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -324,6 +324,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { TyParamDefaultMismatch(ref x) => { return tcx.lift(x).map(TyParamDefaultMismatch) } + ExistentialMismatch(ref x) => return tcx.lift(x).map(ExistentialMismatch) }) } } @@ -426,20 +427,33 @@ impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder { } } -impl<'tcx> TypeFoldable<'tcx> for ty::TraitObject<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::Slice> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::TraitObject::new( - self.principal().map(|p| p.fold_with(folder)), - self.region_bound.fold_with(folder), - self.auto_traits().collect(), - self.projection_bounds.fold_with(folder), - ) + let v = self.iter().map(|p| p.fold_with(folder)).collect::>(); + folder.tcx().intern_existential_predicates(&v) } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.principal().map(|p| p.visit_with(visitor)).unwrap_or(true) || - self.region_bound.visit_with(visitor) || - self.projection_bounds.visit_with(visitor) + self.iter().any(|p| p.visit_with(visitor)) + } +} + +impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialPredicate<'tcx> { + fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { + use ty::ExistentialPredicate::*; + match *self { + Trait(ref tr) => Trait(tr.fold_with(folder)), + Projection(ref p) => Projection(p.fold_with(folder)), + AutoTrait(did) => AutoTrait(did), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + match *self { + ty::ExistentialPredicate::Trait(ref tr) => tr.visit_with(visitor), + ty::ExistentialPredicate::Projection(ref p) => p.visit_with(visitor), + ty::ExistentialPredicate::AutoTrait(_) => false, + } } } @@ -462,7 +476,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyArray(typ, sz) => ty::TyArray(typ.fold_with(folder), sz), ty::TySlice(typ) => ty::TySlice(typ.fold_with(folder)), ty::TyAdt(tid, substs) => ty::TyAdt(tid, substs.fold_with(folder)), - ty::TyTrait(ref trait_ty) => ty::TyTrait(trait_ty.fold_with(folder)), + ty::TyDynamic(ref trait_ty, ref region) => + ty::TyDynamic(trait_ty.fold_with(folder), region.fold_with(folder)), ty::TyTuple(ts) => ty::TyTuple(ts.fold_with(folder)), ty::TyFnDef(def_id, substs, f) => { ty::TyFnDef(def_id, @@ -499,7 +514,8 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyArray(typ, _sz) => typ.visit_with(visitor), ty::TySlice(typ) => typ.visit_with(visitor), ty::TyAdt(_, substs) => substs.visit_with(visitor), - ty::TyTrait(ref trait_ty) => trait_ty.visit_with(visitor), + ty::TyDynamic(ref trait_ty, ref reg) => + trait_ty.visit_with(visitor) || reg.visit_with(visitor), ty::TyTuple(ts) => ts.visit_with(visitor), ty::TyFnDef(_, substs, ref f) => { substs.visit_with(visitor) || f.visit_with(visitor) diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index e6411ca1e4f68..667db5b673054 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -16,8 +16,11 @@ use middle::region; use ty::subst::Substs; use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable}; use ty::{Slice, TyS}; +use ty::subst::Kind; use std::fmt; +use std::iter; +use std::cmp::Ordering; use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::symbol::{keywords, InternedString}; @@ -144,7 +147,7 @@ pub enum TypeVariants<'tcx> { TyFnPtr(&'tcx BareFnTy<'tcx>), /// A trait, defined with `trait`. - TyTrait(Box>), + TyDynamic(Binder<&'tcx Slice>>, &'tcx ty::Region), /// The anonymous type of a closure. Used to represent the type of /// `|a| a`. @@ -272,32 +275,103 @@ impl<'a, 'gcx, 'acx, 'tcx> ClosureSubsts<'tcx> { } } -#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] -pub struct TraitObject<'tcx> { - principal: Option>, - pub region_bound: &'tcx ty::Region, - auto_traits: Vec, - pub projection_bounds: Vec>, +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)] +pub enum ExistentialPredicate<'tcx> { + // e.g. Iterator + Trait(ExistentialTraitRef<'tcx>), + // e.g. Iterator::Item = T + Projection(ExistentialProjection<'tcx>), + // e.g. Send + AutoTrait(DefId), } -impl<'tcx> TraitObject<'tcx> { - pub fn new(principal: Option>, region_bound: &'tcx ty::Region, - auto_traits: Vec, projection_bounds: Vec>) - -> Self { - TraitObject { - principal: principal, - region_bound: region_bound, - auto_traits: auto_traits, - projection_bounds: projection_bounds, +impl<'a, 'gcx, 'tcx> ExistentialPredicate<'tcx> { + pub fn cmp(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, other: &Self) -> Ordering { + use self::ExistentialPredicate::*; + match (*self, *other) { + (Trait(_), Trait(_)) => Ordering::Equal, + (Projection(ref a), Projection(ref b)) => a.sort_key(tcx).cmp(&b.sort_key(tcx)), + (AutoTrait(ref a), AutoTrait(ref b)) => + tcx.lookup_trait_def(*a).def_path_hash.cmp(&tcx.lookup_trait_def(*b).def_path_hash), + (Trait(_), _) => Ordering::Less, + (Projection(_), Trait(_)) => Ordering::Greater, + (Projection(_), _) => Ordering::Less, + (AutoTrait(_), _) => Ordering::Greater, + } + } + +} + +impl<'a, 'gcx, 'tcx> Binder> { + pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) + -> ty::Predicate<'tcx> { + use ty::ToPredicate; + match *self.skip_binder() { + ExistentialPredicate::Trait(tr) => Binder(tr).with_self_ty(tcx, self_ty).to_predicate(), + ExistentialPredicate::Projection(p) => + ty::Predicate::Projection(Binder(p.with_self_ty(tcx, self_ty))), + ExistentialPredicate::AutoTrait(did) => { + let trait_ref = Binder(ty::TraitRef { + def_id: did, + substs: tcx.mk_substs_trait(self_ty, &[]), + }); + trait_ref.to_predicate() + } + } + } +} + +impl<'tcx> serialize::UseSpecializedDecodable for &'tcx Slice> {} + +impl<'tcx> Slice> { + pub fn principal(&self) -> Option> { + match self.get(0) { + Some(&ExistentialPredicate::Trait(tr)) => Some(tr), + _ => None } } + #[inline] + pub fn projection_bounds<'a>(&'a self) -> + impl Iterator> + 'a { + self.iter().filter_map(|predicate| { + match *predicate { + ExistentialPredicate::Projection(p) => Some(p), + _ => None, + } + }) + } + + #[inline] + pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { + self.iter().filter_map(|predicate| { + match *predicate { + ExistentialPredicate::AutoTrait(d) => Some(d), + _ => None + } + }) + } +} + +impl<'tcx> Binder<&'tcx Slice>> { pub fn principal(&self) -> Option> { - self.principal + self.skip_binder().principal().map(Binder) + } + + #[inline] + pub fn projection_bounds<'a>(&'a self) -> + impl Iterator> + 'a { + self.skip_binder().projection_bounds().map(Binder) } + #[inline] pub fn auto_traits<'a>(&'a self) -> impl Iterator + 'a { - self.auto_traits.iter().cloned() + self.skip_binder().auto_traits() + } + + pub fn iter<'a>(&'a self) + -> impl DoubleEndedIterator>> + 'tcx { + self.skip_binder().iter().cloned().map(Binder) } } @@ -362,14 +436,30 @@ pub struct ExistentialTraitRef<'tcx> { pub substs: &'tcx Substs<'tcx>, } -impl<'tcx> ExistentialTraitRef<'tcx> { - pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator> + 'a { +impl<'a, 'gcx, 'tcx> ExistentialTraitRef<'tcx> { + pub fn input_types<'b>(&'b self) -> impl DoubleEndedIterator> + 'b { // Select only the "input types" from a trait-reference. For // now this is all the types that appear in the // trait-reference, but it should eventually exclude // associated types. self.substs.types() } + + /// Object types don't have a self-type specified. Therefore, when + /// we convert the principal trait-ref into a normal trait-ref, + /// you must give *some* self-type. A common choice is `mk_err()` + /// or some skolemized type. + pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) + -> ty::TraitRef<'tcx> { + // otherwise the escaping regions would be captured by the binder + assert!(!self_ty.has_escaping_regions()); + + ty::TraitRef { + def_id: self.def_id, + substs: tcx.mk_substs( + iter::once(Kind::from(self_ty)).chain(self.substs.iter().cloned())) + } + } } pub type PolyExistentialTraitRef<'tcx> = Binder>; @@ -731,61 +821,53 @@ pub struct ExistentialProjection<'tcx> { pub type PolyExistentialProjection<'tcx> = Binder>; -impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { +impl<'a, 'tcx, 'gcx> ExistentialProjection<'tcx> { pub fn item_name(&self) -> Name { - self.0.item_name // safe to skip the binder to access a name + self.item_name // safe to skip the binder to access a name } pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) { // We want something here that is stable across crate boundaries. // The DefId isn't but the `deterministic_hash` of the corresponding // DefPath is. - let trait_def = tcx.lookup_trait_def(self.0.trait_ref.def_id); + let trait_def = tcx.lookup_trait_def(self.trait_ref.def_id); let def_path_hash = trait_def.def_path_hash; // An `ast::Name` is also not stable (it's just an index into an // interning table), so map to the corresponding `InternedString`. - let item_name = self.0.item_name.as_str(); + let item_name = self.item_name.as_str(); (def_path_hash, item_name) } pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) - -> ty::PolyProjectionPredicate<'tcx> + -> ty::ProjectionPredicate<'tcx> { // otherwise the escaping regions would be captured by the binders assert!(!self_ty.has_escaping_regions()); - let trait_ref = self.map_bound(|proj| proj.trait_ref); - self.map_bound(|proj| ty::ProjectionPredicate { + ty::ProjectionPredicate { projection_ty: ty::ProjectionTy { - trait_ref: trait_ref.with_self_ty(tcx, self_ty).0, - item_name: proj.item_name + trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), + item_name: self.item_name }, - ty: proj.ty - }) + ty: self.ty + } } } -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn try_add_builtin_trait(self, - id: DefId, - auto_traits: &mut Vec) - -> bool - { - //! Checks whether `id` refers to one of the builtin - //! traits, like `Send`, and adds it to `auto_traits` if so. - //! Returns true if `idf` refers to a builtin trait. - - if Some(id) == self.lang_items.send_trait() || - Some(id) == self.lang_items.sized_trait() || - Some(id) == self.lang_items.copy_trait() || - Some(id) == self.lang_items.sync_trait() { - auto_traits.push(id); - true - } else { - false - } +impl<'a, 'tcx, 'gcx> PolyExistentialProjection<'tcx> { + pub fn item_name(&self) -> Name { + self.skip_binder().item_name() + } + + pub fn sort_key(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> (u64, InternedString) { + self.skip_binder().sort_key(tcx) + } + + pub fn with_self_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, self_ty: Ty<'tcx>) + -> ty::PolyProjectionPredicate<'tcx> { + self.map_bound(|p| p.with_self_ty(tcx, self_ty)) } } @@ -1045,7 +1127,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn is_trait(&self) -> bool { match self.sty { - TyTrait(..) => true, + TyDynamic(..) => true, _ => false } } @@ -1178,7 +1260,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { pub fn ty_to_def_id(&self) -> Option { match self.sty { - TyTrait(ref tt) => tt.principal().map(|p| p.def_id()), + TyDynamic(ref tt, ..) => tt.principal().map(|p| p.def_id()), TyAdt(def, _) => Some(def.did), TyClosure(id, _) => Some(id), _ => None @@ -1200,9 +1282,11 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { TyRef(region, _) => { vec![region] } - TyTrait(ref obj) => { - let mut v = vec![obj.region_bound]; - v.extend(obj.principal().unwrap().skip_binder().substs.regions()); + TyDynamic(ref obj, region) => { + let mut v = vec![region]; + if let Some(p) = obj.principal() { + v.extend(p.skip_binder().substs.regions()); + } v } TyAdt(_, substs) | TyAnon(_, substs) => { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 350426e7f3e82..ed9a327750a16 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -532,8 +532,8 @@ impl<'a, 'gcx, 'tcx, H: Hasher> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tc self.hash(f.sig.variadic()); self.hash(f.sig.inputs().skip_binder().len()); } - TyTrait(ref data) => { - if let Some(ref p) = data.principal() { + TyDynamic(ref data, ..) => { + if let Some(p) = data.principal() { self.def_id(p.def_id()); } for d in data.auto_traits() { @@ -641,7 +641,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { mutbl: hir::MutMutable, .. }) => Some(true), - TyArray(..) | TySlice(..) | TyTrait(..) | TyTuple(..) | + TyArray(..) | TySlice(..) | TyDynamic(..) | TyTuple(..) | TyClosure(..) | TyAdt(..) | TyAnon(..) | TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None }.unwrap_or_else(|| { @@ -684,7 +684,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { TyBox(..) | TyRawPtr(..) | TyRef(..) | TyFnDef(..) | TyFnPtr(_) | TyArray(..) | TyTuple(..) | TyClosure(..) | TyNever => Some(true), - TyStr | TyTrait(..) | TySlice(_) => Some(false), + TyStr | TyDynamic(..) | TySlice(_) => Some(false), TyAdt(..) | TyProjection(..) | TyParam(..) | TyInfer(..) | TyAnon(..) | TyError => None diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index 02f55c6e34082..0848dcd2c8d21 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -92,14 +92,19 @@ fn push_subtypes<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent_ty: Ty<'tcx>) { ty::TyProjection(ref data) => { stack.extend(data.trait_ref.substs.types().rev()); } - ty::TyTrait(ref obj) => { - match obj.principal() { - Some(ref p) => stack.extend(p.input_types().rev()), - None => {} - } - stack.extend(obj.projection_bounds.iter().map(|pred| { - pred.0.ty - }).rev()); + ty::TyDynamic(ref obj, ..) => { + stack.extend(obj.iter().rev().flat_map(|predicate| { + let (substs, opt_ty) = match *predicate.skip_binder() { + ty::ExistentialPredicate::Trait(tr) => (tr.substs, None), + ty::ExistentialPredicate::Projection(p) => + (p.trait_ref.substs, Some(p.ty)), + ty::ExistentialPredicate::AutoTrait(_) => + // Empty iterator + (ty::Substs::empty(), None), + }; + + substs.types().rev().chain(opt_ty) + })); } ty::TyAdt(_, substs) | ty::TyAnon(_, substs) => { stack.extend(substs.types().rev()); diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index d0bc2f0797705..87a0339fff7d2 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -374,12 +374,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // of whatever returned this exact `impl Trait`. } - ty::TyTrait(ref data) => { + ty::TyDynamic(data, r) => { // WfObject // // Here, we defer WF checking due to higher-ranked // regions. This is perhaps not ideal. - self.from_object_ty(ty, data); + self.from_object_ty(ty, data, r); // FIXME(#27579) RFC also considers adding trait // obligations that don't refer to Self and @@ -388,7 +388,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { let cause = self.cause(traits::MiscObligation); let component_traits = - data.auto_traits().chain(data.principal().map(|ref p| p.def_id())); + data.auto_traits().chain(data.principal().map(|p| p.def_id())); self.out.extend( component_traits.map(|did| traits::Obligation::new( cause.clone(), @@ -450,7 +450,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { .collect() } - fn from_object_ty(&mut self, ty: Ty<'tcx>, data: &ty::TraitObject<'tcx>) { + fn from_object_ty(&mut self, ty: Ty<'tcx>, + data: ty::Binder<&'tcx ty::Slice>>, + region: &'tcx ty::Region) { // Imagine a type like this: // // trait Foo { } @@ -485,11 +487,9 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { if !data.has_escaping_regions() { let implicit_bounds = - object_region_bounds(self.infcx.tcx, - data.principal().unwrap(), - data.auto_traits()); + object_region_bounds(self.infcx.tcx, data); - let explicit_bound = data.region_bound; + let explicit_bound = region; for implicit_bound in implicit_bounds { let cause = self.cause(traits::ObjectTypeBound(ty, explicit_bound)); @@ -506,26 +506,23 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { /// they declare `trait SomeTrait : 'static`, for example, then /// `'static` would appear in the list. The hard work is done by /// `ty::required_region_bounds`, see that for more information. -pub fn object_region_bounds<'a, 'gcx, 'tcx, I>( +pub fn object_region_bounds<'a, 'gcx, 'tcx>( tcx: TyCtxt<'a, 'gcx, 'tcx>, - principal: ty::PolyExistentialTraitRef<'tcx>, - others: I) + existential_predicates: ty::Binder<&'tcx ty::Slice>>) -> Vec<&'tcx ty::Region> - where I: Iterator { // Since we don't actually *know* the self type for an object, // this "open(err)" serves as a kind of dummy standin -- basically // a skolemized type. let open_ty = tcx.mk_infer(ty::FreshTy(0)); - let mut predicates = others.map(|d| { - let trait_ref = ty::TraitRef { - def_id: d, - substs: tcx.mk_substs_trait(open_ty, &[]) - }; - trait_ref.to_predicate() - }).collect::>(); - predicates.push(principal.with_self_ty(tcx, open_ty).to_predicate()); + let predicates = existential_predicates.iter().filter_map(|predicate| { + if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() { + None + } else { + Some(predicate.with_self_ty(tcx, open_ty)) + } + }).collect(); tcx.required_region_bounds(open_ty, predicates) } diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 242342a7f93d6..d839df80a12ac 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -16,9 +16,8 @@ use ty::{TyBool, TyChar, TyAdt}; use ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyFnDef, TyFnPtr}; use ty::{TyParam, TyRawPtr, TyRef, TyNever, TyTuple}; use ty::{TyClosure, TyProjection, TyAnon}; -use ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer}; +use ty::{TyBox, TyDynamic, TyInt, TyUint, TyInfer}; use ty::{self, Ty, TyCtxt, TypeFoldable}; -use ty::fold::{TypeFolder, TypeVisitor}; use std::cell::Cell; use std::fmt; @@ -298,58 +297,23 @@ fn in_binder<'a, 'gcx, 'tcx, T, U>(f: &mut fmt::Formatter, write!(f, "{}", new_value) } -/// This curious type is here to help pretty-print trait objects. In -/// a trait object, the projections are stored separately from the -/// main trait bound, but in fact we want to package them together -/// when printing out; they also have separate binders, but we want -/// them to share a binder when we print them out. (And the binder -/// pretty-printing logic is kind of clever and we don't want to -/// reproduce it.) So we just repackage up the structure somewhat. -/// -/// Right now there is only one trait in an object that can have -/// projection bounds, so we just stuff them altogether. But in -/// reality we should eventually sort things out better. -#[derive(Clone, Debug)] -struct TraitAndProjections<'tcx>(ty::TraitRef<'tcx>, - Vec>); - -impl<'tcx> TypeFoldable<'tcx> for TraitAndProjections<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - TraitAndProjections(self.0.fold_with(folder), self.1.fold_with(folder)) - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.0.visit_with(visitor) || self.1.visit_with(visitor) - } -} - -impl<'tcx> fmt::Display for TraitAndProjections<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let TraitAndProjections(ref trait_ref, ref projection_bounds) = *self; - parameterized(f, trait_ref.substs, - trait_ref.def_id, - projection_bounds) - } -} - -impl<'tcx> fmt::Display for ty::TraitObject<'tcx> { +impl<'tcx> fmt::Display for &'tcx ty::Slice> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Generate the main trait ref, including associated types. ty::tls::with(|tcx| { // Use a type that can't appear in defaults of type parameters. let dummy_self = tcx.mk_infer(ty::FreshTy(0)); - let principal = self.principal().and_then(|ref p| tcx.lift(p)) - .expect("could not lift TraitRef for printing") - .with_self_ty(tcx, dummy_self).0; - let projections = self.projection_bounds.iter().map(|p| { - tcx.lift(p) - .expect("could not lift projection for printing") - .with_self_ty(tcx, dummy_self).0 - }).collect(); - - let tap = ty::Binder(TraitAndProjections(principal, projections)); - in_binder(f, tcx, &ty::Binder(""), Some(tap))?; + if let Some(p) = self.principal() { + let principal = tcx.lift(&p).expect("could not lift TraitRef for printing") + .with_self_ty(tcx, dummy_self); + let projections = self.projection_bounds().map(|p| { + tcx.lift(&p) + .expect("could not lift projection for printing") + .with_self_ty(tcx, dummy_self) + }).collect::>(); + parameterized(f, principal.substs, principal.def_id, &projections)?; + } // Builtin bounds. for did in self.auto_traits() { @@ -359,16 +323,6 @@ impl<'tcx> fmt::Display for ty::TraitObject<'tcx> { Ok(()) })?; - // FIXME: It'd be nice to compute from context when this bound - // is implied, but that's non-trivial -- we'd perhaps have to - // use thread-local data of some kind? There are also - // advantages to just showing the region, since it makes - // people aware that it's there. - let bound = self.region_bound.to_string(); - if !bound.is_empty() { - write!(f, " + {}", bound)?; - } - Ok(()) } } @@ -455,45 +409,6 @@ impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { } } -impl<'tcx> fmt::Debug for ty::TraitObject<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut empty = true; - let mut maybe_continue = |f: &mut fmt::Formatter| { - if empty { - empty = false; - Ok(()) - } else { - write!(f, " + ") - } - }; - - maybe_continue(f)?; - write!(f, "{:?}", self.principal())?; - - let region_str = format!("{:?}", self.region_bound); - if !region_str.is_empty() { - maybe_continue(f)?; - write!(f, "{}", region_str)?; - } - - ty::tls::with(|tcx| { - for did in self.auto_traits() { - maybe_continue(f)?; - write!(f, " + {}", tcx.item_path_str(did))?; - } - - Ok(()) - })?; - - for projection_bound in &self.projection_bounds { - maybe_continue(f)?; - write!(f, "{:?}", projection_bound)?; - } - - Ok(()) - } -} - impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -746,6 +661,12 @@ impl fmt::Debug for ty::IntVarValue { } }*/ +impl<'tcx> fmt::Display for ty::Binder<&'tcx ty::Slice>> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) + } +} + impl<'tcx> fmt::Display for ty::Binder> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { ty::tls::with(|tcx| in_binder(f, tcx, self, tcx.lift(self))) @@ -865,7 +786,15 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { } }) } - TyTrait(ref data) => write!(f, "{}", data), + TyDynamic(data, r) => { + write!(f, "{}", data)?; + let r = r.to_string(); + if !r.is_empty() { + write!(f, " + {}", r) + } else { + Ok(()) + } + } TyProjection(ref data) => write!(f, "{}", data), TyAnon(def_id, substs) => { ty::tls::with(|tcx| { diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 8aa5e9e0a9460..6e9467d63dd1f 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -572,7 +572,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { consider using a raw pointer instead") } - ty::TyTrait(..) => { + ty::TyDynamic(..) => { FfiUnsafe("found Rust trait type in foreign module, \ consider using a raw pointer instead") } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f59f2bcc07476..1e3d12c50a394 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -416,6 +416,15 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> } } +impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice>> + for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) + -> Result<&'tcx ty::Slice>, Self::Error> { + Ok(self.tcx().mk_existential_predicates((0..self.read_usize()?) + .map(|_| Decodable::decode(self)))?) + } +} + impl<'a, 'tcx> MetadataBlob { pub fn is_compatible(&self) -> bool { self.raw_bytes().starts_with(METADATA_HEADER) diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index a79f7e1733c26..f1126e6fd256c 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -295,16 +295,14 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>, let (source, target) = ccx.tcx().struct_lockstep_tails(source, target); match (&source.sty, &target.sty) { (&ty::TyArray(_, len), &ty::TySlice(_)) => C_uint(ccx, len), - (&ty::TyTrait(_), &ty::TyTrait(_)) => { + (&ty::TyDynamic(..), &ty::TyDynamic(..)) => { // For now, upcasts are limited to changes in marker // traits, and hence never actually require an actual // change to the vtable. old_info.expect("unsized_info: missing old info for trait upcast") } - (_, &ty::TyTrait(ref data)) => { - let trait_ref = data.principal().unwrap().with_self_ty(ccx.tcx(), source); - let trait_ref = ccx.tcx().erase_regions(&trait_ref); - consts::ptrcast(meth::get_vtable(ccx, trait_ref), + (_, &ty::TyDynamic(ref data, ..)) => { + consts::ptrcast(meth::get_vtable(ccx, source, data.principal()), Type::vtable_ptr(ccx)) } _ => bug!("unsized_info: invalid unsizing {:?} -> {:?}", diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index ac8793c47e726..120e1a562ebea 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -763,7 +763,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, ty::TyFnDef(..) | ty::TyFnPtr(_) | ty::TyNever | - ty::TyTrait(_) => { + ty::TyDynamic(..) => { /* nothing to do */ } ty::TyAdt(adt_def, substs) => { @@ -1003,18 +1003,20 @@ fn create_trans_items_for_vtable_methods<'a, 'tcx>(scx: &SharedCrateContext<'a, output: &mut Vec>) { assert!(!trait_ty.needs_subst() && !impl_ty.needs_subst()); - if let ty::TyTrait(ref trait_ty) = trait_ty.sty { - let poly_trait_ref = trait_ty.principal().unwrap().with_self_ty(scx.tcx(), impl_ty); - let param_substs = scx.tcx().intern_substs(&[]); - - // Walk all methods of the trait, including those of its supertraits - let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref); - let methods = methods.filter_map(|method| method) - .filter_map(|(def_id, substs)| do_static_dispatch(scx, def_id, substs, param_substs)) - .filter(|&(def_id, _)| can_have_local_instance(scx.tcx(), def_id)) - .map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs)); - output.extend(methods); - + if let ty::TyDynamic(ref trait_ty, ..) = trait_ty.sty { + if let Some(principal) = trait_ty.principal() { + let poly_trait_ref = principal.with_self_ty(scx.tcx(), impl_ty); + let param_substs = scx.tcx().intern_substs(&[]); + + // Walk all methods of the trait, including those of its supertraits + let methods = traits::get_vtable_methods(scx.tcx(), poly_trait_ref); + let methods = methods.filter_map(|method| method) + .filter_map(|(def_id, substs)| do_static_dispatch(scx, def_id, substs, + param_substs)) + .filter(|&(def_id, _)| can_have_local_instance(scx.tcx(), def_id)) + .map(|(def_id, substs)| create_fn_trans_item(scx, def_id, substs, param_substs)); + output.extend(methods); + } // Also add the destructor let dg_type = glue::get_drop_glue_type(scx.tcx(), impl_ty); output.push(TransItem::DropGlue(DropGlueKind::Ty(dg_type))); diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index 771c5ef6d9d28..c0d7c64bd192c 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -95,7 +95,8 @@ pub struct LocalCrateContext<'tcx> { /// Cache instances of monomorphic and polymorphic items instances: RefCell, ValueRef>>, /// Cache generated vtables - vtables: RefCell, ValueRef>>, + vtables: RefCell, + Option>), ValueRef>>, /// Cache of constant strings, const_cstr_cache: RefCell>, @@ -800,7 +801,9 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> { &self.local().instances } - pub fn vtables<'a>(&'a self) -> &'a RefCell, ValueRef>> { + pub fn vtables<'a>(&'a self) + -> &'a RefCell, + Option>), ValueRef>> { &self.local().vtables } diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 5af1b0faebc4a..8bbe50af0651c 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -432,7 +432,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // But it does not describe the trait's methods. let containing_scope = match trait_type.sty { - ty::TyTrait(ref data) => if let Some(principal) = data.principal() { + ty::TyDynamic(ref data, ..) => if let Some(principal) = data.principal() { let def_id = principal.def_id(); get_namespace_and_span_for_item(cx, def_id).0 } else { @@ -523,7 +523,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::TyStr => { fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span) } - ty::TyTrait(..) => { + ty::TyDynamic(..) => { MetadataCreationResult::new( trait_pointer_metadata(cx, t, None, unique_type_id), false) @@ -538,7 +538,7 @@ pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::TyStr => { vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span) } - ty::TyTrait(..) => { + ty::TyDynamic(..) => { MetadataCreationResult::new( trait_pointer_metadata(cx, ty, Some(t), unique_type_id), false) diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 1831125e8eb9e..80e6bd7aa2984 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -93,7 +93,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_debuginfo_type_name(cx, inner_type, true, output); output.push(']'); }, - ty::TyTrait(ref trait_data) => { + ty::TyDynamic(ref trait_data, ..) => { if let Some(principal) = trait_data.principal() { let principal = cx.tcx().erase_late_bound_regions_and_normalize( &principal); diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs index d6d4d33923f1a..06d0b1e19828e 100644 --- a/src/librustc_trans/glue.rs +++ b/src/librustc_trans/glue.rs @@ -394,7 +394,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>, (size, align) } - ty::TyTrait(..) => { + ty::TyDynamic(..) => { // info points to the vtable and the second entry in the vtable is the // dynamic size of the object. let info = bcx.pointercast(info, Type::int(bcx.ccx()).ptr_to()); @@ -463,7 +463,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, trans_exchange_free_ty(bcx, llbox, content_ty, DebugLoc::None) } } - ty::TyTrait(..) => { + ty::TyDynamic(..) => { // No support in vtable for distinguishing destroying with // versus without calling Drop::drop. Assert caller is // okay with always calling the Drop impl, if any. diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs index 1e687f5ff6e3a..aa9b900fa4653 100644 --- a/src/librustc_trans/meth.rs +++ b/src/librustc_trans/meth.rs @@ -110,42 +110,48 @@ pub fn trans_object_shim<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>, /// making an object `Foo` from a value of type `Foo`, then /// `trait_ref` would map `T:Trait`. pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>) + ty: ty::Ty<'tcx>, + trait_ref: Option>) -> ValueRef { let tcx = ccx.tcx(); let _icx = push_ctxt("meth::get_vtable"); - debug!("get_vtable(trait_ref={:?})", trait_ref); + debug!("get_vtable(ty={:?}, trait_ref={:?})", ty, trait_ref); // Check the cache. - if let Some(&val) = ccx.vtables().borrow().get(&trait_ref) { + if let Some(&val) = ccx.vtables().borrow().get(&(ty, trait_ref)) { return val; } // Not in the cache. Build it. let nullptr = C_null(Type::nil(ccx).ptr_to()); - let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| { - opt_mth.map_or(nullptr, |(def_id, substs)| { - Callee::def(ccx, def_id, substs).reify(ccx) - }) - }); - let size_ty = sizing_type_of(ccx, trait_ref.self_ty()); + let size_ty = sizing_type_of(ccx, ty); let size = machine::llsize_of_alloc(ccx, size_ty); - let align = align_of(ccx, trait_ref.self_ty()); + let align = align_of(ccx, ty); - let components: Vec<_> = [ + let mut components: Vec<_> = [ // Generate a destructor for the vtable. - glue::get_drop_glue(ccx, trait_ref.self_ty()), + glue::get_drop_glue(ccx, ty), C_uint(ccx, size), C_uint(ccx, align) - ].iter().cloned().chain(methods).collect(); + ].iter().cloned().collect(); + + if let Some(trait_ref) = trait_ref { + let trait_ref = trait_ref.with_self_ty(tcx, ty); + let methods = traits::get_vtable_methods(tcx, trait_ref).map(|opt_mth| { + opt_mth.map_or(nullptr, |(def_id, substs)| { + Callee::def(ccx, def_id, substs).reify(ccx) + }) + }); + components.extend(methods); + } let vtable_const = C_struct(ccx, &components, false); let align = machine::llalign_of_pref(ccx, val_ty(vtable_const)); let vtable = consts::addr_of(ccx, vtable_const, align, "vtable"); - ccx.vtables().borrow_mut().insert(trait_ref, vtable); + ccx.vtables().borrow_mut().insert((ty, trait_ref), vtable); vtable } diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index c46c6e6f769af..979c2206fc1de 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -457,11 +457,11 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_type_name(inner_type, output); output.push(']'); }, - ty::TyTrait(ref trait_data) => { + ty::TyDynamic(ref trait_data, ..) => { if let Some(principal) = trait_data.principal() { self.push_def_path(principal.def_id(), output); self.push_type_params(principal.skip_binder().substs, - &trait_data.projection_bounds, + &trait_data.projection_bounds().collect::>()[..], output); } }, diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 16d4f97200cb2..22c405fe254a6 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -95,7 +95,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ ty::TyAnon(..) | ty::TyError => { bug!("fictitious type {:?} in sizing_type_of()", t) } - ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => bug!() + ty::TySlice(_) | ty::TyDynamic(..) | ty::TyStr => bug!() }; debug!("--> mapped t={:?} to llsizingty={:?}", t, llsizingty); @@ -148,7 +148,7 @@ fn unsized_info_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => { Type::uint_from_ty(ccx, ast::UintTy::Us) } - ty::TyTrait(_) => Type::vtable_ptr(ccx), + ty::TyDynamic(..) => Type::vtable_ptr(ccx), _ => bug!("Unexpected tail in unsized_info_ty: {:?} for ty={:?}", unsized_part, ty) } @@ -258,7 +258,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> // fat pointers is of the right type (e.g. for array accesses), even // when taking the address of an unsized field in a struct. ty::TySlice(ty) => in_memory_type_of(cx, ty), - ty::TyStr | ty::TyTrait(..) => Type::i8(cx), + ty::TyStr | ty::TyDynamic(..) => Type::i8(cx), ty::TyFnDef(..) => Type::nil(cx), ty::TyFnPtr(f) => { diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index bffd85c57f705..986d817a10cc3 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -49,6 +49,7 @@ //! an rptr (`&r.T`) use the region `r` that appears in the rptr. use rustc_const_eval::eval_length; +use rustc_data_structures::accumulate_vec::AccumulateVec; use hir::{self, SelfKind}; use hir::def::Def; use hir::def_id::DefId; @@ -69,6 +70,7 @@ use util::common::{ErrorReported, FN_OUTPUT_NAME}; use util::nodemap::{NodeMap, FxHashSet}; use std::cell::RefCell; +use std::iter; use syntax::{abi, ast}; use syntax::feature_gate::{GateIssue, emit_feature_err}; use syntax::symbol::{Symbol, keywords}; @@ -1052,8 +1054,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let b = &trait_bounds[0]; let span = b.trait_ref.path.span; struct_span_err!(self.tcx().sess, span, E0225, - "only the builtin traits can be used as closure or object bounds") - .span_label(span, &format!("non-builtin trait used as bounds")) + "only Send/Sync traits can be used as additional traits in a trait object") + .span_label(span, &format!("non-Send/Sync additional trait")) .emit(); } @@ -1070,30 +1072,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ty: b.ty } }) - }).collect(); - - let region_bound = - self.compute_object_lifetime_bound(span, - ®ion_bounds, - existential_principal, - &auto_traits); - - let region_bound = match region_bound { - Some(r) => r, - None => { - tcx.mk_region(match rscope.object_lifetime_default(span) { - Some(r) => r, - None => { - span_err!(self.tcx().sess, span, E0228, - "the lifetime bound for this object type cannot be deduced \ - from context; please supply an explicit bound"); - ty::ReStatic - } - }) - } - }; - - debug!("region_bound: {:?}", region_bound); + }); // ensure the super predicates and stop if we encountered an error if self.ensure_super_predicates(span, principal.def_id()).is_err() { @@ -1135,12 +1114,37 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { .emit(); } - let ty = tcx.mk_trait(ty::TraitObject::new( - Some(existential_principal), - region_bound, - auto_traits, - existential_projections - )); + let mut v = + iter::once(ty::ExistentialPredicate::Trait(*existential_principal.skip_binder())) + .chain(auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait)) + .chain(existential_projections + .map(|x| ty::ExistentialPredicate::Projection(*x.skip_binder()))) + .collect::>(); + v.sort_by(|a, b| a.cmp(tcx, b)); + let existential_predicates = ty::Binder(tcx.mk_existential_predicates(v.into_iter())); + + let region_bound = self.compute_object_lifetime_bound(span, + ®ion_bounds, + existential_predicates); + + let region_bound = match region_bound { + Some(r) => r, + None => { + tcx.mk_region(match rscope.object_lifetime_default(span) { + Some(r) => r, + None => { + span_err!(self.tcx().sess, span, E0228, + "the lifetime bound for this object type cannot be deduced \ + from context; please supply an explicit bound"); + ty::ReStatic + } + }) + } + }; + + debug!("region_bound: {:?}", region_bound); + + let ty = tcx.mk_dynamic(existential_predicates, region_bound); debug!("trait_object_type: {:?}", ty); ty } @@ -1922,38 +1926,36 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { fn compute_object_lifetime_bound(&self, span: Span, explicit_region_bounds: &[&hir::Lifetime], - principal_trait_ref: ty::PolyExistentialTraitRef<'tcx>, - auto_traits: &[DefId]) + existential_predicates: ty::Binder<&'tcx ty::Slice>>) -> Option<&'tcx ty::Region> // if None, use the default { let tcx = self.tcx(); debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \ - principal_trait_ref={:?}, auto_traits={:?})", + existential_predicates={:?})", explicit_region_bounds, - principal_trait_ref, - auto_traits); + existential_predicates); if explicit_region_bounds.len() > 1 { span_err!(tcx.sess, explicit_region_bounds[1].span, E0226, "only a single explicit lifetime bound is permitted"); } - if !explicit_region_bounds.is_empty() { + if let Some(&r) = explicit_region_bounds.get(0) { // Explicitly specified region bound. Use that. - let r = explicit_region_bounds[0]; return Some(ast_region_to_region(tcx, r)); } - if let Err(ErrorReported) = - self.ensure_super_predicates(span, principal_trait_ref.def_id()) { - return Some(tcx.mk_region(ty::ReStatic)); + if let Some(principal) = existential_predicates.principal() { + if let Err(ErrorReported) = self.ensure_super_predicates(span, principal.def_id()) { + return Some(tcx.mk_region(ty::ReStatic)); + } } // No explicit region bound specified. Therefore, examine trait // bounds and see if we can derive region bounds from those. let derived_region_bounds = - object_region_bounds(tcx, principal_trait_ref, auto_traits.into_iter().cloned()); + object_region_bounds(tcx, existential_predicates); // If there are no derived region bounds, then report back that we // can find no region bound. The caller will use the default. @@ -2000,7 +2002,11 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => { match b.trait_ref.path.def { Def::Trait(trait_did) => { - if tcx.try_add_builtin_trait(trait_did, &mut auto_traits) { + // Checks whether `trait_did` refers to one of the builtin + // traits, like `Send`, and adds it to `auto_traits` if so. + if Some(trait_did) == tcx.lang_items.send_trait() || + Some(trait_did) == tcx.lang_items.sync_trait() { + auto_traits.push(trait_did); let segments = &b.trait_ref.path.segments; let parameters = &segments[segments.len() - 1].parameters; if !parameters.types().is_empty() { @@ -2115,12 +2121,15 @@ impl<'a, 'gcx, 'tcx> Bounds<'tcx> { { let mut vec = Vec::new(); - for trait_did in &self.auto_traits { - let trait_ref = ty::TraitRef { - def_id: *trait_did, - substs: tcx.mk_substs_trait(param_ty, &[]), - }; - vec.push(trait_ref.to_predicate()); + // If it could be sized, and is, add the sized predicate + if self.implicitly_sized { + if let Some(sized) = tcx.lang_items.sized_trait() { + let trait_ref = ty::TraitRef { + def_id: sized, + substs: tcx.mk_substs_trait(param_ty, &[]) + }; + vec.push(trait_ref.to_predicate()); + } } for ®ion_bound in &self.region_bounds { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 63e797a87ff21..6e2b42881a709 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -340,7 +340,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::Pat) -> bool { if let PatKind::Binding(..) = inner.node { if let Some(mt) = self.shallow_resolve(expected).builtin_deref(true, ty::NoPreference) { - if let ty::TyTrait(..) = mt.ty.sty { + if let ty::TyDynamic(..) = mt.ty.sty { // This is "x = SomeTrait" being reduced from // "let &x = &SomeTrait" or "let box x = Box", an error. let type_str = self.ty_to_string(expected); diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 197e7793f4b2a..5f904f507e272 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -65,7 +65,7 @@ pub struct CastCheck<'tcx> { /// fat pointers if their unsize-infos have the same kind. #[derive(Copy, Clone, PartialEq, Eq)] enum UnsizeKind<'tcx> { - Vtable(DefId), + Vtable(Option), Length, /// The unsize info of this projection OfProjection(&'tcx ty::ProjectionTy<'tcx>), @@ -79,7 +79,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn unsize_kind(&self, t: Ty<'tcx>) -> Option> { match t.sty { ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length), - ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal().unwrap().def_id())), + ty::TyDynamic(ref tty, ..) => + Some(UnsizeKind::Vtable(tty.principal().map(|p| p.def_id()))), ty::TyAdt(def, substs) if def.is_struct() => { // FIXME(arielb1): do some kind of normalization match def.struct_variant().fields.last() { @@ -130,7 +131,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { // cases now. We do a more thorough check at the end, once // inference is more completely known. match cast_ty.sty { - ty::TyTrait(..) | ty::TySlice(..) => { + ty::TyDynamic(..) | ty::TySlice(..) => { check.report_cast_to_unsized_type(fcx); Err(ErrorReported) } diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index be6d65bf511fd..744d99fe60d17 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -111,16 +111,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { expected_ty); match expected_ty.sty { - ty::TyTrait(ref object_type) => { - let sig = object_type.projection_bounds - .iter() + ty::TyDynamic(ref object_type, ..) => { + let sig = object_type.projection_bounds() .filter_map(|pb| { let pb = pb.with_self_ty(self.tcx, self.tcx.types.err); self.deduce_sig_from_projection(&pb) }) .next(); - let kind = - self.tcx.lang_items.fn_trait_kind(object_type.principal().unwrap().def_id()); + let kind = object_type.principal() + .and_then(|p| self.tcx.lang_items.fn_trait_kind(p.def_id())); (sig, kind) } ty::TyInfer(ty::TyVar(vid)) => self.deduce_expectations_from_obligations(vid), diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 8868d1e54f4b9..a5446b0fbaa89 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -515,7 +515,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( } // these are always dtorck - ty::TyTrait(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(), + ty::TyDynamic(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(), } } @@ -564,7 +564,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, let revised_ty = revise_self_ty(tcx, adt_def, impl_def_id, substs); return DropckKind::RevisedSelf(revised_ty); } - ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => { + ty::TyDynamic(..) | ty::TyProjection(..) | ty::TyAnon(..) => { debug!("ty: {:?} isn't known, and therefore is a dropck type", ty); return DropckKind::BorrowedDataMustStrictlyOutliveSelf; }, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 4c19ea46e5a7f..ff9eaa012ba41 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -255,7 +255,7 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { .autoderef(self.span, self_ty) .filter_map(|(ty, _)| { match ty.sty { - ty::TyTrait(ref data) => data.principal().map(|p| closure(self, ty, p)), + ty::TyDynamic(ref data, ..) => data.principal().map(|p| closure(self, ty, p)), _ => None, } }) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index b76d13125b474..b0787d75c9cb4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -295,9 +295,11 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { debug!("assemble_probe: self_ty={:?}", self_ty); match self_ty.sty { - ty::TyTrait(box ref data) => { - self.assemble_inherent_candidates_from_object(self_ty, data.principal().unwrap()); - self.assemble_inherent_impl_candidates_for_type(data.principal().unwrap().def_id()); + ty::TyDynamic(ref data, ..) => { + if let Some(p) = data.principal() { + self.assemble_inherent_candidates_from_object(self_ty, p); + self.assemble_inherent_impl_candidates_for_type(p.def_id()); + } } ty::TyAdt(def, _) => { self.assemble_inherent_impl_candidates_for_type(def.did); diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 508b0e820cef1..9443e0a3586b0 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -379,8 +379,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { match ty.sty { ty::TyAdt(def, _) => def.did.is_local(), - ty::TyTrait(ref tr) => tr.principal().map(|p| - p.def_id().is_local()).unwrap_or(false), + ty::TyDynamic(ref tr, ..) => tr.principal() + .map_or(false, |p| p.def_id().is_local()), ty::TyParam(_) => true, diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c921936800b38..bad7b4d96cac6 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -269,7 +269,7 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> { /// for examples of where this comes up,. fn rvalue_hint(fcx: &FnCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> { match fcx.tcx.struct_tail(ty).sty { - ty::TySlice(_) | ty::TyStr | ty::TyTrait(..) => { + ty::TySlice(_) | ty::TyStr | ty::TyDynamic(..) => { ExpectRvalueLikeUnsized(ty) } _ => ExpectHasType(ty) diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index ca33682480c4c..fb35cb8181cb3 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -806,11 +806,10 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } /*From:*/ (_, - /*To: */ &ty::TyTrait(ref obj)) => { + /*To: */ &ty::TyDynamic(.., r)) => { // When T is existentially quantified as a trait // `Foo+'to`, it must outlive the region bound `'to`. - self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), - from_ty, obj.region_bound); + self.type_must_outlive(infer::RelateObjectBound(cast_expr.span), from_ty, r); } /*From:*/ (&ty::TyBox(from_referent_ty), diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 57859f9c84cb6..f29965ee47c8f 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -118,15 +118,8 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { // FIXME(#27579) what amount of WF checking do we need for neg impls? let trait_ref = ccx.tcx.impl_trait_ref(ccx.tcx.map.local_def_id(item.id)).unwrap(); - ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id); - let sync_trait = ccx.tcx.lang_items.require(lang_items::SyncTraitLangItem) - .unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..])); - let send_trait = ccx.tcx.lang_items.require(lang_items::SendTraitLangItem) - .unwrap_or_else(|msg| ccx.tcx.sess.fatal(&msg[..])); - if trait_ref.def_id != sync_trait && trait_ref.def_id != send_trait { - if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) { - error_192(ccx, item.span); - } + if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) { + error_192(ccx, item.span); } } hir::ItemFn(.., ref body) => { diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 0b6f2f554a177..30472f85db120 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -23,7 +23,7 @@ use rustc::traits::{self, ObligationCause, Reveal}; use rustc::ty::ParameterEnvironment; use rustc::ty::{Ty, TyBool, TyChar, TyError}; use rustc::ty::{TyParam, TyRawPtr}; -use rustc::ty::{TyRef, TyAdt, TyTrait, TyNever, TyTuple}; +use rustc::ty::{TyRef, TyAdt, TyDynamic, TyNever, TyTuple}; use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt}; use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr}; use rustc::ty::{TyProjection, TyAnon}; @@ -68,7 +68,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { match ty.sty { TyAdt(def, _) => Some(def.did), - TyTrait(ref t) => t.principal().map(|p| p.def_id()), + TyDynamic(ref t, ..) => t.principal().map(|p| p.def_id()), TyBox(_) => self.inference_context.tcx.lang_items.owned_box(), diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index f949a8796c7e0..f04442de09c30 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -86,7 +86,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> { ty::TyAdt(def, _) => { self.check_def_id(item, def.did); } - ty::TyTrait(ref data) if data.principal().is_some() => { + ty::TyDynamic(ref data, ..) if data.principal().is_some() => { self.check_def_id(item, data.principal().unwrap().def_id()); } ty::TyBox(..) => { diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs index 5ae233f647939..815811675a54b 100644 --- a/src/librustc_typeck/coherence/overlap.rs +++ b/src/librustc_typeck/coherence/overlap.rs @@ -178,16 +178,13 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OverlapChecker<'cx, 'tcx> { } // check for overlap with the automatic `impl Trait for Trait` - if let ty::TyTrait(ref data) = trait_ref.self_ty().sty { + if let ty::TyDynamic(ref data, ..) = trait_ref.self_ty().sty { // This is something like impl Trait1 for Trait2. Illegal // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe. - if data.principal().is_none() || - !self.tcx.is_object_safe(data.principal().unwrap().def_id()) { - // This is an error, but it will be - // reported by wfcheck. Ignore it - // here. This is tested by - // `coherence-impl-trait-for-trait-object-safe.rs`. + if data.principal().map_or(true, |p| !self.tcx.is_object_safe(p.def_id())) { + // This is an error, but it will be reported by wfcheck. Ignore it here. + // This is tested by `coherence-impl-trait-for-trait-object-safe.rs`. } else { let mut supertrait_def_ids = traits::supertrait_def_ids(self.tcx, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0f8fe32c8982e..2b69ac12a2c4d 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1617,12 +1617,11 @@ fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, "default bound relaxed for a type parameter, but \ this does nothing because the given bound is not \ a default. Only `?Sized` is supported"); - tcx.try_add_builtin_trait(kind_id, bounds); } } } _ if kind_id.is_ok() => { - tcx.try_add_builtin_trait(kind_id.unwrap(), bounds); + bounds.push(kind_id.unwrap()); } // No lang item for Sized, so we can't add it as a bound. None => {} diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 04314045733ec..01e99a296e886 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -2778,8 +2778,8 @@ fn main() { } ``` -Builtin traits are an exception to this rule: it's possible to have bounds of -one non-builtin type, plus any number of builtin types. For example, the +Send and Sync are an exception to this rule: it's possible to have bounds of +one non-builtin trait, plus either or both of Send and Sync. For example, the following compiles correctly: ``` diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 076d024c1e1bb..f34753c227d71 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -371,16 +371,17 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { variance); } - ty::TyTrait(ref data) => { + ty::TyDynamic(ref data, r) => { // The type `Foo` is contravariant w/r/t `'a`: let contra = self.contravariant(variance); - self.add_constraints_from_region(generics, data.region_bound, contra); + self.add_constraints_from_region(generics, r, contra); - let poly_trait_ref = data.principal().unwrap().with_self_ty(self.tcx(), - self.tcx().types.err); - self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance); + if let Some(p) = data.principal() { + let poly_trait_ref = p.with_self_ty(self.tcx(), self.tcx().types.err); + self.add_constraints_from_trait_ref(generics, poly_trait_ref.0, variance); + } - for projection in &data.projection_bounds { + for projection in data.projection_bounds() { self.add_constraints_from_ty(generics, projection.0.ty, self.invariant); } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9d98cdd3f0377..b9ba7f732a68e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -594,10 +594,10 @@ pub enum TyParamBound { impl TyParamBound { fn maybe_sized(cx: &DocContext) -> TyParamBound { - let did = cx.tcx().lang_items.require(lang_items::SizedTraitLangItem) - .unwrap_or_else(|msg| cx.tcx().sess.fatal(&msg[..])); - let empty = cx.tcx().intern_substs(&[]); - let path = external_path(cx, &cx.tcx().item_name(did).as_str(), + let did = cx.tcx.lang_items.require(lang_items::SizedTraitLangItem) + .unwrap_or_else(|msg| cx.tcx.sess.fatal(&msg[..])); + let empty = cx.tcx.intern_substs(&[]); + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); TraitBound(PolyTrait { @@ -1855,23 +1855,16 @@ impl<'tcx> Clean for ty::Ty<'tcx> { is_generic: false, } } - ty::TyTrait(ref obj) => { + ty::TyDynamic(ref obj, ref reg) => { if let Some(principal) = obj.principal() { let did = principal.def_id(); inline::record_extern_fqn(cx, did, TypeKind::Trait); let mut typarams = vec![]; - obj.region_bound.clean(cx).map(|b| typarams.push(RegionBound(b))); + reg.clean(cx).map(|b| typarams.push(RegionBound(b))); for did in obj.auto_traits() { - let tcx = match cx.tcx_opt() { - Some(tcx) => tcx, - None => { - typarams.push(RegionBound(Lifetime::statik())); - continue; - } - }; - let empty = tcx.intern_substs(&[]); - let path = external_path(cx, &tcx.item_name(did).as_str(), + let empty = cx.tcx.intern_substs(&[]); + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); inline::record_extern_fqn(cx, did, TypeKind::Trait); let bound = TraitBound(PolyTrait { @@ -1887,14 +1880,14 @@ impl<'tcx> Clean for ty::Ty<'tcx> { } let mut bindings = vec![]; - for &ty::Binder(ref pb) in &obj.projection_bounds { + for ty::Binder(ref pb) in obj.projection_bounds() { bindings.push(TypeBinding { name: pb.item_name.clean(cx), ty: pb.ty.clean(cx) }); } - let path = external_path(cx, &cx.tcx().item_name(did).as_str(), Some(did), + let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, bindings, principal.0.substs); ResolvedPath { path: path, diff --git a/src/test/compile-fail/E0225.rs b/src/test/compile-fail/E0225.rs index b013788ceff85..8c79c15e3de5b 100644 --- a/src/test/compile-fail/E0225.rs +++ b/src/test/compile-fail/E0225.rs @@ -10,6 +10,6 @@ fn main() { let _: Box; - //~^ ERROR only the builtin traits can be used as closure or object bounds [E0225] - //~| NOTE non-builtin trait used as bounds + //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object [E0225] + //~| NOTE non-Send/Sync additional trait } diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index 59a039057f37f..a2e2e5caafe6d 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -12,8 +12,7 @@ trait Trait {} pub fn main() { let x: Vec = Vec::new(); - //~^ ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied - //~| ERROR the trait `std::marker::Sized` cannot be made into an object - //~| ERROR the trait bound `Trait + std::marker::Sized: std::marker::Sized` is not satisfied - //~| ERROR the trait `std::marker::Sized` cannot be made into an object + //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object + //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied + //~| ERROR the trait bound `Trait: std::marker::Sized` is not satisfied } diff --git a/src/test/compile-fail/issue-22560.rs b/src/test/compile-fail/issue-22560.rs index 45b110bf5631d..2ad804fc8ced7 100644 --- a/src/test/compile-fail/issue-22560.rs +++ b/src/test/compile-fail/issue-22560.rs @@ -20,6 +20,6 @@ type Test = Add + //~| NOTE missing associated type `Output` value Sub; //~^ ERROR E0225 - //~| NOTE non-builtin trait used as bounds + //~| NOTE non-Send/Sync additional trait fn main() { } diff --git a/src/test/compile-fail/issue-32963.rs b/src/test/compile-fail/issue-32963.rs index 14ab0dd5f631c..f146cfbe68b96 100644 --- a/src/test/compile-fail/issue-32963.rs +++ b/src/test/compile-fail/issue-32963.rs @@ -16,6 +16,6 @@ fn size_of_copy() -> usize { mem::size_of::() } fn main() { size_of_copy::(); - //~^ ERROR the trait bound `Misc + std::marker::Copy: std::marker::Copy` is not satisfied - //~| ERROR the trait `std::marker::Copy` cannot be made into an object + //~^ ERROR only Send/Sync traits can be used as additional traits in a trait object + //~| ERROR the trait bound `Misc: std::marker::Copy` is not satisfied } diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs index 0bfa328751ac1..9f832c7b6e500 100644 --- a/src/test/compile-fail/trait-bounds-cant-coerce.rs +++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs @@ -24,7 +24,7 @@ fn d(x: Box) { a(x); //~ ERROR mismatched types [E0308] //~| NOTE expected type `Box` //~| NOTE found type `Box` - //~| NOTE expected trait Foo, found a different trait Foo + //~| NOTE expected trait `Foo + std::marker::Send`, found trait `Foo` } fn main() { } diff --git a/src/test/run-pass/auxiliary/issue13507.rs b/src/test/run-pass/auxiliary/issue13507.rs index ca1027b11adce..ba50aed42c36f 100644 --- a/src/test/run-pass/auxiliary/issue13507.rs +++ b/src/test/run-pass/auxiliary/issue13507.rs @@ -70,7 +70,7 @@ pub mod testtypes { // Tests TyFnPtr pub type FooFnPtr = fn(u8) -> bool; - // Tests TyTrait + // Tests TyDynamic pub trait FooTrait { fn foo_method(&self) -> usize; } From 9b803ec4217d37fe73f1f738f8007d5d6512a425 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Fri, 25 Nov 2016 19:15:25 -0700 Subject: [PATCH 5/7] Remove auto_traits from PartitionedBounds --- src/librustc_privacy/lib.rs | 7 ++- src/librustc_typeck/astconv.rs | 93 ++++++++++++++++------------ src/librustc_typeck/collect.rs | 28 +++++---- src/test/compile-fail/issue-16966.rs | 2 +- 4 files changed, 73 insertions(+), 57 deletions(-) diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index ee18968ff35e3..5aac23f0f5fa2 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -71,7 +71,8 @@ impl<'a, 'tcx> EmbargoVisitor<'a, 'tcx> { fn item_ty_level(&self, item_def_id: DefId) -> Option { let ty_def_id = match self.tcx.item_type(item_def_id).sty { ty::TyAdt(adt, _) => adt.did, - ty::TyTrait(ref obj) => obj.principal.def_id(), + ty::TyDynamic(ref obj, ..) if obj.principal().is_some() => + obj.principal().unwrap().def_id(), ty::TyProjection(ref proj) => proj.trait_ref.def_id, _ => return Some(AccessLevel::Public) }; @@ -359,7 +360,7 @@ impl<'b, 'a, 'tcx> TypeVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'b fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { let ty_def_id = match ty.sty { ty::TyAdt(adt, _) => Some(adt.did), - ty::TyTrait(ref obj) => Some(obj.principal.def_id()), + ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), ty::TyProjection(ref proj) => Some(proj.trait_ref.def_id), ty::TyFnDef(def_id, ..) | ty::TyAnon(def_id, _) => Some(def_id), @@ -934,7 +935,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<' fn visit_ty(&mut self, ty: Ty<'tcx>) -> bool { let ty_def_id = match ty.sty { ty::TyAdt(adt, _) => Some(adt.did), - ty::TyTrait(ref obj) => Some(obj.principal.def_id()), + ty::TyDynamic(ref obj, ..) => obj.principal().map(|p| p.def_id()), ty::TyProjection(ref proj) => { if self.required_visibility == ty::Visibility::PrivateExternal { // Conservatively approximate the whole type alias as public without diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 986d817a10cc3..9f3887a87686a 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -962,7 +962,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ty.id, path.segments.last().unwrap(), span, - partition_bounds(tcx, span, bounds)) + partition_bounds(bounds)) } else { struct_span_err!(tcx.sess, ty.span, E0172, "expected a reference to a trait") @@ -1045,11 +1045,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_segment, &mut projection_bounds); - let PartitionedBounds { auto_traits, - trait_bounds, + let PartitionedBounds { trait_bounds, region_bounds } = partitioned_bounds; + let (auto_traits, trait_bounds) = split_auto_traits(tcx, trait_bounds); + if !trait_bounds.is_empty() { let b = &trait_bounds[0]; let span = b.trait_ref.path.span; @@ -1443,7 +1444,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { path_id, path.segments.last().unwrap(), span, - partition_bounds(tcx, span, &[])) + partition_bounds(&[])) } Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) | Def::Union(did) => { assert_eq!(opt_self_ty, None); @@ -1897,7 +1898,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ast_bounds: &[hir::TyParamBound]) -> Ty<'tcx> { - let mut partitioned_bounds = partition_bounds(self.tcx(), span, &ast_bounds[..]); + let mut partitioned_bounds = partition_bounds(ast_bounds); let trait_bound = if !partitioned_bounds.trait_bounds.is_empty() { partitioned_bounds.trait_bounds.remove(0) @@ -1982,49 +1983,62 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { } pub struct PartitionedBounds<'a> { - pub auto_traits: Vec, pub trait_bounds: Vec<&'a hir::PolyTraitRef>, pub region_bounds: Vec<&'a hir::Lifetime>, } -/// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc), -/// general trait bounds, and region bounds. -pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - _span: Span, - ast_bounds: &'b [hir::TyParamBound]) - -> PartitionedBounds<'b> +/// Divides a list of general trait bounds into two groups: builtin bounds (Sync/Send) and the +/// remaining general trait bounds. +fn split_auto_traits<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, + trait_bounds: Vec<&'b hir::PolyTraitRef>) + -> (Vec, Vec<&'b hir::PolyTraitRef>) +{ + let (auto_traits, trait_bounds): (Vec<_>, _) = trait_bounds.into_iter().partition(|bound| { + match bound.trait_ref.path.def { + Def::Trait(trait_did) => { + // Checks whether `trait_did` refers to one of the builtin + // traits, like `Send`, and adds it to `auto_traits` if so. + if Some(trait_did) == tcx.lang_items.send_trait() || + Some(trait_did) == tcx.lang_items.sync_trait() { + let segments = &bound.trait_ref.path.segments; + let parameters = &segments[segments.len() - 1].parameters; + if !parameters.types().is_empty() { + check_type_argument_count(tcx, bound.trait_ref.path.span, + parameters.types().len(), &[]); + } + if !parameters.lifetimes().is_empty() { + report_lifetime_number_error(tcx, bound.trait_ref.path.span, + parameters.lifetimes().len(), 0); + } + true + } else { + false + } + } + _ => false + } + }); + + let auto_traits = auto_traits.into_iter().map(|tr| { + if let Def::Trait(trait_did) = tr.trait_ref.path.def { + trait_did + } else { + unreachable!() + } + }).collect::>(); + + (auto_traits, trait_bounds) +} + +/// Divides a list of bounds from the AST into two groups: general trait bounds and region bounds +pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(ast_bounds: &'b [hir::TyParamBound]) + -> PartitionedBounds<'b> { - let mut auto_traits = Vec::new(); let mut region_bounds = Vec::new(); let mut trait_bounds = Vec::new(); for ast_bound in ast_bounds { match *ast_bound { hir::TraitTyParamBound(ref b, hir::TraitBoundModifier::None) => { - match b.trait_ref.path.def { - Def::Trait(trait_did) => { - // Checks whether `trait_did` refers to one of the builtin - // traits, like `Send`, and adds it to `auto_traits` if so. - if Some(trait_did) == tcx.lang_items.send_trait() || - Some(trait_did) == tcx.lang_items.sync_trait() { - auto_traits.push(trait_did); - let segments = &b.trait_ref.path.segments; - let parameters = &segments[segments.len() - 1].parameters; - if !parameters.types().is_empty() { - check_type_argument_count(tcx, b.trait_ref.path.span, - parameters.types().len(), &[]); - } - if !parameters.lifetimes().is_empty() { - report_lifetime_number_error(tcx, b.trait_ref.path.span, - parameters.lifetimes().len(), 0); - } - continue; // success - } - } - _ => { - // Not a trait? that's an error, but it'll get - // reported later. - } - } trait_bounds.push(b); } hir::TraitTyParamBound(_, hir::TraitBoundModifier::Maybe) => {} @@ -2035,7 +2049,6 @@ pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } PartitionedBounds { - auto_traits: auto_traits, trait_bounds: trait_bounds, region_bounds: region_bounds, } @@ -2110,7 +2123,7 @@ fn report_lifetime_number_error(tcx: TyCtxt, span: Span, number: usize, expected #[derive(PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { pub region_bounds: Vec<&'tcx ty::Region>, - pub auto_traits: Vec, + pub implicitly_sized: bool, pub trait_bounds: Vec>, pub projection_bounds: Vec>, } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 2b69ac12a2c4d..8495c1b3fb8ae 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1584,11 +1584,10 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, assert!(prev_predicates.is_none()); } -// Add the Sized bound, unless the type parameter is marked as `?Sized`. -fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, - bounds: &mut Vec, - ast_bounds: &[hir::TyParamBound], - span: Span) +// Is it marked with ?Sized +fn is_unsized<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, + ast_bounds: &[hir::TyParamBound], + span: Span) -> bool { let tcx = astconv.tcx(); @@ -1621,11 +1620,13 @@ fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, } } _ if kind_id.is_ok() => { - bounds.push(kind_id.unwrap()); + return false; } // No lang item for Sized, so we can't add it as a bound. None => {} } + + true } /// Returns the early-bound lifetimes declared in this generics @@ -1907,14 +1908,9 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, { let tcx = astconv.tcx(); let PartitionedBounds { - mut auto_traits, trait_bounds, region_bounds - } = partition_bounds(tcx, span, &ast_bounds); - - if let SizedByDefault::Yes = sized_by_default { - add_unsized_bound(astconv, &mut auto_traits, ast_bounds, span); - } + } = partition_bounds(&ast_bounds); let mut projection_bounds = vec![]; @@ -1932,9 +1928,15 @@ pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, trait_bounds.sort_by(|a,b| a.def_id().cmp(&b.def_id())); + let implicitly_sized = if let SizedByDefault::Yes = sized_by_default { + !is_unsized(astconv, ast_bounds, span) + } else { + false + }; + Bounds { region_bounds: region_bounds, - auto_traits: auto_traits, + implicitly_sized: implicitly_sized, trait_bounds: trait_bounds, projection_bounds: projection_bounds, } diff --git a/src/test/compile-fail/issue-16966.rs b/src/test/compile-fail/issue-16966.rs index 5dbf7546de224..508442fcb9453 100644 --- a/src/test/compile-fail/issue-16966.rs +++ b/src/test/compile-fail/issue-16966.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// error-pattern:type annotations required +// error-pattern:type annotations or generic parameter binding required fn main() { panic!( std::default::Default::default() From a79c80d0b0f3fa15111ba88fe7260f86ff6df410 Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Fri, 25 Nov 2016 21:21:03 -0700 Subject: [PATCH 6/7] Adds TyCtxt::require_lang_item(LangItem) to simplify lang item requires. Replaces instances of tcx.lang_items.require(..) with fatal unwrap with this method. --- src/librustc/infer/mod.rs | 3 +-- src/librustc/middle/lang_items.rs | 8 ++++++++ src/librustc/traits/select.rs | 3 +-- src/librustc/ty/fast_reject.rs | 6 ++---- src/librustc/ty/mod.rs | 12 ++++-------- src/librustc/ty/util.rs | 8 +++----- src/librustc/ty/wf.rs | 3 +-- .../borrowck/mir/elaborate_drops.rs | 3 +-- src/librustc_mir/build/scope.rs | 3 +-- src/librustc_mir/transform/qualify_consts.rs | 4 +--- src/librustc_typeck/check/cast.rs | 3 +-- src/librustc_typeck/check/mod.rs | 6 ++---- src/librustc_typeck/check/wfcheck.rs | 3 +-- src/librustdoc/clean/mod.rs | 3 +-- 14 files changed, 28 insertions(+), 40 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 9c63eac34e440..72ef987aefd5c 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1493,8 +1493,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - let copy_def_id = self.tcx.lang_items.require(lang_items::CopyTraitLangItem) - .unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..])); + let copy_def_id = self.tcx.require_lang_item(lang_items::CopyTraitLangItem); // this can get called from typeck (by euv), and moves_by_default // rightly refuses to work with inference variables, but diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 8d02d63e3a4bb..1efc211b8c35b 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -356,3 +356,11 @@ language_item_table! { DebugTraitLangItem, "debug_trait", debug_trait; } + +impl<'a, 'tcx, 'gcx> ty::TyCtxt<'a, 'tcx, 'gcx> { + pub fn require_lang_item(&self, lang_item: LangItem) -> DefId { + self.lang_items.require(lang_item).unwrap_or_else(|msg| { + self.sess.fatal(&msg) + }) + } +} diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index a23b021cd4f4a..38a228034dd05 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2521,8 +2521,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // We can only make objects from sized types. let tr = ty::TraitRef { - def_id: tcx.lang_items.require(lang_items::SizedTraitLangItem) - .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])), + def_id: tcx.require_lang_item(lang_items::SizedTraitLangItem), substs: tcx.mk_substs_trait(source, &[]), }; push(tr.to_predicate()); diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 9791ccb101380..ade6cad6866df 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -11,6 +11,7 @@ use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; use syntax::ast; +use middle::lang_items::OwnedBoxLangItem; use self::SimplifiedType::*; @@ -70,10 +71,7 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, } ty::TyBox(_) => { // treat like we would treat `Box` - match tcx.lang_items.require_owned_box() { - Ok(def_id) => Some(AdtSimplifiedType(def_id)), - Err(msg) => tcx.sess.fatal(&msg), - } + Some(AdtSimplifiedType(tcx.require_lang_item(OwnedBoxLangItem))) } ty::TyClosure(def_id, _) => { Some(ClosureSimplifiedType(def_id)) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 86fe14ea504b6..ab8f7d524f44d 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1878,18 +1878,14 @@ pub enum ClosureKind { impl<'a, 'tcx> ClosureKind { pub fn trait_did(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefId { - let result = match *self { - ClosureKind::Fn => tcx.lang_items.require(FnTraitLangItem), + match *self { + ClosureKind::Fn => tcx.require_lang_item(FnTraitLangItem), ClosureKind::FnMut => { - tcx.lang_items.require(FnMutTraitLangItem) + tcx.require_lang_item(FnMutTraitLangItem) } ClosureKind::FnOnce => { - tcx.lang_items.require(FnOnceTraitLangItem) + tcx.require_lang_item(FnOnceTraitLangItem) } - }; - match result { - Ok(trait_did) => trait_did, - Err(err) => tcx.sess.fatal(&err[..]), } } diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index ed9a327750a16..6ba4b8d2da77b 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -646,8 +646,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None }.unwrap_or_else(|| { !self.impls_bound(tcx, param_env, - tcx.lang_items.require(lang_items::CopyTraitLangItem) - .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])), + tcx.require_lang_item(lang_items::CopyTraitLangItem), ¶m_env.is_copy_cache, span) }); if !self.has_param_types() && !self.has_self_ty() { @@ -689,9 +688,8 @@ impl<'a, 'tcx> ty::TyS<'tcx> { TyAdt(..) | TyProjection(..) | TyParam(..) | TyInfer(..) | TyAnon(..) | TyError => None }.unwrap_or_else(|| { - self.impls_bound(tcx, param_env, tcx.lang_items.require(lang_items::SizedTraitLangItem) - .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])), - ¶m_env.is_copy_cache, span) }); + self.impls_bound(tcx, param_env, tcx.require_lang_item(lang_items::SizedTraitLangItem), + ¶m_env.is_sized_cache, span) }); if !self.has_param_types() && !self.has_self_ty() { self.flags.set(self.flags.get() | if result { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 87a0339fff7d2..bab9964651dca 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -283,8 +283,7 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { if !subty.has_escaping_regions() { let cause = self.cause(cause); let trait_ref = ty::TraitRef { - def_id: self.infcx.tcx.lang_items.require(lang_items::SizedTraitLangItem) - .unwrap_or_else(|msg| self.infcx.tcx.sess.fatal(&msg[..])), + def_id: self.infcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), substs: self.infcx.tcx.mk_substs_trait(subty, &[]), }; self.out.push(traits::Obligation::new(cause, trait_ref.to_predicate())); diff --git a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs index cdb19d164bf29..49ef5dd7a1725 100644 --- a/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs +++ b/src/librustc_borrowck/borrowck/mir/elaborate_drops.rs @@ -857,8 +857,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { let tcx = self.tcx; let unit_temp = Lvalue::Local(self.patch.new_temp(tcx.mk_nil())); - let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) - .unwrap_or_else(|e| tcx.sess.fatal(&e)); + let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); let substs = tcx.mk_substs(iter::once(Kind::from(ty))); let fty = tcx.item_type(free_func).subst(tcx, substs); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index e5fac94a8a494..c02a1822d7369 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -783,8 +783,7 @@ fn build_free<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, data: &FreeData<'tcx>, target: BasicBlock) -> TerminatorKind<'tcx> { - let free_func = tcx.lang_items.require(lang_items::BoxFreeFnLangItem) - .unwrap_or_else(|e| tcx.sess.fatal(&e)); + let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); let substs = tcx.intern_substs(&[Kind::from(data.item_ty)]); TerminatorKind::Call { func: Operand::Constant(Constant { diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 9cd92cf1fdcf7..9c6922016e02a 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1048,9 +1048,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { let cause = traits::ObligationCause::new(mir.span, id, traits::SharedStatic); let mut fulfillment_cx = traits::FulfillmentContext::new(); fulfillment_cx.register_bound(&infcx, ty, - tcx.lang_items - .require(lang_items::SyncTraitLangItem) - .unwrap_or_else(|msg| tcx.sess.fatal(&msg[..])), + tcx.require_lang_item(lang_items::SyncTraitLangItem), cause); if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) { infcx.report_fulfillment_errors(&err); diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 5f904f507e272..f2c8ef46a7e25 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -545,8 +545,7 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { fn type_is_known_to_be_sized(&self, ty: Ty<'tcx>, span: Span) -> bool { - let lang_item = self.tcx.lang_items.require(lang_items::SizedTraitLangItem) - .unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..])); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); traits::type_known_to_meet_bound(self, ty, lang_item, span) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bad7b4d96cac6..df3d68d225440 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1819,8 +1819,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { span: Span, code: traits::ObligationCauseCode<'tcx>) { - let lang_item = self.tcx.lang_items.require(lang_items::SizedTraitLangItem) - .unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..])); + let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem); self.require_type_meets(ty, span, code, lang_item); } @@ -3902,8 +3901,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if count > 1 { // For [foo, ..n] where n > 1, `foo` must have // Copy type: - let lang_item = self.tcx.lang_items.require(lang_items::CopyTraitLangItem) - .unwrap_or_else(|msg| self.tcx.sess.fatal(&msg[..])); + let lang_item = self.tcx.require_lang_item(lang_items::CopyTraitLangItem); self.require_type_meets(t, expr.span, traits::RepeatVec, lang_item); } diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index f29965ee47c8f..28aa4b9ef3893 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -238,8 +238,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { for field in &variant.fields[..variant.fields.len() - unsized_len] { fcx.register_bound( field.ty, - fcx.tcx.lang_items.require(lang_items::SizedTraitLangItem) - .unwrap_or_else(|msg| fcx.tcx.sess.fatal(&msg[..])), + fcx.tcx.require_lang_item(lang_items::SizedTraitLangItem), traits::ObligationCause::new(field.span, fcx.body_id, traits::FieldSized)); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b9ba7f732a68e..8d65a5dbc6fcb 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -594,8 +594,7 @@ pub enum TyParamBound { impl TyParamBound { fn maybe_sized(cx: &DocContext) -> TyParamBound { - let did = cx.tcx.lang_items.require(lang_items::SizedTraitLangItem) - .unwrap_or_else(|msg| cx.tcx.sess.fatal(&msg[..])); + let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); let empty = cx.tcx.intern_substs(&[]); let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), false, vec![], empty); From 8b82fd7a94313140d8c745bb8cc647a953e07d9e Mon Sep 17 00:00:00 2001 From: Mark-Simulacrum Date: Fri, 25 Nov 2016 21:54:48 -0700 Subject: [PATCH 7/7] Remove allocation in push_type_params --- src/librustc_trans/trans_item.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index 979c2206fc1de..322c5eb6e182a 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -36,6 +36,7 @@ use glue; use abi::{Abi, FnType}; use back::symbol_names; use std::fmt::Write; +use std::iter; #[derive(PartialEq, Eq, Clone, Copy, Debug, Hash)] pub enum TransItem<'tcx> { @@ -410,7 +411,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { ty::TyFloat(ast::FloatTy::F64) => output.push_str("f64"), ty::TyAdt(adt_def, substs) => { self.push_def_path(adt_def.did, output); - self.push_type_params(substs, &[], output); + self.push_type_params(substs, iter::empty(), output); }, ty::TyTuple(component_types) => { output.push('('); @@ -461,7 +462,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { if let Some(principal) = trait_data.principal() { self.push_def_path(principal.def_id(), output); self.push_type_params(principal.skip_binder().substs, - &trait_data.projection_bounds().collect::>()[..], + trait_data.projection_bounds(), output); } }, @@ -513,7 +514,7 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { self.push_def_path(def_id, output); let generics = self.tcx.item_generics(self.tcx.closure_base_def_id(def_id)); let substs = closure_substs.substs.truncate_to(self.tcx, generics); - self.push_type_params(substs, &[], output); + self.push_type_params(substs, iter::empty(), output); } ty::TyError | ty::TyInfer(_) | @@ -553,11 +554,14 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { output.pop(); } - pub fn push_type_params(&self, + fn push_type_params(&self, substs: &Substs<'tcx>, - projections: &[ty::PolyExistentialProjection<'tcx>], - output: &mut String) { - if substs.types().next().is_none() && projections.is_empty() { + projections: I, + output: &mut String) + where I: Iterator> + { + let mut projections = projections.peekable(); + if substs.types().next().is_none() && projections.peek().is_none() { return; } @@ -587,6 +591,6 @@ impl<'a, 'tcx> DefPathBasedNames<'a, 'tcx> { instance: Instance<'tcx>, output: &mut String) { self.push_def_path(instance.def, output); - self.push_type_params(instance.substs, &[], output); + self.push_type_params(instance.substs, iter::empty(), output); } }