2024-05-09 20:05:59 -04:00
|
|
|
use crate::traits::{self, Obligation, ObligationCauseCode, PredicateObligation};
|
2023-10-18 03:04:00 +00:00
|
|
|
use rustc_data_structures::fx::FxHashSet;
|
2024-07-05 16:02:35 -04:00
|
|
|
use rustc_middle::ty::ToPolyTraitRef;
|
2024-07-06 12:21:00 -04:00
|
|
|
use rustc_middle::ty::{self, TyCtxt};
|
2020-12-03 20:10:55 -03:00
|
|
|
use rustc_span::symbol::Ident;
|
2021-11-13 23:56:22 +01:00
|
|
|
use rustc_span::Span;
|
2024-07-06 12:21:00 -04:00
|
|
|
pub use rustc_type_ir::elaborate::*;
|
2020-02-22 11:44:18 +01:00
|
|
|
|
2020-03-31 16:50:15 -07:00
|
|
|
pub fn anonymize_predicate<'tcx>(
|
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2020-05-23 11:09:32 +02:00
|
|
|
pred: ty::Predicate<'tcx>,
|
2020-03-31 16:50:15 -07:00
|
|
|
) -> ty::Predicate<'tcx> {
|
2022-07-25 20:24:13 +02:00
|
|
|
let new = tcx.anonymize_bound_vars(pred.kind());
|
2020-12-23 16:36:23 -05:00
|
|
|
tcx.reuse_or_mk_predicate(pred, new)
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
|
|
2021-06-17 12:20:18 +08:00
|
|
|
pub struct PredicateSet<'tcx> {
|
2020-02-22 11:44:18 +01:00
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
|
set: FxHashSet<ty::Predicate<'tcx>>,
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-13 16:50:58 -05:00
|
|
|
impl<'tcx> PredicateSet<'tcx> {
|
2021-06-17 12:20:18 +08:00
|
|
|
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
|
2020-03-21 13:53:34 +01:00
|
|
|
Self { tcx, set: Default::default() }
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
|
|
2023-07-19 09:44:40 +00:00
|
|
|
/// Adds a predicate to the set.
|
|
|
|
|
///
|
|
|
|
|
/// Returns whether the predicate was newly inserted. That is:
|
|
|
|
|
/// - If the set did not previously contain this predicate, `true` is returned.
|
|
|
|
|
/// - If the set already contained this predicate, `false` is returned,
|
|
|
|
|
/// and the set is not modified: original predicate is not replaced,
|
|
|
|
|
/// and the predicate passed as argument is dropped.
|
2021-06-17 12:20:18 +08:00
|
|
|
pub fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
|
2020-02-22 11:44:18 +01:00
|
|
|
// We have to be careful here because we want
|
|
|
|
|
//
|
2020-06-06 12:05:37 +02:00
|
|
|
// for<'a> Foo<&'a i32>
|
2020-02-22 11:44:18 +01:00
|
|
|
//
|
|
|
|
|
// and
|
|
|
|
|
//
|
2020-06-06 12:05:37 +02:00
|
|
|
// for<'b> Foo<&'b i32>
|
2020-02-22 11:44:18 +01:00
|
|
|
//
|
|
|
|
|
// to be considered equivalent. So normalize all late-bound
|
|
|
|
|
// regions before we throw things into the underlying set.
|
|
|
|
|
self.set.insert(anonymize_predicate(self.tcx, pred))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-13 16:50:58 -05:00
|
|
|
impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
|
2020-05-23 11:09:32 +02:00
|
|
|
fn extend<I: IntoIterator<Item = ty::Predicate<'tcx>>>(&mut self, iter: I) {
|
2020-02-22 11:44:18 +01:00
|
|
|
for pred in iter {
|
2020-05-23 11:09:32 +02:00
|
|
|
self.insert(pred);
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
|
}
|
2020-05-12 20:09:55 -07:00
|
|
|
|
|
|
|
|
fn extend_one(&mut self, pred: ty::Predicate<'tcx>) {
|
|
|
|
|
self.insert(pred);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn extend_reserve(&mut self, additional: usize) {
|
|
|
|
|
Extend::<ty::Predicate<'tcx>>::extend_reserve(&mut self.set, additional);
|
|
|
|
|
}
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
|
|
2023-04-06 23:11:19 +00:00
|
|
|
/// For [`Obligation`], a sub-obligation is combined with the current obligation's
|
2024-07-06 12:21:00 -04:00
|
|
|
/// param-env and cause code.
|
|
|
|
|
impl<'tcx> Elaboratable<TyCtxt<'tcx>> for PredicateObligation<'tcx> {
|
2023-04-06 23:11:19 +00:00
|
|
|
fn predicate(&self) -> ty::Predicate<'tcx> {
|
|
|
|
|
self.predicate
|
|
|
|
|
}
|
|
|
|
|
|
2023-06-29 00:46:41 +00:00
|
|
|
fn child(&self, clause: ty::Clause<'tcx>) -> Self {
|
2023-04-06 23:11:19 +00:00
|
|
|
Obligation {
|
|
|
|
|
cause: self.cause.clone(),
|
|
|
|
|
param_env: self.param_env,
|
|
|
|
|
recursion_depth: 0,
|
2023-06-29 00:46:41 +00:00
|
|
|
predicate: clause.as_predicate(),
|
2023-04-06 23:11:19 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn child_with_derived_cause(
|
|
|
|
|
&self,
|
2023-06-29 00:46:41 +00:00
|
|
|
clause: ty::Clause<'tcx>,
|
2023-04-06 23:11:19 +00:00
|
|
|
span: Span,
|
|
|
|
|
parent_trait_pred: ty::PolyTraitPredicate<'tcx>,
|
|
|
|
|
index: usize,
|
|
|
|
|
) -> Self {
|
|
|
|
|
let cause = self.cause.clone().derived_cause(parent_trait_pred, |derived| {
|
2024-05-09 20:25:11 -04:00
|
|
|
ObligationCauseCode::ImplDerived(Box::new(traits::ImplDerivedCause {
|
2024-05-09 20:12:47 -04:00
|
|
|
derived,
|
|
|
|
|
impl_or_alias_def_id: parent_trait_pred.def_id(),
|
|
|
|
|
impl_def_predicate_index: Some(index),
|
|
|
|
|
span,
|
|
|
|
|
}))
|
2023-04-06 23:11:19 +00:00
|
|
|
});
|
2023-06-29 00:46:41 +00:00
|
|
|
Obligation {
|
|
|
|
|
cause,
|
|
|
|
|
param_env: self.param_env,
|
|
|
|
|
recursion_depth: 0,
|
|
|
|
|
predicate: clause.as_predicate(),
|
|
|
|
|
}
|
2023-04-06 23:11:19 +00:00
|
|
|
}
|
2020-03-31 16:50:15 -07:00
|
|
|
}
|
|
|
|
|
|
2023-04-06 23:24:03 +00:00
|
|
|
/// A specialized variant of `elaborate` that only elaborates trait references that may
|
2023-05-03 20:13:32 +00:00
|
|
|
/// define the given associated item with the name `assoc_name`. It uses the
|
2024-06-27 12:01:49 -04:00
|
|
|
/// `explicit_supertraits_containing_assoc_item` query to avoid enumerating super-predicates that
|
2022-11-16 20:34:16 +00:00
|
|
|
/// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or
|
2020-12-03 20:10:55 -03:00
|
|
|
/// `T::Item` and helps to avoid cycle errors (see e.g. #35237).
|
2023-05-03 20:13:32 +00:00
|
|
|
pub fn transitive_bounds_that_define_assoc_item<'tcx>(
|
2020-12-03 20:10:55 -03:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2023-10-18 02:45:16 +00:00
|
|
|
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
2020-12-03 20:10:55 -03:00
|
|
|
assoc_name: Ident,
|
2024-07-05 16:02:35 -04:00
|
|
|
) -> impl Iterator<Item = ty::PolyTraitRef<'tcx>> {
|
|
|
|
|
let mut seen = FxHashSet::default();
|
|
|
|
|
let mut stack: Vec<_> = trait_refs.collect();
|
|
|
|
|
|
|
|
|
|
std::iter::from_fn(move || {
|
|
|
|
|
while let Some(trait_ref) = stack.pop() {
|
|
|
|
|
if !seen.insert(tcx.anonymize_bound_vars(trait_ref)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
stack.extend(
|
|
|
|
|
tcx.explicit_supertraits_containing_assoc_item((trait_ref.def_id(), assoc_name))
|
|
|
|
|
.instantiate_own_identity()
|
|
|
|
|
.map(|(clause, _)| clause.instantiate_supertrait(tcx, trait_ref))
|
|
|
|
|
.filter_map(|clause| clause.as_trait_clause())
|
|
|
|
|
// FIXME: Negative supertraits are elaborated here lol
|
|
|
|
|
.map(|trait_pred| trait_pred.to_poly_trait_ref()),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
return Some(trait_ref);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
None
|
|
|
|
|
})
|
2020-12-03 20:10:55 -03:00
|
|
|
}
|