diff --git a/frontend/exporter/src/traits.rs b/frontend/exporter/src/traits.rs index 1ba78515d..9b3175489 100644 --- a/frontend/exporter/src/traits.rs +++ b/frontend/exporter/src/traits.rs @@ -206,13 +206,15 @@ pub fn solve_item_implied_traits<'tcx, S: UnderOwnerState<'tcx>>( fn solve_item_traits_inner<'tcx, S: UnderOwnerState<'tcx>>( s: &S, generics: ty::GenericArgsRef<'tcx>, - predicates: impl Iterator>, + predicates: ty::GenericPredicates<'tcx>, ) -> Vec { use crate::rustc_middle::ty::ToPolyTraitRef; let tcx = s.base().tcx; let param_env = s.param_env(); - predicates + .predicates + .iter() + .map(|(clause, _span)| *clause) .filter_map(|clause| clause.as_trait_clause()) .map(|clause| clause.to_poly_trait_ref()) // Substitute the item generics @@ -239,7 +241,7 @@ pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>( let tr_def_id = tcx.trait_of_item(assoc.def_id)?; // The "self" predicate in the context of the trait. - let self_pred = self_predicate(tcx, tr_def_id).unwrap(); + let self_pred = self_predicate(tcx, tr_def_id); // Substitute to be in the context of the current item. let generics = generics.truncate_to(tcx, tcx.generics_of(tr_def_id)); let self_pred = EarlyBinder::bind(self_pred).instantiate(tcx, generics); diff --git a/frontend/exporter/src/traits/resolution.rs b/frontend/exporter/src/traits/resolution.rs index 53379a6a5..cc5377161 100644 --- a/frontend/exporter/src/traits/resolution.rs +++ b/frontend/exporter/src/traits/resolution.rs @@ -118,6 +118,11 @@ fn initial_search_predicates<'tcx>( predicates: &mut Vec>, pred_id: &mut usize, ) { + let next_item_origin = |pred_id: &mut usize| { + let origin = BoundPredicateOrigin::Item(*pred_id); + *pred_id += 1; + origin + }; use DefKind::*; match tcx.def_kind(def_id) { // These inherit some predicates from their parent. @@ -126,7 +131,7 @@ fn initial_search_predicates<'tcx>( acc_predicates(tcx, parent, predicates, pred_id); } Trait => { - let self_pred = self_predicate(tcx, def_id).unwrap().upcast(tcx); + let self_pred = self_predicate(tcx, def_id).upcast(tcx); predicates.push(AnnotatedTraitPred { origin: BoundPredicateOrigin::SelfPred, clause: self_pred, @@ -134,16 +139,18 @@ fn initial_search_predicates<'tcx>( } _ => {} } - predicates.extend(required_predicates(tcx, def_id).filter_map(|clause| { - clause.as_trait_clause().map(|clause| { - let id = *pred_id; - *pred_id += 1; - AnnotatedTraitPred { - origin: BoundPredicateOrigin::Item(id), - clause, - } - }) - })); + predicates.extend( + required_predicates(tcx, def_id) + .predicates + .iter() + .map(|(clause, _span)| *clause) + .filter_map(|clause| { + clause.as_trait_clause().map(|clause| AnnotatedTraitPred { + origin: next_item_origin(pred_id), + clause, + }) + }), + ); } let mut predicates = vec![]; @@ -158,6 +165,9 @@ fn parents_trait_predicates<'tcx>( ) -> Vec> { let self_trait_ref = pred.to_poly_trait_ref(); implied_predicates(tcx, pred.def_id()) + .predicates + .iter() + .map(|(clause, _span)| *clause) // Substitute with the `self` args so that the clause makes sense in the // outside context. .map(|clause| clause.instantiate_supertrait(tcx, self_trait_ref)) @@ -270,6 +280,9 @@ impl<'tcx> PredicateSearcher<'tcx> { // The bounds that hold on the associated type. let item_bounds = implied_predicates(tcx, alias_ty.def_id) + .predicates + .iter() + .map(|(clause, _span)| *clause) .filter_map(|pred| pred.as_trait_clause()) // Substitute the item generics .map(|pred| EarlyBinder::bind(pred).instantiate(tcx, alias_ty.args)) @@ -425,6 +438,9 @@ impl<'tcx> PredicateSearcher<'tcx> { ) -> Result>, String> { let tcx = self.tcx; required_predicates(tcx, def_id) + .predicates + .iter() + .map(|(clause, _span)| *clause) .filter_map(|clause| clause.as_trait_clause()) .map(|trait_pred| trait_pred.map_bound(|p| p.trait_ref)) // Substitute the item generics diff --git a/frontend/exporter/src/traits/utils.rs b/frontend/exporter/src/traits/utils.rs index 202915236..235a36df7 100644 --- a/frontend/exporter/src/traits/utils.rs +++ b/frontend/exporter/src/traits/utils.rs @@ -51,10 +51,7 @@ pub fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> GenericPredicate } /// The predicates that must hold to mention this item. -pub fn required_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, -) -> impl Iterator> + DoubleEndedIterator { +pub fn required_predicates<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> GenericPredicates<'tcx> { use DefKind::*; match tcx.def_kind(def_id) { AssocConst @@ -70,58 +67,42 @@ pub fn required_predicates<'tcx>( | Struct | TraitAlias | TyAlias - | Union => Some( - predicates_defined_on(tcx, def_id) - .predicates - .iter() - .map(|(clause, _span)| *clause), - ), + | Union => predicates_defined_on(tcx, def_id), // The tuple struct/variant constructor functions inherit the generics and predicates from // their parents. Variant | Ctor(..) => return required_predicates(tcx, tcx.parent(def_id)), // We consider all predicates on traits to be outputs - Trait => None, + Trait => Default::default(), // `predicates_defined_on` ICEs on other def kinds. - _ => None, + _ => Default::default(), } - .into_iter() - .flatten() } /// The special "self" predicate on a trait. -pub fn self_predicate<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option> { - use DefKind::*; - match tcx.def_kind(def_id) { - // Copied from the code of `tcx.predicates_of()`. - Trait => Some(Binder::dummy(TraitRef::identity(tcx, def_id))), - _ => None, - } +pub fn self_predicate<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> PolyTraitRef<'tcx> { + // Copied from the code of `tcx.predicates_of()`. + Binder::dummy(TraitRef::identity(tcx, def_id)) } /// The predicates that can be deduced from the presence of this item in a signature. We only /// consider predicates implied by traits here, not implied bounds such as `&'a T` implying `T: /// 'a`. -pub fn implied_predicates<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: DefId, -) -> impl Iterator> + DoubleEndedIterator { +pub fn implied_predicates<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> GenericPredicates<'tcx> { use DefKind::*; + let parent = tcx.opt_parent(def_id); match tcx.def_kind(def_id) { // We consider all predicates on traits to be outputs - Trait => predicates_defined_on(tcx, def_id) - .predicates - .iter() - .map(|(clause, _span)| *clause) - .collect::>(), - AssocTy => tcx - // TODO: `item_bounds` contains parent traits, use `explicit_item_bounds` instead. - .item_bounds(def_id) - .instantiate_identity() - .iter() - .collect(), - _ => vec![], + Trait => predicates_defined_on(tcx, def_id), + AssocTy if matches!(tcx.def_kind(parent.unwrap()), Trait) => { + GenericPredicates { + parent, + // `skip_binder` is for an `EarlyBinder` + predicates: tcx.explicit_item_bounds(def_id).skip_binder(), + ..GenericPredicates::default() + } + } + _ => GenericPredicates::default(), } - .into_iter() } /// Erase all regions. Largely copied from `tcx.erase_regions`. diff --git a/frontend/exporter/src/types/new/full_def.rs b/frontend/exporter/src/types/new/full_def.rs index 4473fa76c..b432c687f 100644 --- a/frontend/exporter/src/types/new/full_def.rs +++ b/frontend/exporter/src/types/new/full_def.rs @@ -97,7 +97,7 @@ pub enum FullDefKind { Struct { #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_required_predicates(s, s.owner_id()))] predicates: GenericPredicates, #[value(s.base().tcx.adt_def(s.owner_id()).sinto(s))] def: AdtDef, @@ -105,7 +105,7 @@ pub enum FullDefKind { Union { #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_required_predicates(s, s.owner_id()))] predicates: GenericPredicates, #[value(s.base().tcx.adt_def(s.owner_id()).sinto(s))] def: AdtDef, @@ -113,7 +113,7 @@ pub enum FullDefKind { Enum { #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_required_predicates(s, s.owner_id()))] predicates: GenericPredicates, #[value(s.base().tcx.adt_def(s.owner_id()).sinto(s))] def: AdtDef, @@ -122,7 +122,7 @@ pub enum FullDefKind { TyAlias { #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_required_predicates(s, s.owner_id()))] predicates: GenericPredicates, /// `Some` if the item is in the local crate. #[value(s.base().tcx.hir().get_if_local(s.owner_id()).map(|node| { @@ -142,7 +142,7 @@ pub enum FullDefKind { parent: DefId, #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_item_predicates(s, s.owner_id()))] + #[value(normalized_implied_predicates(s, s.owner_id()))] // FIXME: clarify implied vs required predicates predicates: GenericPredicates, #[value(s.base().tcx.associated_item(s.owner_id()).sinto(s))] @@ -164,7 +164,7 @@ pub enum FullDefKind { Trait { #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_implied_predicates(s, s.owner_id()))] predicates: GenericPredicates, /// The special `Self: Trait` clause. #[value({ @@ -172,7 +172,6 @@ pub enum FullDefKind { let tcx = s.base().tcx; let pred: ty::TraitPredicate = crate::traits::self_predicate(tcx, s.owner_id()) - .unwrap() .no_bound_vars() .unwrap() .upcast(tcx); @@ -226,7 +225,7 @@ pub enum FullDefKind { Fn { #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_required_predicates(s, s.owner_id()))] predicates: GenericPredicates, #[value(s.base().tcx.codegen_fn_attrs(s.owner_id()).inline.sinto(s))] inline: InlineAttr, @@ -246,7 +245,7 @@ pub enum FullDefKind { associated_item: AssocItem, #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_required_predicates(s, s.owner_id()))] predicates: GenericPredicates, #[value(s.base().tcx.codegen_fn_attrs(s.owner_id()).inline.sinto(s))] inline: InlineAttr, @@ -281,7 +280,7 @@ pub enum FullDefKind { Const { #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_required_predicates(s, s.owner_id()))] predicates: GenericPredicates, #[value(s.base().tcx.type_of(s.owner_id()).instantiate_identity().sinto(s))] ty: Ty, @@ -296,7 +295,7 @@ pub enum FullDefKind { associated_item: AssocItem, #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_required_predicates(s, s.owner_id()))] predicates: GenericPredicates, #[value(s.base().tcx.type_of(s.owner_id()).instantiate_identity().sinto(s))] ty: Ty, @@ -316,7 +315,7 @@ pub enum FullDefKind { nested: bool, #[value(s.base().tcx.generics_of(s.owner_id()).sinto(s))] generics: TyGenerics, - #[value(get_generic_predicates(s, s.owner_id()))] + #[value(normalized_required_predicates(s, s.owner_id()))] predicates: GenericPredicates, #[value(s.base().tcx.type_of(s.owner_id()).instantiate_identity().sinto(s))] ty: Ty, @@ -662,7 +661,7 @@ where let tcx = s.base().tcx; let impl_def_id = s.owner_id(); let generics = tcx.generics_of(impl_def_id).sinto(s); - let predicates = get_generic_predicates(s, impl_def_id); + let predicates = normalized_required_predicates(s, impl_def_id); match tcx.impl_subject(impl_def_id).instantiate_identity() { ty::ImplSubject::Inherent(ty) => { let items = tcx @@ -866,9 +865,10 @@ where #[cfg(feature = "rustc")] fn normalize_trait_clauses<'tcx, S: UnderOwnerState<'tcx>>( s: &S, - predicates: &[(ty::Clause<'tcx>, rustc_span::Span)], -) -> Vec<(Predicate, Span)> { - let predicates: Vec<_> = predicates + predicates: ty::GenericPredicates<'tcx>, +) -> GenericPredicates { + let clauses: Vec<_> = predicates + .predicates .iter() .map(|(clause, span)| { let mut clause = *clause; @@ -882,46 +882,30 @@ fn normalize_trait_clauses<'tcx, S: UnderOwnerState<'tcx>>( (clause.as_predicate(), *span) }) .collect(); - predicates.sinto(s) + GenericPredicates { + parent: predicates.parent.sinto(s), + predicates: clauses.sinto(s), + } } -/// Gets the `predicates_defined_on` the given `DefId` and processes them with +/// Get the `required_predicates` for the given `def_id` and process them with /// `normalize_trait_clauses`. #[cfg(feature = "rustc")] -fn get_generic_predicates<'tcx, S: UnderOwnerState<'tcx>>( +fn normalized_required_predicates<'tcx, S: UnderOwnerState<'tcx>>( s: &S, def_id: RDefId, ) -> GenericPredicates { - let predicates = predicates_defined_on(s.base().tcx, def_id); - let pred_list = normalize_trait_clauses(s, predicates.predicates); - GenericPredicates { - parent: predicates.parent.sinto(s), - predicates: pred_list, - } + let tcx = s.base().tcx; + normalize_trait_clauses(s, required_predicates(tcx, def_id)) } -/// Gets the predicates defined on the given associated type and processes them with +/// Get the `implied_predicates` for the given `def_id` and process them with /// `normalize_trait_clauses`. #[cfg(feature = "rustc")] -fn get_item_predicates<'tcx, S: UnderOwnerState<'tcx>>(s: &S, def_id: RDefId) -> GenericPredicates { +fn normalized_implied_predicates<'tcx, S: UnderOwnerState<'tcx>>( + s: &S, + def_id: RDefId, +) -> GenericPredicates { let tcx = s.base().tcx; - let parent_id = tcx.parent(def_id); - // `item_bounds` cannot be called on a trait impl item, and returns empty on an inherent impl - // item. So we only call it for trait decl items. - let predicates = match tcx.def_kind(parent_id) { - rustc_hir::def::DefKind::Trait => { - // TODO: we probably want to use `explicit_item_bounds` instead, but should do so - // consistently. - let clauses = tcx.item_bounds(def_id).instantiate_identity(); - use crate::rustc_middle::query::Key; - let span = clauses.default_span(tcx); - clauses.iter().map(|c| (c, span)).collect::>() - } - _ => Vec::new(), - }; - let predicates = normalize_trait_clauses(s, predicates.as_slice()); - GenericPredicates { - parent: Some(parent_id.sinto(s)), - predicates, - } + normalize_trait_clauses(s, implied_predicates(tcx, def_id)) }