rustc_hir_analysis/collect/
predicates_of.rs

1use std::assert_matches::assert_matches;
2
3use hir::Node;
4use rustc_data_structures::fx::FxIndexSet;
5use rustc_hir as hir;
6use rustc_hir::attrs::AttributeKind;
7use rustc_hir::def::DefKind;
8use rustc_hir::def_id::{DefId, LocalDefId};
9use rustc_hir::find_attr;
10use rustc_middle::ty::{
11    self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast,
12};
13use rustc_middle::{bug, span_bug};
14use rustc_span::{DUMMY_SP, Ident, Span};
15use tracing::{debug, instrument, trace};
16
17use super::item_bounds::explicit_item_bounds_with_filter;
18use crate::collect::ItemCtxt;
19use crate::constrained_generic_params as cgp;
20use crate::delegation::inherit_predicates_for_delegation_item;
21use crate::hir_ty_lowering::{
22    HirTyLowerer, ImpliedBoundsContext, OverlappingAsssocItemConstraints, PredicateFilter,
23    RegionInferReason,
24};
25
26/// Returns a list of all type predicates (explicit and implicit) for the definition with
27/// ID `def_id`. This includes all predicates returned by `explicit_predicates_of`, plus
28/// inferred constraints concerning which regions outlive other regions.
29#[instrument(level = "debug", skip(tcx))]
30pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
31    let mut result = tcx.explicit_predicates_of(def_id);
32    debug!("predicates_of: explicit_predicates_of({:?}) = {:?}", def_id, result);
33
34    let inferred_outlives = tcx.inferred_outlives_of(def_id);
35    if !inferred_outlives.is_empty() {
36        debug!("predicates_of: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives,);
37        let inferred_outlives_iter =
38            inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span));
39        if result.predicates.is_empty() {
40            result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter);
41        } else {
42            result.predicates = tcx.arena.alloc_from_iter(
43                result.predicates.into_iter().copied().chain(inferred_outlives_iter),
44            );
45        }
46    }
47
48    if tcx.is_trait(def_id) {
49        // For traits, add `Self: Trait` predicate. This is
50        // not part of the predicates that a user writes, but it
51        // is something that one must prove in order to invoke a
52        // method or project an associated type.
53        //
54        // In the chalk setup, this predicate is not part of the
55        // "predicates" for a trait item. But it is useful in
56        // rustc because if you directly (e.g.) invoke a trait
57        // method like `Trait::method(...)`, you must naturally
58        // prove that the trait applies to the types that were
59        // used, and adding the predicate into this list ensures
60        // that this is done.
61        //
62        // We use a DUMMY_SP here as a way to signal trait bounds that come
63        // from the trait itself that *shouldn't* be shown as the source of
64        // an obligation and instead be skipped. Otherwise we'd use
65        // `tcx.def_span(def_id);`
66        let span = DUMMY_SP;
67
68        result.predicates = tcx.arena.alloc_from_iter(
69            result
70                .predicates
71                .iter()
72                .copied()
73                .chain(std::iter::once((ty::TraitRef::identity(tcx, def_id).upcast(tcx), span))),
74        );
75    }
76
77    debug!("predicates_of({:?}) = {:?}", def_id, result);
78    result
79}
80
81/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
82/// N.B., this does not include any implied/inferred constraints.
83#[instrument(level = "trace", skip(tcx), ret)]
84fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
85    use rustc_hir::*;
86
87    match tcx.opt_rpitit_info(def_id.to_def_id()) {
88        Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
89            let mut predicates = Vec::new();
90
91            // RPITITs should inherit the predicates of their parent. This is
92            // both to ensure that the RPITITs are only instantiated when the
93            // parent predicates would hold, and also so that the param-env
94            // inherits these predicates as assumptions.
95            let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
96            predicates
97                .extend(tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_args));
98
99            // We also install bidirectional outlives predicates for the RPITIT
100            // to keep the duplicates lifetimes from opaque lowering in sync.
101            // We only need to compute bidirectional outlives for the duplicated
102            // opaque lifetimes, which explains the slicing below.
103            compute_bidirectional_outlives_predicates(
104                tcx,
105                &tcx.generics_of(def_id.to_def_id()).own_params
106                    [tcx.generics_of(fn_def_id).own_params.len()..],
107                &mut predicates,
108            );
109
110            return ty::GenericPredicates {
111                parent: Some(tcx.parent(def_id.to_def_id())),
112                predicates: tcx.arena.alloc_from_iter(predicates),
113            };
114        }
115
116        Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
117            let trait_item_def_id = tcx.trait_item_of(def_id).unwrap();
118            let trait_assoc_predicates = tcx.explicit_predicates_of(trait_item_def_id);
119
120            let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
121            let impl_def_id = tcx.parent(fn_def_id);
122            let impl_trait_ref_args = tcx.impl_trait_ref(impl_def_id).instantiate_identity().args;
123
124            let impl_assoc_args =
125                impl_assoc_identity_args.rebase_onto(tcx, impl_def_id, impl_trait_ref_args);
126
127            let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_args);
128
129            return ty::GenericPredicates {
130                parent: Some(impl_def_id),
131                predicates: tcx.arena.alloc_from_iter(impl_predicates),
132            };
133        }
134
135        None => {}
136    }
137
138    let hir_id = tcx.local_def_id_to_hir_id(def_id);
139    let node = tcx.hir_node(hir_id);
140
141    if let Some(sig) = node.fn_sig()
142        && let Some(sig_id) = sig.decl.opt_delegation_sig_id()
143    {
144        return inherit_predicates_for_delegation_item(tcx, def_id, sig_id);
145    }
146
147    let mut is_trait = None;
148    let mut is_default_impl_trait = None;
149
150    let icx = ItemCtxt::new(tcx, def_id);
151
152    const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
153
154    // We use an `IndexSet` to preserve order of insertion.
155    // Preserving the order of insertion is important here so as not to break UI tests.
156    let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
157
158    let hir_generics = node.generics().unwrap_or(NO_GENERICS);
159    if let Node::Item(item) = node {
160        match item.kind {
161            ItemKind::Impl(impl_) => {
162                if let Some(of_trait) = impl_.of_trait
163                    && of_trait.defaultness.is_default()
164                {
165                    is_default_impl_trait =
166                        Some(ty::Binder::dummy(tcx.impl_trait_ref(def_id).instantiate_identity()));
167                }
168            }
169            ItemKind::Trait(_, _, _, _, _, self_bounds, ..)
170            | ItemKind::TraitAlias(_, _, self_bounds) => {
171                is_trait = Some((self_bounds, item.span));
172            }
173            _ => {}
174        }
175    };
176
177    let generics = tcx.generics_of(def_id);
178
179    // Below we'll consider the bounds on the type parameters (including `Self`)
180    // and the explicit where-clauses, but to get the full set of predicates
181    // on a trait we must also consider the bounds that follow the trait's name,
182    // like `trait Foo: A + B + C`.
183    if let Some((self_bounds, span)) = is_trait {
184        let mut bounds = Vec::new();
185        icx.lowerer().lower_bounds(
186            tcx.types.self_param,
187            self_bounds,
188            &mut bounds,
189            ty::List::empty(),
190            PredicateFilter::All,
191            OverlappingAsssocItemConstraints::Allowed,
192        );
193        icx.lowerer().add_implicit_sizedness_bounds(
194            &mut bounds,
195            tcx.types.self_param,
196            self_bounds,
197            ImpliedBoundsContext::TraitDef(def_id),
198            span,
199        );
200        icx.lowerer().add_default_traits(
201            &mut bounds,
202            tcx.types.self_param,
203            self_bounds,
204            ImpliedBoundsContext::TraitDef(def_id),
205            span,
206        );
207        predicates.extend(bounds);
208    }
209
210    // In default impls, we can assume that the self type implements
211    // the trait. So in:
212    //
213    //     default impl Foo for Bar { .. }
214    //
215    // we add a default where clause `Bar: Foo`. We do a similar thing for traits
216    // (see below). Recall that a default impl is not itself an impl, but rather a
217    // set of defaults that can be incorporated into another impl.
218    if let Some(trait_ref) = is_default_impl_trait {
219        predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id)));
220    }
221
222    // Add implicit predicates that should be treated as if the user has written them,
223    // including the implicit `T: Sized` for all generic parameters, and `ConstArgHasType`
224    // for const params.
225    for param in hir_generics.params {
226        match param.kind {
227            GenericParamKind::Lifetime { .. } => (),
228            GenericParamKind::Type { .. } => {
229                let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
230                let mut bounds = Vec::new();
231                // Implicit bounds are added to type params unless a `?Trait` bound is found
232                icx.lowerer().add_implicit_sizedness_bounds(
233                    &mut bounds,
234                    param_ty,
235                    &[],
236                    ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
237                    param.span,
238                );
239                icx.lowerer().add_default_traits(
240                    &mut bounds,
241                    param_ty,
242                    &[],
243                    ImpliedBoundsContext::TyParam(param.def_id, hir_generics.predicates),
244                    param.span,
245                );
246                trace!(?bounds);
247                predicates.extend(bounds);
248                trace!(?predicates);
249            }
250            hir::GenericParamKind::Const { .. } => {
251                let param_def_id = param.def_id.to_def_id();
252                let ct_ty = tcx.type_of(param_def_id).instantiate_identity();
253                let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
254                predicates
255                    .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
256            }
257        }
258    }
259
260    trace!(?predicates);
261    // Add inline `<T: Foo>` bounds and bounds in the where clause.
262    for predicate in hir_generics.predicates {
263        match predicate.kind {
264            hir::WherePredicateKind::BoundPredicate(bound_pred) => {
265                let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
266                let bound_vars = tcx.late_bound_vars(predicate.hir_id);
267
268                // This is a `where Ty:` (sic!).
269                if bound_pred.bounds.is_empty() {
270                    if let ty::Param(_) = ty.kind() {
271                        // We can skip the predicate because type parameters are trivially WF.
272                    } else {
273                        // Keep the type around in a dummy predicate. That way, it's not a complete
274                        // noop (see #53696) and `Ty` is still checked for WF.
275
276                        let span = bound_pred.bounded_ty.span;
277                        let predicate = ty::Binder::bind_with_vars(
278                            ty::ClauseKind::WellFormed(ty.into()),
279                            bound_vars,
280                        );
281                        predicates.insert((predicate.upcast(tcx), span));
282                    }
283                }
284
285                let mut bounds = Vec::new();
286                icx.lowerer().lower_bounds(
287                    ty,
288                    bound_pred.bounds,
289                    &mut bounds,
290                    bound_vars,
291                    PredicateFilter::All,
292                    OverlappingAsssocItemConstraints::Allowed,
293                );
294                predicates.extend(bounds);
295            }
296
297            hir::WherePredicateKind::RegionPredicate(region_pred) => {
298                let r1 = icx
299                    .lowerer()
300                    .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
301                predicates.extend(region_pred.bounds.iter().map(|bound| {
302                    let (r2, span) = match bound {
303                        hir::GenericBound::Outlives(lt) => (
304                            icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
305                            lt.ident.span,
306                        ),
307                        bound => {
308                            span_bug!(
309                                bound.span(),
310                                "lifetime param bounds must be outlives, but found {bound:?}"
311                            )
312                        }
313                    };
314                    let pred =
315                        ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)).upcast(tcx);
316                    (pred, span)
317                }))
318            }
319
320            hir::WherePredicateKind::EqPredicate(..) => {
321                // FIXME(#20041)
322            }
323        }
324    }
325
326    if tcx.features().generic_const_exprs() {
327        predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
328    }
329
330    let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
331    // FIXME(staged_api): We might want to look at the normal stability attributes too but
332    // first we would need a way to let std/core use APIs with unstable feature bounds from
333    // within stable APIs.
334    let allow_unstable_feature_attr =
335        find_attr!(attrs, AttributeKind::UnstableFeatureBound(i) => i)
336            .map(|i| i.as_slice())
337            .unwrap_or_default();
338
339    for (feat_name, span) in allow_unstable_feature_attr {
340        predicates.insert((ty::ClauseKind::UnstableFeature(*feat_name).upcast(tcx), *span));
341    }
342
343    let mut predicates: Vec<_> = predicates.into_iter().collect();
344
345    // Subtle: before we store the predicates into the tcx, we
346    // sort them so that predicates like `T: Foo<Item=U>` come
347    // before uses of `U`. This avoids false ambiguity errors
348    // in trait checking. See `setup_constraining_predicates`
349    // for details.
350    if let Node::Item(&Item { kind: ItemKind::Impl(impl_), .. }) = node {
351        let self_ty = tcx.type_of(def_id).instantiate_identity();
352        let trait_ref =
353            impl_.of_trait.is_some().then(|| tcx.impl_trait_ref(def_id).instantiate_identity());
354        cgp::setup_constraining_predicates(
355            tcx,
356            &mut predicates,
357            trait_ref,
358            &mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
359        );
360    }
361
362    // Opaque types duplicate some of their generic parameters.
363    // We create bi-directional Outlives predicates between the original
364    // and the duplicated parameter, to ensure that they do not get out of sync.
365    if let Node::OpaqueTy(..) = node {
366        compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
367        debug!(?predicates);
368    }
369
370    ty::GenericPredicates {
371        parent: generics.parent,
372        predicates: tcx.arena.alloc_from_iter(predicates),
373    }
374}
375
376/// Opaques have duplicated lifetimes and we need to compute bidirectional outlives predicates to
377/// enforce that these lifetimes stay in sync.
378fn compute_bidirectional_outlives_predicates<'tcx>(
379    tcx: TyCtxt<'tcx>,
380    opaque_own_params: &[ty::GenericParamDef],
381    predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
382) {
383    for param in opaque_own_params {
384        let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
385        if let ty::ReEarlyParam(..) = orig_lifetime.kind() {
386            let dup_lifetime = ty::Region::new_early_param(
387                tcx,
388                ty::EarlyParamRegion { index: param.index, name: param.name },
389            );
390            let span = tcx.def_span(param.def_id);
391            predicates.push((
392                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime))
393                    .upcast(tcx),
394                span,
395            ));
396            predicates.push((
397                ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime))
398                    .upcast(tcx),
399                span,
400            ));
401        }
402    }
403}
404
405#[instrument(level = "debug", skip(tcx, predicates), ret)]
406fn const_evaluatable_predicates_of<'tcx>(
407    tcx: TyCtxt<'tcx>,
408    def_id: LocalDefId,
409    predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
410) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
411    struct ConstCollector<'tcx> {
412        tcx: TyCtxt<'tcx>,
413        preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
414    }
415
416    fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
417        let hir_id = tcx.local_def_id_to_hir_id(def);
418        let (_, parent_node) = tcx
419            .hir_parent_iter(hir_id)
420            .skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
421            .next()
422            .unwrap();
423        matches!(
424            parent_node,
425            Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
426        )
427    }
428
429    impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
430        fn visit_const(&mut self, c: ty::Const<'tcx>) {
431            if let ty::ConstKind::Unevaluated(uv) = c.kind() {
432                if let Some(local) = uv.def.as_local()
433                    && is_const_param_default(self.tcx, local)
434                {
435                    // Do not look into const param defaults,
436                    // these get checked when they are actually instantiated.
437                    //
438                    // We do not want the following to error:
439                    //
440                    //     struct Foo<const N: usize, const M: usize = { N + 1 }>;
441                    //     struct Bar<const N: usize>(Foo<N, 3>);
442                    return;
443                }
444
445                let span = self.tcx.def_span(uv.def);
446                self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
447            }
448        }
449    }
450
451    let hir_id = tcx.local_def_id_to_hir_id(def_id);
452    let node = tcx.hir_node(hir_id);
453
454    let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
455
456    for (clause, _sp) in predicates {
457        clause.visit_with(&mut collector);
458    }
459
460    if let hir::Node::Item(item) = node
461        && let hir::ItemKind::Impl(impl_) = item.kind
462    {
463        if impl_.of_trait.is_some() {
464            debug!("visit impl trait_ref");
465            let trait_ref = tcx.impl_trait_ref(def_id);
466            trait_ref.instantiate_identity().visit_with(&mut collector);
467        }
468
469        debug!("visit self_ty");
470        let self_ty = tcx.type_of(def_id);
471        self_ty.instantiate_identity().visit_with(&mut collector);
472    }
473
474    if let Some(_) = tcx.hir_fn_sig_by_hir_id(hir_id) {
475        debug!("visit fn sig");
476        let fn_sig = tcx.fn_sig(def_id);
477        let fn_sig = fn_sig.instantiate_identity();
478        debug!(?fn_sig);
479        fn_sig.visit_with(&mut collector);
480    }
481
482    collector.preds
483}
484
485pub(super) fn trait_explicit_predicates_and_bounds(
486    tcx: TyCtxt<'_>,
487    def_id: LocalDefId,
488) -> ty::GenericPredicates<'_> {
489    assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
490    gather_explicit_predicates_of(tcx, def_id)
491}
492
493pub(super) fn explicit_predicates_of<'tcx>(
494    tcx: TyCtxt<'tcx>,
495    def_id: LocalDefId,
496) -> ty::GenericPredicates<'tcx> {
497    let def_kind = tcx.def_kind(def_id);
498    if let DefKind::Trait = def_kind {
499        // Remove bounds on associated types from the predicates, they will be
500        // returned by `explicit_item_bounds`.
501        let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
502        let trait_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
503
504        let is_assoc_item_ty = |ty: Ty<'tcx>| {
505            // For a predicate from a where clause to become a bound on an
506            // associated type:
507            // * It must use the identity args of the item.
508            //   * We're in the scope of the trait, so we can't name any
509            //     parameters of the GAT. That means that all we need to
510            //     check are that the args of the projection are the
511            //     identity args of the trait.
512            // * It must be an associated type for this trait (*not* a
513            //   supertrait).
514            if let ty::Alias(ty::Projection, projection) = ty.kind() {
515                projection.args == trait_identity_args
516                    // FIXME(return_type_notation): This check should be more robust
517                    && !tcx.is_impl_trait_in_trait(projection.def_id)
518                    && tcx.parent(projection.def_id) == def_id.to_def_id()
519            } else {
520                false
521            }
522        };
523
524        let predicates: Vec<_> = predicates_and_bounds
525            .predicates
526            .iter()
527            .copied()
528            .filter(|(pred, _)| match pred.kind().skip_binder() {
529                ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
530                ty::ClauseKind::Projection(proj) => {
531                    !is_assoc_item_ty(proj.projection_term.self_ty())
532                }
533                ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
534                _ => true,
535            })
536            .collect();
537        if predicates.len() == predicates_and_bounds.predicates.len() {
538            predicates_and_bounds
539        } else {
540            ty::GenericPredicates {
541                parent: predicates_and_bounds.parent,
542                predicates: tcx.arena.alloc_slice(&predicates),
543            }
544        }
545    } else {
546        if matches!(def_kind, DefKind::AnonConst)
547            && tcx.features().generic_const_exprs()
548            && let Some(defaulted_param_def_id) =
549                tcx.hir_opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
550        {
551            // In `generics_of` we set the generics' parent to be our parent's parent which means that
552            // we lose out on the predicates of our actual parent if we dont return those predicates here.
553            // (See comment in `generics_of` for more information on why the parent shenanigans is necessary)
554            //
555            // struct Foo<T, const N: usize = { <T as Trait>::ASSOC }>(T) where T: Trait;
556            //        ^^^                     ^^^^^^^^^^^^^^^^^^^^^^^ the def id we are calling
557            //        ^^^                                             explicit_predicates_of on
558            //        parent item we dont have set as the
559            //        parent of generics returned by `generics_of`
560            //
561            // In the above code we want the anon const to have predicates in its param env for `T: Trait`
562            // and we would be calling `explicit_predicates_of(Foo)` here
563            let parent_def_id = tcx.local_parent(def_id);
564            let parent_preds = tcx.explicit_predicates_of(parent_def_id);
565
566            // If we dont filter out `ConstArgHasType` predicates then every single defaulted const parameter
567            // will ICE because of #106994. FIXME(generic_const_exprs): remove this when a more general solution
568            // to #106994 is implemented.
569            let filtered_predicates = parent_preds
570                .predicates
571                .into_iter()
572                .filter(|(pred, _)| {
573                    if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
574                        match ct.kind() {
575                            ty::ConstKind::Param(param_const) => {
576                                let defaulted_param_idx = tcx
577                                    .generics_of(parent_def_id)
578                                    .param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
579                                param_const.index < defaulted_param_idx
580                            }
581                            _ => bug!(
582                                "`ConstArgHasType` in `predicates_of`\
583                                 that isn't a `Param` const"
584                            ),
585                        }
586                    } else {
587                        true
588                    }
589                })
590                .cloned();
591            return GenericPredicates {
592                parent: parent_preds.parent,
593                predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
594            };
595        }
596        gather_explicit_predicates_of(tcx, def_id)
597    }
598}
599
600/// Ensures that the super-predicates of the trait with a `DefId`
601/// of `trait_def_id` are lowered and stored. This also ensures that
602/// the transitive super-predicates are lowered.
603pub(super) fn explicit_super_predicates_of<'tcx>(
604    tcx: TyCtxt<'tcx>,
605    trait_def_id: LocalDefId,
606) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
607    implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
608}
609
610pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>(
611    tcx: TyCtxt<'tcx>,
612    (trait_def_id, assoc_ident): (DefId, Ident),
613) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
614    implied_predicates_with_filter(
615        tcx,
616        trait_def_id,
617        PredicateFilter::SelfTraitThatDefines(assoc_ident),
618    )
619}
620
621pub(super) fn explicit_implied_predicates_of<'tcx>(
622    tcx: TyCtxt<'tcx>,
623    trait_def_id: LocalDefId,
624) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
625    implied_predicates_with_filter(
626        tcx,
627        trait_def_id.to_def_id(),
628        if tcx.is_trait_alias(trait_def_id.to_def_id()) {
629            PredicateFilter::All
630        } else {
631            PredicateFilter::SelfAndAssociatedTypeBounds
632        },
633    )
634}
635
636/// Ensures that the super-predicates of the trait with a `DefId`
637/// of `trait_def_id` are lowered and stored. This also ensures that
638/// the transitive super-predicates are lowered.
639pub(super) fn implied_predicates_with_filter<'tcx>(
640    tcx: TyCtxt<'tcx>,
641    trait_def_id: DefId,
642    filter: PredicateFilter,
643) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
644    let Some(trait_def_id) = trait_def_id.as_local() else {
645        // if `assoc_ident` is None, then the query should've been redirected to an
646        // external provider
647        assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_));
648        return tcx.explicit_super_predicates_of(trait_def_id);
649    };
650
651    let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else {
652        bug!("trait_def_id {trait_def_id:?} is not an item");
653    };
654
655    let (generics, superbounds) = match item.kind {
656        hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
657        hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
658        _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
659    };
660
661    let icx = ItemCtxt::new(tcx, trait_def_id);
662
663    let self_param_ty = tcx.types.self_param;
664    let mut bounds = Vec::new();
665    icx.lowerer().lower_bounds(
666        self_param_ty,
667        superbounds,
668        &mut bounds,
669        ty::List::empty(),
670        filter,
671        OverlappingAsssocItemConstraints::Allowed,
672    );
673    match filter {
674        PredicateFilter::All
675        | PredicateFilter::SelfOnly
676        | PredicateFilter::SelfTraitThatDefines(_)
677        | PredicateFilter::SelfAndAssociatedTypeBounds => {
678            icx.lowerer().add_implicit_sizedness_bounds(
679                &mut bounds,
680                self_param_ty,
681                superbounds,
682                ImpliedBoundsContext::TraitDef(trait_def_id),
683                item.span,
684            );
685            icx.lowerer().add_default_traits(
686                &mut bounds,
687                self_param_ty,
688                superbounds,
689                ImpliedBoundsContext::TraitDef(trait_def_id),
690                item.span,
691            );
692        }
693        //`ConstIfConst` is only interested in `[const]` bounds.
694        PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
695    }
696
697    let where_bounds_that_match =
698        icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);
699
700    // Combine the two lists to form the complete set of superbounds:
701    let implied_bounds =
702        &*tcx.arena.alloc_from_iter(bounds.into_iter().chain(where_bounds_that_match));
703    debug!(?implied_bounds);
704
705    // Now require that immediate supertraits are lowered, which will, in
706    // turn, reach indirect supertraits, so we detect cycles now instead of
707    // overflowing during elaboration. Same for implied predicates, which
708    // make sure we walk into associated type bounds.
709    match filter {
710        PredicateFilter::SelfOnly => {
711            for &(pred, span) in implied_bounds {
712                debug!("superbound: {:?}", pred);
713                if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
714                    && bound.polarity == ty::PredicatePolarity::Positive
715                {
716                    tcx.at(span).explicit_super_predicates_of(bound.def_id());
717                }
718            }
719        }
720        PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
721            for &(pred, span) in implied_bounds {
722                debug!("superbound: {:?}", pred);
723                if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
724                    && bound.polarity == ty::PredicatePolarity::Positive
725                {
726                    tcx.at(span).explicit_implied_predicates_of(bound.def_id());
727                }
728            }
729        }
730        _ => {}
731    }
732
733    assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
734
735    ty::EarlyBinder::bind(implied_bounds)
736}
737
738// Make sure when elaborating supertraits, probing for associated types, etc.,
739// we really truly are elaborating clauses that have `ty` as their self type.
740// This is very important since downstream code relies on this being correct.
741pub(super) fn assert_only_contains_predicates_from<'tcx>(
742    filter: PredicateFilter,
743    bounds: &'tcx [(ty::Clause<'tcx>, Span)],
744    ty: Ty<'tcx>,
745) {
746    if !cfg!(debug_assertions) {
747        return;
748    }
749
750    match filter {
751        PredicateFilter::SelfOnly => {
752            for (clause, _) in bounds {
753                match clause.kind().skip_binder() {
754                    ty::ClauseKind::Trait(trait_predicate) => {
755                        assert_eq!(
756                            trait_predicate.self_ty(),
757                            ty,
758                            "expected `Self` predicate when computing \
759                            `{filter:?}` implied bounds: {clause:?}"
760                        );
761                    }
762                    ty::ClauseKind::Projection(projection_predicate) => {
763                        assert_eq!(
764                            projection_predicate.self_ty(),
765                            ty,
766                            "expected `Self` predicate when computing \
767                            `{filter:?}` implied bounds: {clause:?}"
768                        );
769                    }
770                    ty::ClauseKind::TypeOutlives(outlives_predicate) => {
771                        assert_eq!(
772                            outlives_predicate.0, ty,
773                            "expected `Self` predicate when computing \
774                            `{filter:?}` implied bounds: {clause:?}"
775                        );
776                    }
777                    ty::ClauseKind::HostEffect(host_effect_predicate) => {
778                        assert_eq!(
779                            host_effect_predicate.self_ty(),
780                            ty,
781                            "expected `Self` predicate when computing \
782                            `{filter:?}` implied bounds: {clause:?}"
783                        );
784                    }
785
786                    ty::ClauseKind::RegionOutlives(_)
787                    | ty::ClauseKind::ConstArgHasType(_, _)
788                    | ty::ClauseKind::WellFormed(_)
789                    | ty::ClauseKind::UnstableFeature(_)
790                    | ty::ClauseKind::ConstEvaluatable(_) => {
791                        bug!(
792                            "unexpected non-`Self` predicate when computing \
793                            `{filter:?}` implied bounds: {clause:?}"
794                        );
795                    }
796                }
797            }
798        }
799        PredicateFilter::SelfTraitThatDefines(_) => {
800            for (clause, _) in bounds {
801                match clause.kind().skip_binder() {
802                    ty::ClauseKind::Trait(trait_predicate) => {
803                        assert_eq!(
804                            trait_predicate.self_ty(),
805                            ty,
806                            "expected `Self` predicate when computing \
807                            `{filter:?}` implied bounds: {clause:?}"
808                        );
809                    }
810
811                    ty::ClauseKind::Projection(_)
812                    | ty::ClauseKind::TypeOutlives(_)
813                    | ty::ClauseKind::RegionOutlives(_)
814                    | ty::ClauseKind::ConstArgHasType(_, _)
815                    | ty::ClauseKind::WellFormed(_)
816                    | ty::ClauseKind::ConstEvaluatable(_)
817                    | ty::ClauseKind::UnstableFeature(_)
818                    | ty::ClauseKind::HostEffect(..) => {
819                        bug!(
820                            "unexpected non-`Self` predicate when computing \
821                            `{filter:?}` implied bounds: {clause:?}"
822                        );
823                    }
824                }
825            }
826        }
827        PredicateFilter::ConstIfConst => {
828            for (clause, _) in bounds {
829                match clause.kind().skip_binder() {
830                    ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
831                        trait_ref: _,
832                        constness: ty::BoundConstness::Maybe,
833                    }) => {}
834                    _ => {
835                        bug!(
836                            "unexpected non-`HostEffect` predicate when computing \
837                            `{filter:?}` implied bounds: {clause:?}"
838                        );
839                    }
840                }
841            }
842        }
843        PredicateFilter::SelfConstIfConst => {
844            for (clause, _) in bounds {
845                match clause.kind().skip_binder() {
846                    ty::ClauseKind::HostEffect(pred) => {
847                        assert_eq!(
848                            pred.constness,
849                            ty::BoundConstness::Maybe,
850                            "expected `[const]` predicate when computing `{filter:?}` \
851                            implied bounds: {clause:?}",
852                        );
853                        assert_eq!(
854                            pred.trait_ref.self_ty(),
855                            ty,
856                            "expected `Self` predicate when computing `{filter:?}` \
857                            implied bounds: {clause:?}"
858                        );
859                    }
860                    _ => {
861                        bug!(
862                            "unexpected non-`HostEffect` predicate when computing \
863                            `{filter:?}` implied bounds: {clause:?}"
864                        );
865                    }
866                }
867            }
868        }
869        PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
870    }
871}
872
873/// Returns the predicates defined on `item_def_id` of the form
874/// `X: Foo` where `X` is the type parameter `def_id`.
875#[instrument(level = "trace", skip(tcx))]
876pub(super) fn type_param_predicates<'tcx>(
877    tcx: TyCtxt<'tcx>,
878    (item_def_id, def_id, assoc_ident): (LocalDefId, LocalDefId, Ident),
879) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
880    match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
881        Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
882            return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_ident));
883        }
884        Some(ty::ImplTraitInTraitData::Impl { .. }) => {
885            unreachable!("should not be lowering bounds on RPITIT in impl")
886        }
887        None => {}
888    }
889
890    // In the HIR, bounds can derive from two places. Either
891    // written inline like `<T: Foo>` or in a where-clause like
892    // `where T: Foo`.
893
894    let param_id = tcx.local_def_id_to_hir_id(def_id);
895    let param_owner = tcx.hir_ty_param_owner(def_id);
896
897    // Don't look for bounds where the type parameter isn't in scope.
898    let parent = if item_def_id == param_owner {
899        // FIXME: Shouldn't this be unreachable?
900        None
901    } else {
902        tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local())
903    };
904
905    let result = if let Some(parent) = parent {
906        let icx = ItemCtxt::new(tcx, parent);
907        icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_ident)
908    } else {
909        ty::EarlyBinder::bind(&[] as &[_])
910    };
911    let mut extend = None;
912
913    let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id);
914
915    let hir_node = tcx.hir_node(item_hir_id);
916    let Some(hir_generics) = hir_node.generics() else {
917        return result;
918    };
919
920    if let Node::Item(item) = hir_node
921        && let hir::ItemKind::Trait(..) = item.kind
922        // Implied `Self: Trait` and supertrait bounds.
923        && param_id == item_hir_id
924    {
925        let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id());
926        extend = Some((identity_trait_ref.upcast(tcx), item.span));
927    }
928
929    let icx = ItemCtxt::new(tcx, item_def_id);
930    let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics(
931        hir_generics,
932        def_id,
933        PredicateFilter::SelfTraitThatDefines(assoc_ident),
934    ));
935
936    let bounds =
937        &*tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates));
938
939    // Double check that the bounds *only* contain `SelfTy: Trait` preds.
940    let self_ty = match tcx.def_kind(def_id) {
941        DefKind::TyParam => Ty::new_param(
942            tcx,
943            tcx.generics_of(item_def_id)
944                .param_def_id_to_index(tcx, def_id.to_def_id())
945                .expect("expected generic param to be owned by item"),
946            tcx.item_name(def_id.to_def_id()),
947        ),
948        DefKind::Trait | DefKind::TraitAlias => tcx.types.self_param,
949        _ => unreachable!(),
950    };
951    assert_only_contains_predicates_from(
952        PredicateFilter::SelfTraitThatDefines(assoc_ident),
953        bounds,
954        self_ty,
955    );
956
957    ty::EarlyBinder::bind(bounds)
958}
959
960impl<'tcx> ItemCtxt<'tcx> {
961    /// Finds bounds from `hir::Generics`.
962    ///
963    /// This requires scanning through the HIR.
964    /// We do this to avoid having to lower *all* the bounds, which would create artificial cycles.
965    /// Instead, we can only lower the bounds for a type parameter `X` if `X::Foo` is used.
966    #[instrument(level = "trace", skip(self, hir_generics))]
967    fn probe_ty_param_bounds_in_generics(
968        &self,
969        hir_generics: &'tcx hir::Generics<'tcx>,
970        param_def_id: LocalDefId,
971        filter: PredicateFilter,
972    ) -> Vec<(ty::Clause<'tcx>, Span)> {
973        let mut bounds = Vec::new();
974
975        for predicate in hir_generics.predicates {
976            let hir_id = predicate.hir_id;
977            let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind else {
978                continue;
979            };
980
981            match filter {
982                _ if predicate.is_param_bound(param_def_id.to_def_id()) => {
983                    // Ok
984                }
985                PredicateFilter::All => {
986                    // Ok
987                }
988                PredicateFilter::SelfOnly
989                | PredicateFilter::SelfTraitThatDefines(_)
990                | PredicateFilter::SelfConstIfConst
991                | PredicateFilter::SelfAndAssociatedTypeBounds => continue,
992                PredicateFilter::ConstIfConst => unreachable!(),
993            }
994
995            let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty);
996
997            let bound_vars = self.tcx.late_bound_vars(hir_id);
998            self.lowerer().lower_bounds(
999                bound_ty,
1000                predicate.bounds,
1001                &mut bounds,
1002                bound_vars,
1003                filter,
1004                OverlappingAsssocItemConstraints::Allowed,
1005            );
1006        }
1007
1008        bounds
1009    }
1010}
1011
1012pub(super) fn const_conditions<'tcx>(
1013    tcx: TyCtxt<'tcx>,
1014    def_id: LocalDefId,
1015) -> ty::ConstConditions<'tcx> {
1016    if !tcx.is_conditionally_const(def_id) {
1017        bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}");
1018    }
1019
1020    match tcx.opt_rpitit_info(def_id.to_def_id()) {
1021        // RPITITs inherit const conditions of their parent fn
1022        Some(
1023            ty::ImplTraitInTraitData::Impl { fn_def_id }
1024            | ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
1025        ) => return tcx.const_conditions(fn_def_id),
1026        None => {}
1027    }
1028
1029    let (generics, trait_def_id_and_supertraits, has_parent) = match tcx.hir_node_by_def_id(def_id)
1030    {
1031        Node::Item(item) => match item.kind {
1032            hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
1033            hir::ItemKind::Fn { generics, .. } => (generics, None, false),
1034            hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => {
1035                (generics, Some((item.owner_id.def_id, supertraits)), false)
1036            }
1037            _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1038        },
1039        // While associated types are not really const, we do allow them to have `[const]`
1040        // bounds and where clauses. `const_conditions` is responsible for gathering
1041        // these up so we can check them in `compare_type_predicate_entailment`, and
1042        // in `HostEffect` goal computation.
1043        Node::TraitItem(item) => match item.kind {
1044            hir::TraitItemKind::Fn(_, _) | hir::TraitItemKind::Type(_, _) => {
1045                (item.generics, None, true)
1046            }
1047            _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1048        },
1049        Node::ImplItem(item) => match item.kind {
1050            hir::ImplItemKind::Fn(_, _) | hir::ImplItemKind::Type(_) => {
1051                (item.generics, None, tcx.is_conditionally_const(tcx.local_parent(def_id)))
1052            }
1053            _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1054        },
1055        Node::ForeignItem(item) => match item.kind {
1056            hir::ForeignItemKind::Fn(_, _, generics) => (generics, None, false),
1057            _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1058        },
1059        Node::OpaqueTy(opaque) => match opaque.origin {
1060            hir::OpaqueTyOrigin::FnReturn { parent, .. } => return tcx.const_conditions(parent),
1061            hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => {
1062                unreachable!()
1063            }
1064        },
1065        // N.B. Tuple ctors are unconditionally constant.
1066        Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(),
1067        _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1068    };
1069
1070    let icx = ItemCtxt::new(tcx, def_id);
1071    let mut bounds = Vec::new();
1072
1073    for pred in generics.predicates {
1074        match pred.kind {
1075            hir::WherePredicateKind::BoundPredicate(bound_pred) => {
1076                let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
1077                let bound_vars = tcx.late_bound_vars(pred.hir_id);
1078                icx.lowerer().lower_bounds(
1079                    ty,
1080                    bound_pred.bounds.iter(),
1081                    &mut bounds,
1082                    bound_vars,
1083                    PredicateFilter::ConstIfConst,
1084                    OverlappingAsssocItemConstraints::Allowed,
1085                );
1086            }
1087            _ => {}
1088        }
1089    }
1090
1091    if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
1092        // We've checked above that the trait is conditionally const.
1093        bounds.push((
1094            ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
1095                .to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
1096            DUMMY_SP,
1097        ));
1098
1099        icx.lowerer().lower_bounds(
1100            tcx.types.self_param,
1101            supertraits,
1102            &mut bounds,
1103            ty::List::empty(),
1104            PredicateFilter::ConstIfConst,
1105            OverlappingAsssocItemConstraints::Allowed,
1106        );
1107    }
1108
1109    ty::ConstConditions {
1110        parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
1111        predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| {
1112            (
1113                clause.kind().map_bound(|clause| match clause {
1114                    ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1115                        trait_ref,
1116                        constness: ty::BoundConstness::Maybe,
1117                    }) => trait_ref,
1118                    _ => bug!("converted {clause:?}"),
1119                }),
1120                span,
1121            )
1122        })),
1123    }
1124}
1125
1126pub(super) fn explicit_implied_const_bounds<'tcx>(
1127    tcx: TyCtxt<'tcx>,
1128    def_id: LocalDefId,
1129) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
1130    if !tcx.is_conditionally_const(def_id) {
1131        bug!(
1132            "explicit_implied_const_bounds invoked for item that is not conditionally const: {def_id:?}"
1133        );
1134    }
1135
1136    let bounds = match tcx.opt_rpitit_info(def_id.to_def_id()) {
1137        // RPITIT's bounds are the same as opaque type bounds, but with
1138        // a projection self type.
1139        Some(ty::ImplTraitInTraitData::Trait { .. }) => {
1140            explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1141        }
1142        Some(ty::ImplTraitInTraitData::Impl { .. }) => {
1143            span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds")
1144        }
1145        None => match tcx.hir_node_by_def_id(def_id) {
1146            Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
1147                implied_predicates_with_filter(
1148                    tcx,
1149                    def_id.to_def_id(),
1150                    PredicateFilter::SelfConstIfConst,
1151                )
1152            }
1153            Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. })
1154            | Node::OpaqueTy(_) => {
1155                explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1156            }
1157            _ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"),
1158        },
1159    };
1160
1161    bounds.map_bound(|bounds| {
1162        &*tcx.arena.alloc_from_iter(bounds.iter().copied().map(|(clause, span)| {
1163            (
1164                clause.kind().map_bound(|clause| match clause {
1165                    ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1166                        trait_ref,
1167                        constness: ty::BoundConstness::Maybe,
1168                    }) => trait_ref,
1169                    _ => bug!("converted {clause:?}"),
1170                }),
1171                span,
1172            )
1173        }))
1174    })
1175}