Skip to content

Commit

Permalink
Merge pull request #1222 from Nadrieril/fix-more-generics
Browse files Browse the repository at this point in the history
Make predicate handling a bit more consistent
  • Loading branch information
W95Psp authored Jan 16, 2025
2 parents fa1b025 + 1524f39 commit 54a4159
Show file tree
Hide file tree
Showing 4 changed files with 81 additions and 98 deletions.
8 changes: 5 additions & 3 deletions frontend/exporter/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Item = ty::Clause<'tcx>>,
predicates: ty::GenericPredicates<'tcx>,
) -> Vec<ImplExpr> {
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
Expand All @@ -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);
Expand Down
38 changes: 27 additions & 11 deletions frontend/exporter/src/traits/resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ fn initial_search_predicates<'tcx>(
predicates: &mut Vec<AnnotatedTraitPred<'tcx>>,
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.
Expand All @@ -126,24 +131,26 @@ 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,
})
}
_ => {}
}
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![];
Expand All @@ -158,6 +165,9 @@ fn parents_trait_predicates<'tcx>(
) -> Vec<PolyTraitPredicate<'tcx>> {
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))
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -425,6 +438,9 @@ impl<'tcx> PredicateSearcher<'tcx> {
) -> Result<Vec<ImplExpr<'tcx>>, 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
Expand Down
57 changes: 19 additions & 38 deletions frontend/exporter/src/traits/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Item = Clause<'tcx>> + DoubleEndedIterator {
pub fn required_predicates<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> GenericPredicates<'tcx> {
use DefKind::*;
match tcx.def_kind(def_id) {
AssocConst
Expand All @@ -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<PolyTraitRef<'tcx>> {
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<Item = Clause<'tcx>> + 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::<Vec<_>>(),
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`.
Expand Down
76 changes: 30 additions & 46 deletions frontend/exporter/src/types/new/full_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,23 +97,23 @@ pub enum FullDefKind<Body> {
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,
},
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,
},
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,
Expand All @@ -122,7 +122,7 @@ pub enum FullDefKind<Body> {
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| {
Expand All @@ -142,7 +142,7 @@ pub enum FullDefKind<Body> {
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))]
Expand All @@ -164,15 +164,14 @@ pub enum FullDefKind<Body> {
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({
use ty::Upcast;
let tcx = s.base().tcx;
let pred: ty::TraitPredicate =
crate::traits::self_predicate(tcx, s.owner_id())
.unwrap()
.no_bound_vars()
.unwrap()
.upcast(tcx);
Expand Down Expand Up @@ -226,7 +225,7 @@ pub enum FullDefKind<Body> {
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,
Expand All @@ -246,7 +245,7 @@ pub enum FullDefKind<Body> {
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,
Expand Down Expand Up @@ -281,7 +280,7 @@ pub enum FullDefKind<Body> {
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,
Expand All @@ -296,7 +295,7 @@ pub enum FullDefKind<Body> {
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,
Expand All @@ -316,7 +315,7 @@ pub enum FullDefKind<Body> {
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,
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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<_>>()
}
_ => 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))
}

0 comments on commit 54a4159

Please sign in to comment.