1use std::assert_matches::assert_matches;
2
3use hir::Node;
4use rustc_data_structures::fx::FxIndexSet;
5use rustc_hir as hir;
6use rustc_hir::def::DefKind;
7use rustc_hir::def_id::{DefId, LocalDefId};
8use rustc_middle::ty::{
9 self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast,
10};
11use rustc_middle::{bug, span_bug};
12use rustc_span::{DUMMY_SP, Ident, Span};
13use tracing::{debug, instrument, trace};
14
15use super::item_bounds::explicit_item_bounds_with_filter;
16use crate::collect::ItemCtxt;
17use crate::constrained_generic_params as cgp;
18use crate::delegation::inherit_predicates_for_delegation_item;
19use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter, RegionInferReason};
20
21#[instrument(level = "debug", skip(tcx))]
25pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
26 let mut result = tcx.explicit_predicates_of(def_id);
27 debug!("predicates_of: explicit_predicates_of({:?}) = {:?}", def_id, result);
28
29 let inferred_outlives = tcx.inferred_outlives_of(def_id);
30 if !inferred_outlives.is_empty() {
31 debug!("predicates_of: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives,);
32 let inferred_outlives_iter =
33 inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span));
34 if result.predicates.is_empty() {
35 result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter);
36 } else {
37 result.predicates = tcx.arena.alloc_from_iter(
38 result.predicates.into_iter().copied().chain(inferred_outlives_iter),
39 );
40 }
41 }
42
43 if tcx.is_trait(def_id) {
44 let span = DUMMY_SP;
62
63 result.predicates = tcx.arena.alloc_from_iter(
64 result
65 .predicates
66 .iter()
67 .copied()
68 .chain(std::iter::once((ty::TraitRef::identity(tcx, def_id).upcast(tcx), span))),
69 );
70 }
71
72 debug!("predicates_of({:?}) = {:?}", def_id, result);
73 result
74}
75
76#[instrument(level = "trace", skip(tcx), ret)]
79fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
80 use rustc_hir::*;
81
82 match tcx.opt_rpitit_info(def_id.to_def_id()) {
83 Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
84 let mut predicates = Vec::new();
85
86 let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
91 predicates
92 .extend(tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_args));
93
94 compute_bidirectional_outlives_predicates(
99 tcx,
100 &tcx.generics_of(def_id.to_def_id()).own_params
101 [tcx.generics_of(fn_def_id).own_params.len()..],
102 &mut predicates,
103 );
104
105 return ty::GenericPredicates {
106 parent: Some(tcx.parent(def_id.to_def_id())),
107 predicates: tcx.arena.alloc_from_iter(predicates),
108 };
109 }
110
111 Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
112 let assoc_item = tcx.associated_item(def_id);
113 let trait_assoc_predicates =
114 tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
115
116 let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
117 let impl_def_id = tcx.parent(fn_def_id);
118 let impl_trait_ref_args =
119 tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args;
120
121 let impl_assoc_args =
122 impl_assoc_identity_args.rebase_onto(tcx, impl_def_id, impl_trait_ref_args);
123
124 let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_args);
125
126 return ty::GenericPredicates {
127 parent: Some(impl_def_id),
128 predicates: tcx.arena.alloc_from_iter(impl_predicates),
129 };
130 }
131
132 None => {}
133 }
134
135 let hir_id = tcx.local_def_id_to_hir_id(def_id);
136 let node = tcx.hir_node(hir_id);
137
138 if let Some(sig) = node.fn_sig()
139 && let Some(sig_id) = sig.decl.opt_delegation_sig_id()
140 {
141 return inherit_predicates_for_delegation_item(tcx, def_id, sig_id);
142 }
143
144 let mut is_trait = None;
145 let mut is_default_impl_trait = None;
146
147 let icx = ItemCtxt::new(tcx, def_id);
148
149 const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
150
151 let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
154
155 let hir_generics = node.generics().unwrap_or(NO_GENERICS);
156 if let Node::Item(item) = node {
157 match item.kind {
158 ItemKind::Impl(impl_) => {
159 if impl_.defaultness.is_default() {
160 is_default_impl_trait = tcx
161 .impl_trait_ref(def_id)
162 .map(|t| ty::Binder::dummy(t.instantiate_identity()));
163 }
164 }
165
166 ItemKind::Trait(_, _, _, _, self_bounds, ..)
167 | ItemKind::TraitAlias(_, _, self_bounds) => {
168 is_trait = Some((self_bounds, item.span));
169 }
170 _ => {}
171 }
172 };
173
174 if let Node::TraitItem(item) = node {
175 let mut bounds = Vec::new();
176 icx.lowerer().add_default_trait_item_bounds(item, &mut bounds);
177 predicates.extend(bounds);
178 }
179
180 let generics = tcx.generics_of(def_id);
181
182 if let Some(self_bounds) = is_trait {
187 let mut bounds = Vec::new();
188 icx.lowerer().lower_bounds(
189 tcx.types.self_param,
190 self_bounds.0,
191 &mut bounds,
192 ty::List::empty(),
193 PredicateFilter::All,
194 );
195 icx.lowerer().add_default_super_traits(
196 def_id,
197 &mut bounds,
198 self_bounds.0,
199 hir_generics,
200 self_bounds.1,
201 );
202 predicates.extend(bounds);
203 }
204
205 if let Some(trait_ref) = is_default_impl_trait {
214 predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id)));
215 }
216
217 for param in hir_generics.params {
221 match param.kind {
222 GenericParamKind::Lifetime { .. } => (),
223 GenericParamKind::Type { .. } => {
224 let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
225 let mut bounds = Vec::new();
226 icx.lowerer().add_default_traits(
228 &mut bounds,
229 param_ty,
230 &[],
231 Some((param.def_id, hir_generics.predicates)),
232 param.span,
233 );
234 trace!(?bounds);
235 predicates.extend(bounds);
236 trace!(?predicates);
237 }
238 hir::GenericParamKind::Const { .. } => {
239 let param_def_id = param.def_id.to_def_id();
240 let ct_ty = tcx.type_of(param_def_id).instantiate_identity();
241 let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
242 predicates
243 .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
244 }
245 }
246 }
247
248 trace!(?predicates);
249 for predicate in hir_generics.predicates {
251 match predicate.kind {
252 hir::WherePredicateKind::BoundPredicate(bound_pred) => {
253 let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
254
255 let bound_vars = tcx.late_bound_vars(predicate.hir_id);
256 if bound_pred.bounds.is_empty() {
260 if let ty::Param(_) = ty.kind() {
261 } else {
268 let span = bound_pred.bounded_ty.span;
269 let predicate = ty::Binder::bind_with_vars(
270 ty::ClauseKind::WellFormed(ty.into()),
271 bound_vars,
272 );
273 predicates.insert((predicate.upcast(tcx), span));
274 }
275 }
276
277 let mut bounds = Vec::new();
278 icx.lowerer().lower_bounds(
279 ty,
280 bound_pred.bounds,
281 &mut bounds,
282 bound_vars,
283 PredicateFilter::All,
284 );
285 predicates.extend(bounds);
286 }
287
288 hir::WherePredicateKind::RegionPredicate(region_pred) => {
289 let r1 = icx
290 .lowerer()
291 .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
292 predicates.extend(region_pred.bounds.iter().map(|bound| {
293 let (r2, span) = match bound {
294 hir::GenericBound::Outlives(lt) => (
295 icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
296 lt.ident.span,
297 ),
298 bound => {
299 span_bug!(
300 bound.span(),
301 "lifetime param bounds must be outlives, but found {bound:?}"
302 )
303 }
304 };
305 let pred =
306 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)).upcast(tcx);
307 (pred, span)
308 }))
309 }
310
311 hir::WherePredicateKind::EqPredicate(..) => {
312 }
314 }
315 }
316
317 if tcx.features().generic_const_exprs() {
318 predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
319 }
320
321 let mut predicates: Vec<_> = predicates.into_iter().collect();
322
323 if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
329 let self_ty = tcx.type_of(def_id).instantiate_identity();
330 let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
331 cgp::setup_constraining_predicates(
332 tcx,
333 &mut predicates,
334 trait_ref,
335 &mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
336 );
337 }
338
339 if let Node::OpaqueTy(..) = node {
343 compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
344 debug!(?predicates);
345 }
346
347 ty::GenericPredicates {
348 parent: generics.parent,
349 predicates: tcx.arena.alloc_from_iter(predicates),
350 }
351}
352
353fn compute_bidirectional_outlives_predicates<'tcx>(
356 tcx: TyCtxt<'tcx>,
357 opaque_own_params: &[ty::GenericParamDef],
358 predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
359) {
360 for param in opaque_own_params {
361 let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
362 if let ty::ReEarlyParam(..) = orig_lifetime.kind() {
363 let dup_lifetime = ty::Region::new_early_param(
364 tcx,
365 ty::EarlyParamRegion { index: param.index, name: param.name },
366 );
367 let span = tcx.def_span(param.def_id);
368 predicates.push((
369 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime))
370 .upcast(tcx),
371 span,
372 ));
373 predicates.push((
374 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime))
375 .upcast(tcx),
376 span,
377 ));
378 }
379 }
380}
381
382#[instrument(level = "debug", skip(tcx, predicates), ret)]
383fn const_evaluatable_predicates_of<'tcx>(
384 tcx: TyCtxt<'tcx>,
385 def_id: LocalDefId,
386 predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
387) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
388 struct ConstCollector<'tcx> {
389 tcx: TyCtxt<'tcx>,
390 preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
391 }
392
393 fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
394 let hir_id = tcx.local_def_id_to_hir_id(def);
395 let (_, parent_node) = tcx
396 .hir_parent_iter(hir_id)
397 .skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
398 .next()
399 .unwrap();
400 matches!(
401 parent_node,
402 Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
403 )
404 }
405
406 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
407 fn visit_const(&mut self, c: ty::Const<'tcx>) {
408 if let ty::ConstKind::Unevaluated(uv) = c.kind() {
409 if is_const_param_default(self.tcx, uv.def.expect_local()) {
410 return;
418 }
419
420 let span = self.tcx.def_span(uv.def);
421 self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
422 }
423 }
424 }
425
426 let hir_id = tcx.local_def_id_to_hir_id(def_id);
427 let node = tcx.hir_node(hir_id);
428
429 let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
430
431 for (clause, _sp) in predicates {
432 clause.visit_with(&mut collector);
433 }
434
435 if let hir::Node::Item(item) = node
436 && let hir::ItemKind::Impl(_) = item.kind
437 {
438 if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
439 debug!("visit impl trait_ref");
440 of_trait.instantiate_identity().visit_with(&mut collector);
441 }
442
443 debug!("visit self_ty");
444 let self_ty = tcx.type_of(def_id);
445 self_ty.instantiate_identity().visit_with(&mut collector);
446 }
447
448 if let Some(_) = tcx.hir_fn_sig_by_hir_id(hir_id) {
449 debug!("visit fn sig");
450 let fn_sig = tcx.fn_sig(def_id);
451 let fn_sig = fn_sig.instantiate_identity();
452 debug!(?fn_sig);
453 fn_sig.visit_with(&mut collector);
454 }
455
456 collector.preds
457}
458
459pub(super) fn trait_explicit_predicates_and_bounds(
460 tcx: TyCtxt<'_>,
461 def_id: LocalDefId,
462) -> ty::GenericPredicates<'_> {
463 assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
464 gather_explicit_predicates_of(tcx, def_id)
465}
466
467pub(super) fn explicit_predicates_of<'tcx>(
468 tcx: TyCtxt<'tcx>,
469 def_id: LocalDefId,
470) -> ty::GenericPredicates<'tcx> {
471 let def_kind = tcx.def_kind(def_id);
472 if let DefKind::Trait = def_kind {
473 let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
476 let trait_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
477
478 let is_assoc_item_ty = |ty: Ty<'tcx>| {
479 if let ty::Alias(ty::Projection, projection) = ty.kind() {
489 projection.args == trait_identity_args
490 && !tcx.is_impl_trait_in_trait(projection.def_id)
492 && tcx.associated_item(projection.def_id).container_id(tcx)
493 == def_id.to_def_id()
494 } else {
495 false
496 }
497 };
498
499 let predicates: Vec<_> = predicates_and_bounds
500 .predicates
501 .iter()
502 .copied()
503 .filter(|(pred, _)| match pred.kind().skip_binder() {
504 ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
505 ty::ClauseKind::Projection(proj) => {
506 !is_assoc_item_ty(proj.projection_term.self_ty())
507 }
508 ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
509 _ => true,
510 })
511 .collect();
512 if predicates.len() == predicates_and_bounds.predicates.len() {
513 predicates_and_bounds
514 } else {
515 ty::GenericPredicates {
516 parent: predicates_and_bounds.parent,
517 predicates: tcx.arena.alloc_slice(&predicates),
518 }
519 }
520 } else {
521 if matches!(def_kind, DefKind::AnonConst)
522 && tcx.features().generic_const_exprs()
523 && let Some(defaulted_param_def_id) =
524 tcx.hir_opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
525 {
526 let parent_def_id = tcx.local_parent(def_id);
539 let parent_preds = tcx.explicit_predicates_of(parent_def_id);
540
541 let filtered_predicates = parent_preds
545 .predicates
546 .into_iter()
547 .filter(|(pred, _)| {
548 if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
549 match ct.kind() {
550 ty::ConstKind::Param(param_const) => {
551 let defaulted_param_idx = tcx
552 .generics_of(parent_def_id)
553 .param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
554 param_const.index < defaulted_param_idx
555 }
556 _ => bug!(
557 "`ConstArgHasType` in `predicates_of`\
558 that isn't a `Param` const"
559 ),
560 }
561 } else {
562 true
563 }
564 })
565 .cloned();
566 return GenericPredicates {
567 parent: parent_preds.parent,
568 predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
569 };
570 }
571 gather_explicit_predicates_of(tcx, def_id)
572 }
573}
574
575pub(super) fn explicit_super_predicates_of<'tcx>(
579 tcx: TyCtxt<'tcx>,
580 trait_def_id: LocalDefId,
581) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
582 implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
583}
584
585pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>(
586 tcx: TyCtxt<'tcx>,
587 (trait_def_id, assoc_ident): (DefId, Ident),
588) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
589 implied_predicates_with_filter(
590 tcx,
591 trait_def_id,
592 PredicateFilter::SelfTraitThatDefines(assoc_ident),
593 )
594}
595
596pub(super) fn explicit_implied_predicates_of<'tcx>(
597 tcx: TyCtxt<'tcx>,
598 trait_def_id: LocalDefId,
599) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
600 implied_predicates_with_filter(
601 tcx,
602 trait_def_id.to_def_id(),
603 if tcx.is_trait_alias(trait_def_id.to_def_id()) {
604 PredicateFilter::All
605 } else {
606 PredicateFilter::SelfAndAssociatedTypeBounds
607 },
608 )
609}
610
611pub(super) fn implied_predicates_with_filter<'tcx>(
615 tcx: TyCtxt<'tcx>,
616 trait_def_id: DefId,
617 filter: PredicateFilter,
618) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
619 let Some(trait_def_id) = trait_def_id.as_local() else {
620 assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_));
623 return tcx.explicit_super_predicates_of(trait_def_id);
624 };
625
626 let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else {
627 bug!("trait_def_id {trait_def_id:?} is not an item");
628 };
629
630 let (generics, superbounds) = match item.kind {
631 hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
632 hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
633 _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
634 };
635
636 let icx = ItemCtxt::new(tcx, trait_def_id);
637
638 let self_param_ty = tcx.types.self_param;
639 let mut bounds = Vec::new();
640 icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
641 match filter {
642 PredicateFilter::All
643 | PredicateFilter::SelfOnly
644 | PredicateFilter::SelfTraitThatDefines(_)
645 | PredicateFilter::SelfAndAssociatedTypeBounds => {
646 icx.lowerer().add_default_super_traits(
647 trait_def_id,
648 &mut bounds,
649 superbounds,
650 generics,
651 item.span,
652 );
653 }
654 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
656 }
657
658 let where_bounds_that_match =
659 icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);
660
661 let implied_bounds =
663 &*tcx.arena.alloc_from_iter(bounds.into_iter().chain(where_bounds_that_match));
664 debug!(?implied_bounds);
665
666 match filter {
671 PredicateFilter::SelfOnly => {
672 for &(pred, span) in implied_bounds {
673 debug!("superbound: {:?}", pred);
674 if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
675 && bound.polarity == ty::PredicatePolarity::Positive
676 {
677 tcx.at(span).explicit_super_predicates_of(bound.def_id());
678 }
679 }
680 }
681 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
682 for &(pred, span) in implied_bounds {
683 debug!("superbound: {:?}", pred);
684 if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
685 && bound.polarity == ty::PredicatePolarity::Positive
686 {
687 tcx.at(span).explicit_implied_predicates_of(bound.def_id());
688 }
689 }
690 }
691 _ => {}
692 }
693
694 assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
695
696 ty::EarlyBinder::bind(implied_bounds)
697}
698
699pub(super) fn assert_only_contains_predicates_from<'tcx>(
703 filter: PredicateFilter,
704 bounds: &'tcx [(ty::Clause<'tcx>, Span)],
705 ty: Ty<'tcx>,
706) {
707 if !cfg!(debug_assertions) {
708 return;
709 }
710
711 match filter {
712 PredicateFilter::SelfOnly => {
713 for (clause, _) in bounds {
714 match clause.kind().skip_binder() {
715 ty::ClauseKind::Trait(trait_predicate) => {
716 assert_eq!(
717 trait_predicate.self_ty(),
718 ty,
719 "expected `Self` predicate when computing \
720 `{filter:?}` implied bounds: {clause:?}"
721 );
722 }
723 ty::ClauseKind::Projection(projection_predicate) => {
724 assert_eq!(
725 projection_predicate.self_ty(),
726 ty,
727 "expected `Self` predicate when computing \
728 `{filter:?}` implied bounds: {clause:?}"
729 );
730 }
731 ty::ClauseKind::TypeOutlives(outlives_predicate) => {
732 assert_eq!(
733 outlives_predicate.0, ty,
734 "expected `Self` predicate when computing \
735 `{filter:?}` implied bounds: {clause:?}"
736 );
737 }
738 ty::ClauseKind::HostEffect(host_effect_predicate) => {
739 assert_eq!(
740 host_effect_predicate.self_ty(),
741 ty,
742 "expected `Self` predicate when computing \
743 `{filter:?}` implied bounds: {clause:?}"
744 );
745 }
746
747 ty::ClauseKind::RegionOutlives(_)
748 | ty::ClauseKind::ConstArgHasType(_, _)
749 | ty::ClauseKind::WellFormed(_)
750 | ty::ClauseKind::ConstEvaluatable(_) => {
751 bug!(
752 "unexpected non-`Self` predicate when computing \
753 `{filter:?}` implied bounds: {clause:?}"
754 );
755 }
756 }
757 }
758 }
759 PredicateFilter::SelfTraitThatDefines(_) => {
760 for (clause, _) in bounds {
761 match clause.kind().skip_binder() {
762 ty::ClauseKind::Trait(trait_predicate) => {
763 assert_eq!(
764 trait_predicate.self_ty(),
765 ty,
766 "expected `Self` predicate when computing \
767 `{filter:?}` implied bounds: {clause:?}"
768 );
769 }
770
771 ty::ClauseKind::Projection(_)
772 | ty::ClauseKind::TypeOutlives(_)
773 | ty::ClauseKind::RegionOutlives(_)
774 | ty::ClauseKind::ConstArgHasType(_, _)
775 | ty::ClauseKind::WellFormed(_)
776 | ty::ClauseKind::ConstEvaluatable(_)
777 | ty::ClauseKind::HostEffect(..) => {
778 bug!(
779 "unexpected non-`Self` predicate when computing \
780 `{filter:?}` implied bounds: {clause:?}"
781 );
782 }
783 }
784 }
785 }
786 PredicateFilter::ConstIfConst => {
787 for (clause, _) in bounds {
788 match clause.kind().skip_binder() {
789 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
790 trait_ref: _,
791 constness: ty::BoundConstness::Maybe,
792 }) => {}
793 _ => {
794 bug!(
795 "unexpected non-`HostEffect` predicate when computing \
796 `{filter:?}` implied bounds: {clause:?}"
797 );
798 }
799 }
800 }
801 }
802 PredicateFilter::SelfConstIfConst => {
803 for (clause, _) in bounds {
804 match clause.kind().skip_binder() {
805 ty::ClauseKind::HostEffect(pred) => {
806 assert_eq!(
807 pred.constness,
808 ty::BoundConstness::Maybe,
809 "expected `~const` predicate when computing `{filter:?}` \
810 implied bounds: {clause:?}",
811 );
812 assert_eq!(
813 pred.trait_ref.self_ty(),
814 ty,
815 "expected `Self` predicate when computing `{filter:?}` \
816 implied bounds: {clause:?}"
817 );
818 }
819 _ => {
820 bug!(
821 "unexpected non-`HostEffect` predicate when computing \
822 `{filter:?}` implied bounds: {clause:?}"
823 );
824 }
825 }
826 }
827 }
828 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
829 }
830}
831
832#[instrument(level = "trace", skip(tcx))]
835pub(super) fn type_param_predicates<'tcx>(
836 tcx: TyCtxt<'tcx>,
837 (item_def_id, def_id, assoc_ident): (LocalDefId, LocalDefId, Ident),
838) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
839 match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
840 Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
841 return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_ident));
842 }
843 Some(ty::ImplTraitInTraitData::Impl { .. }) => {
844 unreachable!("should not be lowering bounds on RPITIT in impl")
845 }
846 None => {}
847 }
848
849 let param_id = tcx.local_def_id_to_hir_id(def_id);
854 let param_owner = tcx.hir_ty_param_owner(def_id);
855
856 let parent = if item_def_id == param_owner {
858 None
860 } else {
861 tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local())
862 };
863
864 let result = if let Some(parent) = parent {
865 let icx = ItemCtxt::new(tcx, parent);
866 icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_ident)
867 } else {
868 ty::EarlyBinder::bind(&[] as &[_])
869 };
870 let mut extend = None;
871
872 let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id);
873
874 let hir_node = tcx.hir_node(item_hir_id);
875 let Some(hir_generics) = hir_node.generics() else {
876 return result;
877 };
878
879 if let Node::Item(item) = hir_node
880 && let hir::ItemKind::Trait(..) = item.kind
881 && param_id == item_hir_id
883 {
884 let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id());
885 extend = Some((identity_trait_ref.upcast(tcx), item.span));
886 }
887
888 let icx = ItemCtxt::new(tcx, item_def_id);
889 let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics(
890 hir_generics,
891 def_id,
892 PredicateFilter::SelfTraitThatDefines(assoc_ident),
893 ));
894
895 let bounds =
896 &*tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates));
897
898 let self_ty = match tcx.def_kind(def_id) {
900 DefKind::TyParam => Ty::new_param(
901 tcx,
902 tcx.generics_of(item_def_id)
903 .param_def_id_to_index(tcx, def_id.to_def_id())
904 .expect("expected generic param to be owned by item"),
905 tcx.item_name(def_id.to_def_id()),
906 ),
907 DefKind::Trait | DefKind::TraitAlias => tcx.types.self_param,
908 _ => unreachable!(),
909 };
910 assert_only_contains_predicates_from(
911 PredicateFilter::SelfTraitThatDefines(assoc_ident),
912 bounds,
913 self_ty,
914 );
915
916 ty::EarlyBinder::bind(bounds)
917}
918
919impl<'tcx> ItemCtxt<'tcx> {
920 #[instrument(level = "trace", skip(self, hir_generics))]
926 fn probe_ty_param_bounds_in_generics(
927 &self,
928 hir_generics: &'tcx hir::Generics<'tcx>,
929 param_def_id: LocalDefId,
930 filter: PredicateFilter,
931 ) -> Vec<(ty::Clause<'tcx>, Span)> {
932 let mut bounds = Vec::new();
933
934 for predicate in hir_generics.predicates {
935 let hir_id = predicate.hir_id;
936 let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind else {
937 continue;
938 };
939
940 match filter {
941 _ if predicate.is_param_bound(param_def_id.to_def_id()) => {
942 }
944 PredicateFilter::All => {
945 }
947 PredicateFilter::SelfOnly
948 | PredicateFilter::SelfTraitThatDefines(_)
949 | PredicateFilter::SelfConstIfConst
950 | PredicateFilter::SelfAndAssociatedTypeBounds => continue,
951 PredicateFilter::ConstIfConst => unreachable!(),
952 }
953
954 let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty);
955
956 let bound_vars = self.tcx.late_bound_vars(hir_id);
957 self.lowerer().lower_bounds(
958 bound_ty,
959 predicate.bounds,
960 &mut bounds,
961 bound_vars,
962 filter,
963 );
964 }
965
966 bounds
967 }
968}
969
970pub(super) fn const_conditions<'tcx>(
971 tcx: TyCtxt<'tcx>,
972 def_id: LocalDefId,
973) -> ty::ConstConditions<'tcx> {
974 if !tcx.is_conditionally_const(def_id) {
975 bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}");
976 }
977
978 match tcx.opt_rpitit_info(def_id.to_def_id()) {
979 Some(
981 ty::ImplTraitInTraitData::Impl { fn_def_id }
982 | ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
983 ) => return tcx.const_conditions(fn_def_id),
984 None => {}
985 }
986
987 let (generics, trait_def_id_and_supertraits, has_parent) = match tcx.hir_node_by_def_id(def_id)
988 {
989 Node::Item(item) => match item.kind {
990 hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
991 hir::ItemKind::Fn { generics, .. } => (generics, None, false),
992 hir::ItemKind::Trait(_, _, _, generics, supertraits, _) => {
993 (generics, Some((item.owner_id.def_id, supertraits)), false)
994 }
995 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
996 },
997 Node::TraitItem(item) => match item.kind {
1002 hir::TraitItemKind::Fn(_, _) | hir::TraitItemKind::Type(_, _) => {
1003 (item.generics, None, true)
1004 }
1005 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1006 },
1007 Node::ImplItem(item) => match item.kind {
1008 hir::ImplItemKind::Fn(_, _) | hir::ImplItemKind::Type(_) => {
1009 (item.generics, None, tcx.is_conditionally_const(tcx.local_parent(def_id)))
1010 }
1011 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1012 },
1013 Node::ForeignItem(item) => match item.kind {
1014 hir::ForeignItemKind::Fn(_, _, generics) => (generics, None, false),
1015 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1016 },
1017 Node::OpaqueTy(opaque) => match opaque.origin {
1018 hir::OpaqueTyOrigin::FnReturn { parent, .. } => return tcx.const_conditions(parent),
1019 hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => {
1020 unreachable!()
1021 }
1022 },
1023 Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(),
1025 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1026 };
1027
1028 let icx = ItemCtxt::new(tcx, def_id);
1029 let mut bounds = Vec::new();
1030
1031 for pred in generics.predicates {
1032 match pred.kind {
1033 hir::WherePredicateKind::BoundPredicate(bound_pred) => {
1034 let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
1035 let bound_vars = tcx.late_bound_vars(pred.hir_id);
1036 icx.lowerer().lower_bounds(
1037 ty,
1038 bound_pred.bounds.iter(),
1039 &mut bounds,
1040 bound_vars,
1041 PredicateFilter::ConstIfConst,
1042 );
1043 }
1044 _ => {}
1045 }
1046 }
1047
1048 if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
1049 bounds.push((
1051 ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
1052 .to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
1053 DUMMY_SP,
1054 ));
1055
1056 icx.lowerer().lower_bounds(
1057 tcx.types.self_param,
1058 supertraits,
1059 &mut bounds,
1060 ty::List::empty(),
1061 PredicateFilter::ConstIfConst,
1062 );
1063 }
1064
1065 ty::ConstConditions {
1066 parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
1067 predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| {
1068 (
1069 clause.kind().map_bound(|clause| match clause {
1070 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1071 trait_ref,
1072 constness: ty::BoundConstness::Maybe,
1073 }) => trait_ref,
1074 _ => bug!("converted {clause:?}"),
1075 }),
1076 span,
1077 )
1078 })),
1079 }
1080}
1081
1082pub(super) fn explicit_implied_const_bounds<'tcx>(
1083 tcx: TyCtxt<'tcx>,
1084 def_id: LocalDefId,
1085) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
1086 if !tcx.is_conditionally_const(def_id) {
1087 bug!(
1088 "explicit_implied_const_bounds invoked for item that is not conditionally const: {def_id:?}"
1089 );
1090 }
1091
1092 let bounds = match tcx.opt_rpitit_info(def_id.to_def_id()) {
1093 Some(ty::ImplTraitInTraitData::Trait { .. }) => {
1096 explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1097 }
1098 Some(ty::ImplTraitInTraitData::Impl { .. }) => {
1099 span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds")
1100 }
1101 None => match tcx.hir_node_by_def_id(def_id) {
1102 Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
1103 implied_predicates_with_filter(
1104 tcx,
1105 def_id.to_def_id(),
1106 PredicateFilter::SelfConstIfConst,
1107 )
1108 }
1109 Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. })
1110 | Node::OpaqueTy(_) => {
1111 explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1112 }
1113 _ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"),
1114 },
1115 };
1116
1117 bounds.map_bound(|bounds| {
1118 &*tcx.arena.alloc_from_iter(bounds.iter().copied().map(|(clause, span)| {
1119 (
1120 clause.kind().map_bound(|clause| match clause {
1121 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1122 trait_ref,
1123 constness: ty::BoundConstness::Maybe,
1124 }) => trait_ref,
1125 _ => bug!("converted {clause:?}"),
1126 }),
1127 span,
1128 )
1129 }))
1130 })
1131}