From 6f5e455c2de007a12ed632f84b986369ae43a504 Mon Sep 17 00:00:00 2001 From: Eduard Burtescu Date: Thu, 11 Aug 2016 09:19:42 +0300 Subject: [PATCH] rustc: split GenericPredicates of a method from its parent predicates. --- src/librustc/traits/select.rs | 26 ++- src/librustc/ty/mod.rs | 25 ++- src/librustc/ty/structural_impls.rs | 12 -- src/librustc_metadata/decoder.rs | 1 + src/librustc_metadata/encoder.rs | 3 + src/librustc_typeck/astconv.rs | 1 + src/librustc_typeck/check/compare_method.rs | 30 ++-- src/librustc_typeck/check/dropck.rs | 1 + src/librustc_typeck/check/mod.rs | 12 +- src/librustc_typeck/check/regionck.rs | 1 + src/librustc_typeck/check/wfcheck.rs | 1 + src/librustc_typeck/collect.rs | 158 +++++++++--------- src/librustdoc/clean/mod.rs | 12 +- .../associated-const-type-parameter-arrays.rs | 3 +- 14 files changed, 136 insertions(+), 150 deletions(-) diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 9099d6cd740..bf6aad98db1 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -2897,20 +2897,18 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // obligation will normalize to `<$0 as Iterator>::Item = $1` and // `$1: Copy`, so we must ensure the obligations are emitted in // that order. - let predicates = tcx - .lookup_predicates(def_id) - .predicates.iter() - .flat_map(|predicate| { - let predicate = - normalize_with_depth(self, cause.clone(), recursion_depth, - &predicate.subst(tcx, substs)); - predicate.obligations.into_iter().chain( - Some(Obligation { - cause: cause.clone(), - recursion_depth: recursion_depth, - predicate: predicate.value - })) - }).collect(); + let predicates = tcx.lookup_predicates(def_id); + assert_eq!(predicates.parent, None); + let predicates = predicates.predicates.iter().flat_map(|predicate| { + let predicate = normalize_with_depth(self, cause.clone(), recursion_depth, + &predicate.subst(tcx, substs)); + predicate.obligations.into_iter().chain( + Some(Obligation { + cause: cause.clone(), + recursion_depth: recursion_depth, + predicate: predicate.value + })) + }).collect(); self.infcx().plug_leaks(skol_map, snapshot, &predicates) } } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 689f2ad02c9..b2b8286be2f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -768,27 +768,38 @@ pub struct Generics<'tcx> { /// Bounds on generics. #[derive(Clone)] pub struct GenericPredicates<'tcx> { + pub parent: Option, pub predicates: Vec>, } impl<'a, 'gcx, 'tcx> GenericPredicates<'tcx> { - pub fn empty() -> GenericPredicates<'tcx> { - GenericPredicates { - predicates: vec![] + pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) + -> InstantiatedPredicates<'tcx> { + let mut instantiated = InstantiatedPredicates::empty(); + self.instantiate_into(tcx, &mut instantiated, substs); + instantiated + } + pub fn instantiate_own(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) + -> InstantiatedPredicates<'tcx> { + InstantiatedPredicates { + predicates: self.predicates.subst(tcx, substs) } } - pub fn instantiate(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, substs: &Substs<'tcx>) - -> InstantiatedPredicates<'tcx> { - InstantiatedPredicates { - predicates: self.predicates.subst(tcx, substs), + fn instantiate_into(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, + instantiated: &mut InstantiatedPredicates<'tcx>, + substs: &Substs<'tcx>) { + if let Some(def_id) = self.parent { + tcx.lookup_predicates(def_id).instantiate_into(tcx, instantiated, substs); } + instantiated.predicates.extend(self.predicates.iter().map(|p| p.subst(tcx, substs))) } pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, poly_trait_ref: &ty::PolyTraitRef<'tcx>) -> InstantiatedPredicates<'tcx> { + assert_eq!(self.parent, None); InstantiatedPredicates { predicates: self.predicates.iter().map(|pred| { pred.subst_supertrait(tcx, poly_trait_ref) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 248d5d9062d..021ae820b87 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -832,18 +832,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef { } } -impl<'tcx> TypeFoldable<'tcx> for ty::GenericPredicates<'tcx> { - fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - ty::GenericPredicates { - predicates: self.predicates.fold_with(folder), - } - } - - fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.predicates.visit_with(visitor) - } -} - impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { match *self { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index e42825ef1e5..5488f114db3 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1591,6 +1591,7 @@ fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, let doc = reader::get_doc(base_doc, tag); ty::GenericPredicates { + parent: item_parent_item(cdata, doc), predicates: reader::tagged_docs(doc, tag_predicate).map(|predicate_doc| { doc_predicate(cdata, predicate_doc, tcx) }).collect() diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0cde9b48d6f..320ba3c8d9d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -525,6 +525,9 @@ fn encode_predicates<'a,'tcx>(rbml_w: &mut Encoder, tag: usize) { rbml_w.start_tag(tag); + if let Some(def_id) = predicates.parent { + rbml_w.wr_tagged_u64(tag_items_data_parent_item, def_to_u64(def_id)); + } for predicate in &predicates.predicates { rbml_w.wr_tagged_u32(tag_predicate, index.add_xref(XRef::Predicate(predicate.clone()))); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index a452b55a7d3..aec8f8245da 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -1726,6 +1726,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let predicates = bounds.predicates(tcx, ty); let predicates = tcx.lift_to_global(&predicates).unwrap(); tcx.predicates.borrow_mut().insert(def_id, ty::GenericPredicates { + parent: None, predicates: predicates }); diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 5bfe58e78f1..4cbb2d7f09f 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -211,29 +211,18 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return; } - // Depend on trait/impl predicates always being before method's own predicates, - // to be able to split method predicates into "inherited" and method-specific. - let trait_predicates = tcx.lookup_predicates(trait_m.container_id()).predicates; - let impl_predicates = tcx.lookup_predicates(impl_m.container_id()).predicates; - let trait_method_start = trait_predicates.len(); - let impl_method_start = impl_predicates.len(); - assert_eq!(&trait_predicates[..], &trait_m.predicates.predicates[..trait_method_start]); - assert_eq!(&impl_predicates[..], &impl_m.predicates.predicates[..impl_method_start]); - tcx.infer_ctxt(None, None, Reveal::NotSpecializable).enter(|mut infcx| { let mut fulfillment_cx = traits::FulfillmentContext::new(); - // Normalize the associated types in the trait_bounds. - let trait_bounds = trait_m.predicates.instantiate(tcx, trait_to_skol_substs); - // Create obligations for each predicate declared by the impl // definition in the context of the trait's parameter // environment. We can't just use `impl_env.caller_bounds`, // however, because we want to replace all late-bound regions with // region variables. - let impl_bounds = impl_m.predicates.instantiate(tcx, impl_to_skol_substs); + let impl_predicates = tcx.lookup_predicates(impl_m.predicates.parent.unwrap()); + let mut hybrid_preds = impl_predicates.instantiate(tcx, impl_to_skol_substs); - debug!("compare_impl_method: impl_bounds={:?}", impl_bounds); + debug!("compare_impl_method: impl_bounds={:?}", hybrid_preds); // This is the only tricky bit of the new way we check implementation methods // We need to build a set of predicates where only the FnSpace bounds @@ -242,14 +231,14 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, // // We then register the obligations from the impl_m and check to see // if all constraints hold. - let hybrid_preds = impl_bounds.predicates[..impl_method_start].iter() - .chain(trait_bounds.predicates[trait_method_start..].iter()); + hybrid_preds.predicates.extend( + trait_m.predicates.instantiate_own(tcx, trait_to_skol_substs).predicates); // Construct trait parameter environment and then shift it into the skolemized viewpoint. // The key step here is to update the caller_bounds's predicates to be // the new hybrid bounds we computed. let normalize_cause = traits::ObligationCause::misc(impl_m_span, impl_m_body_id); - let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.cloned().collect()); + let trait_param_env = impl_param_env.with_caller_bounds(hybrid_preds.predicates); let trait_param_env = traits::normalize_param_env_or_error(tcx, trait_param_env, normalize_cause.clone()); @@ -261,12 +250,13 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let mut selcx = traits::SelectionContext::new(&infcx); - let (impl_pred_fns, _) = + let impl_m_own_bounds = impl_m.predicates.instantiate_own(tcx, impl_to_skol_substs); + let (impl_m_own_bounds, _) = infcx.replace_late_bound_regions_with_fresh_var( impl_m_span, infer::HigherRankedType, - &ty::Binder(impl_bounds.predicates[impl_method_start..].to_vec())); - for predicate in impl_pred_fns { + &ty::Binder(impl_m_own_bounds.predicates)); + for predicate in impl_m_own_bounds { let traits::Normalized { value: predicate, .. } = traits::normalize(&mut selcx, normalize_cause.clone(), &predicate); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 7d79fc4fbf8..d1da95f39df 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -184,6 +184,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>( // 'a:'b and T:'b into region inference constraints. It is simpler // just to look for all the predicates directly. + assert_eq!(dtor_predicates.parent, None); for predicate in &dtor_predicates.predicates { // (We do not need to worry about deep analysis of type // expressions etc because the Drop impls are already forced diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index d699bafed9a..8c4ec845317 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1612,8 +1612,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { bounds: &ty::GenericPredicates<'tcx>) -> ty::InstantiatedPredicates<'tcx> { + let result = bounds.instantiate(self.tcx, substs); + let result = self.normalize_associated_types_in(span, &result.predicates); + debug!("instantiate_bounds(bounds={:?}, substs={:?}) = {:?}", + bounds, + substs, + result); ty::InstantiatedPredicates { - predicates: self.instantiate_type_scheme(span, substs, &bounds.predicates) + predicates: result } } @@ -4210,8 +4216,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } _ => {} } - let scheme = self.tcx.lookup_item_type(def.def_id()); - let type_predicates = self.tcx.lookup_predicates(def.def_id()); // Now we have to compare the types that the user *actually* // provided against the types that were *expected*. If the user @@ -4296,6 +4300,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // The things we are substituting into the type should not contain // escaping late-bound regions, and nor should the base type scheme. + let scheme = self.tcx.lookup_item_type(def.def_id()); + let type_predicates = self.tcx.lookup_predicates(def.def_id()); assert!(!substs.has_escaping_regions()); assert!(!scheme.ty.has_escaping_regions()); diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 8e34b0b8c55..f6ffbc60c28 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -1754,6 +1754,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // // we can thus deduce that `>::SomeType : 'a`. let trait_predicates = self.tcx.lookup_predicates(projection_ty.trait_ref.def_id); + assert_eq!(trait_predicates.parent, None); let predicates = trait_predicates.predicates.as_slice().to_vec(); traits::elaborate_predicates(self.tcx, predicates) .filter_map(|predicate| { diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index f793ce7acb7..ef5e1a26f41 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -454,6 +454,7 @@ impl<'ccx, 'gcx> CheckTypeWellFormedVisitor<'ccx, 'gcx> { let item_def_id = self.tcx().map.local_def_id(item.id); let ty_predicates = self.tcx().lookup_predicates(item_def_id); + assert_eq!(ty_predicates.parent, None); let variances = self.tcx().item_variances(item_def_id); let mut constrained_parameters: HashSet<_> = diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 9e8fe710cc1..939f8ac50a6 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -459,35 +459,38 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for () { impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> { fn get_type_parameter_bounds(&self, astconv: &AstConv<'tcx, 'tcx>, - _span: Span, + span: Span, node_id: ast::NodeId) -> Vec> { let def = astconv.tcx().type_parameter_def(node_id); - self.predicates - .iter() - .filter(|predicate| { - match **predicate { - ty::Predicate::Trait(ref data) => { - data.skip_binder().self_ty().is_param(def.space, def.index) - } - ty::Predicate::TypeOutlives(ref data) => { - data.skip_binder().0.is_param(def.space, def.index) - } - ty::Predicate::Rfc1592(..) | - ty::Predicate::Equate(..) | - ty::Predicate::RegionOutlives(..) | - ty::Predicate::WellFormed(..) | - ty::Predicate::ObjectSafe(..) | - ty::Predicate::ClosureKind(..) | - ty::Predicate::Projection(..) => { - false - } + let mut results = self.parent.map_or(vec![], |def_id| { + let parent = astconv.tcx().lookup_predicates(def_id); + parent.get_type_parameter_bounds(astconv, span, node_id) + }); + + results.extend(self.predicates.iter().filter(|predicate| { + match **predicate { + ty::Predicate::Trait(ref data) => { + data.skip_binder().self_ty().is_param(def.space, def.index) } - }) - .cloned() - .collect() + ty::Predicate::TypeOutlives(ref data) => { + data.skip_binder().0.is_param(def.space, def.index) + } + ty::Predicate::Rfc1592(..) | + ty::Predicate::Equate(..) | + ty::Predicate::RegionOutlives(..) | + ty::Predicate::WellFormed(..) | + ty::Predicate::ObjectSafe(..) | + ty::Predicate::ClosureKind(..) | + ty::Predicate::Projection(..) => { + false + } + } + }).cloned()); + + results } } @@ -568,7 +571,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let ty_generics = generics_of_def_id(ccx, def_id); let ty_generic_predicates = - ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates); + ty_generic_predicates(ccx, FnSpace, &sig.generics, ty_generics.parent, vec![], false); let (fty, explicit_self_category) = { let anon_scope = match container { @@ -634,8 +637,12 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ty: ty::Ty<'tcx>, has_value: bool) { + let predicates = ty::GenericPredicates { + parent: Some(container.id()), + predicates: vec![] + }; ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id), - ty::GenericPredicates::empty()); + predicates); write_ty_to_tcx(ccx, id, ty); @@ -744,7 +751,8 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) { debug!("convert: ast_generics={:?}", generics); let def_id = ccx.tcx.map.local_def_id(it.id); let ty_generics = generics_of_def_id(ccx, def_id); - let mut ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics); + let mut ty_predicates = + ty_generic_predicates(ccx, TypeSpace, generics, None, vec![], false); debug!("convert: impl_bounds={:?}", ty_predicates); @@ -1187,6 +1195,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // generic types: let trait_def = trait_def_of_item(ccx, item); let self_predicate = ty::GenericPredicates { + parent: None, predicates: vec![trait_def.trait_ref.to_predicate()] }; let scope = &(generics, &self_predicate); @@ -1209,6 +1218,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt, // Combine the two lists to form the complete set of superbounds: let superbounds = superbounds1.into_iter().chain(superbounds2).collect(); let superpredicates = ty::GenericPredicates { + parent: None, predicates: superbounds }; debug!("superpredicates for trait {:?} = {:?}", @@ -1327,16 +1337,16 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) // but to get the full set of predicates on a trait we need to add // in the supertrait bounds and anything declared on the // associated types. - let mut base_predicates = super_predicates; + let mut base_predicates = super_predicates.predicates; // Add in a predicate that `Self:Trait` (where `Trait` is the // current trait). This is needed for builtin bounds. let self_predicate = trait_def.trait_ref.to_poly_trait_ref().to_predicate(); - base_predicates.predicates.push(self_predicate); + base_predicates.push(self_predicate); // add in the explicit where-clauses let mut trait_predicates = - ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates, true); + ty_generic_predicates(ccx, TypeSpace, generics, None, base_predicates, true); let assoc_predicates = predicates_for_associated_types(ccx, generics, @@ -1619,32 +1629,17 @@ fn predicates_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &hir::Item) -> ty::GenericPredicates<'tcx> { let def_id = ccx.tcx.map.local_def_id(it.id); - let predicates = match it.node { - hir::ItemStatic(..) | hir::ItemConst(..) => { - ty::GenericPredicates::empty() - } - hir::ItemFn(_, _, _, _, ref ast_generics, _) => { - ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty()) - } + + let no_generics = hir::Generics::empty(); + let (space, generics) = match it.node { + hir::ItemFn(_, _, _, _, ref generics, _) => (FnSpace, generics), hir::ItemTy(_, ref generics) | hir::ItemEnum(_, ref generics) | - hir::ItemStruct(_, ref generics) => { - ty_generic_predicates_for_type_or_impl(ccx, generics) - } - hir::ItemDefaultImpl(..) | - hir::ItemTrait(..) | - hir::ItemExternCrate(..) | - hir::ItemUse(..) | - hir::ItemImpl(..) | - hir::ItemMod(..) | - hir::ItemForeignMod(..) => { - span_bug!( - it.span, - "predicates_of_item: unexpected item type: {:?}", - it.node); - } + hir::ItemStruct(_, ref generics) => (TypeSpace, generics), + _ => (TypeSpace, &no_generics) }; + let predicates = ty_generic_predicates(ccx, space, generics, None, vec![], false); let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates.clone()); assert!(prev_predicates.is_none()); @@ -1662,34 +1657,17 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let def_id = ccx.tcx.map.local_def_id(it.id); type_scheme_of_def_id(ccx, def_id); - let predicates = match it.node { - hir::ForeignItemFn(_, ref generics) => { - ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty()) - } - hir::ForeignItemStatic(..) => { - ty::GenericPredicates::empty() - } + let no_generics = hir::Generics::empty(); + let (space, generics) = match it.node { + hir::ForeignItemFn(_, ref generics) => (FnSpace, generics), + hir::ForeignItemStatic(..) => (TypeSpace, &no_generics) }; + let predicates = ty_generic_predicates(ccx, space, generics, None, vec![], false); let prev_predicates = ccx.tcx.predicates.borrow_mut().insert(def_id, predicates); assert!(prev_predicates.is_none()); } -fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - generics: &hir::Generics) - -> ty::GenericPredicates<'tcx> -{ - ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty(), false) -} - -fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, - generics: &hir::Generics, - base_predicates: &ty::GenericPredicates<'tcx>) - -> ty::GenericPredicates<'tcx> -{ - ty_generic_predicates(ccx, FnSpace, generics, base_predicates, false) -} - // 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, @@ -1757,12 +1735,25 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx, 'hir>( fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, space: ParamSpace, ast_generics: &hir::Generics, - base_predicates: &ty::GenericPredicates<'tcx>, + parent: Option, + super_predicates: Vec>, has_self: bool) -> ty::GenericPredicates<'tcx> { let tcx = ccx.tcx; - let mut result = base_predicates.clone(); + let ref base_predicates = match parent { + Some(def_id) => { + assert_eq!(super_predicates, vec![]); + tcx.lookup_predicates(def_id) + } + None => { + ty::GenericPredicates { + parent: None, + predicates: super_predicates.clone() + } + } + }; + let mut predicates = super_predicates; // Collect the predicates that were written inline by the user on each // type parameter (e.g., ``). @@ -1775,7 +1766,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, SizedByDefault::Yes, None, param.span); - result.predicates.extend(bounds.predicates(ccx.tcx, param_ty)); + predicates.extend(bounds.predicates(ccx.tcx, param_ty)); } // Collect the region predicates that were declared inline as @@ -1793,7 +1784,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for bound in ¶m.bounds { let bound_region = ast_region_to_region(ccx.tcx, bound); let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region)); - result.predicates.push(outlives.to_predicate()); + predicates.push(outlives.to_predicate()); } } @@ -1819,17 +1810,17 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, ty, &mut projections); - result.predicates.push(trait_ref.to_predicate()); + predicates.push(trait_ref.to_predicate()); for projection in &projections { - result.predicates.push(projection.to_predicate()); + predicates.push(projection.to_predicate()); } } &hir::TyParamBound::RegionTyParamBound(ref lifetime) => { let region = ast_region_to_region(tcx, lifetime); let pred = ty::Binder(ty::OutlivesPredicate(ty, region)); - result.predicates.push(ty::Predicate::TypeOutlives(pred)) + predicates.push(ty::Predicate::TypeOutlives(pred)) } } } @@ -1840,7 +1831,7 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, for bound in ®ion_pred.bounds { let r2 = ast_region_to_region(tcx, bound); let pred = ty::Binder(ty::OutlivesPredicate(r1, r2)); - result.predicates.push(ty::Predicate::RegionOutlives(pred)) + predicates.push(ty::Predicate::RegionOutlives(pred)) } } @@ -1853,7 +1844,10 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } } - result + ty::GenericPredicates { + parent: parent, + predicates: predicates + } } fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 07821a730cc..90288b17dfc 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1348,17 +1348,7 @@ impl Clean for hir::ImplItem { impl<'tcx> Clean for ty::Method<'tcx> { fn clean(&self, cx: &DocContext) -> Item { - // Depend on trait/impl predicates always being before method's own predicates, - // to be able to split method predicates into "inherited" and method-specific. - let outer_predicates = cx.tcx().lookup_predicates(self.container_id()).predicates; - let method_start = outer_predicates.len(); - assert_eq!(&outer_predicates[..], &self.predicates.predicates[..method_start]); - - let method_predicates = ty::GenericPredicates { - predicates: self.predicates.predicates[method_start..].to_vec() - }; - - let generics = (self.generics, &method_predicates).clean(cx); + let generics = (self.generics, &self.predicates).clean(cx); let mut decl = (self.def_id, &self.fty.sig).clean(cx); match self.explicit_self { ty::ExplicitSelfCategory::ByValue => { diff --git a/src/test/compile-fail/associated-const-type-parameter-arrays.rs b/src/test/compile-fail/associated-const-type-parameter-arrays.rs index 3d3b795b229..ddf16a2278e 100644 --- a/src/test/compile-fail/associated-const-type-parameter-arrays.rs +++ b/src/test/compile-fail/associated-const-type-parameter-arrays.rs @@ -25,7 +25,8 @@ impl Foo for Def { } pub fn test() { - let _array: [u32; ::Y]; //~ error: the parameter type + let _array: [u32; ::Y]; + //~^ ERROR the trait bound `A: Foo` is not satisfied } fn main() {