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::{HirTyLowerer, PredicateFilter, RegionInferReason};
22
23#[instrument(level = "debug", skip(tcx))]
27pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
28 let mut result = tcx.explicit_predicates_of(def_id);
29 debug!("predicates_of: explicit_predicates_of({:?}) = {:?}", def_id, result);
30
31 let inferred_outlives = tcx.inferred_outlives_of(def_id);
32 if !inferred_outlives.is_empty() {
33 debug!("predicates_of: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives,);
34 let inferred_outlives_iter =
35 inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span));
36 if result.predicates.is_empty() {
37 result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter);
38 } else {
39 result.predicates = tcx.arena.alloc_from_iter(
40 result.predicates.into_iter().copied().chain(inferred_outlives_iter),
41 );
42 }
43 }
44
45 if tcx.is_trait(def_id) {
46 let span = DUMMY_SP;
64
65 result.predicates = tcx.arena.alloc_from_iter(
66 result
67 .predicates
68 .iter()
69 .copied()
70 .chain(std::iter::once((ty::TraitRef::identity(tcx, def_id).upcast(tcx), span))),
71 );
72 }
73
74 debug!("predicates_of({:?}) = {:?}", def_id, result);
75 result
76}
77
78#[instrument(level = "trace", skip(tcx), ret)]
81fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
82 use rustc_hir::*;
83
84 match tcx.opt_rpitit_info(def_id.to_def_id()) {
85 Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
86 let mut predicates = Vec::new();
87
88 let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
93 predicates
94 .extend(tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_args));
95
96 compute_bidirectional_outlives_predicates(
101 tcx,
102 &tcx.generics_of(def_id.to_def_id()).own_params
103 [tcx.generics_of(fn_def_id).own_params.len()..],
104 &mut predicates,
105 );
106
107 return ty::GenericPredicates {
108 parent: Some(tcx.parent(def_id.to_def_id())),
109 predicates: tcx.arena.alloc_from_iter(predicates),
110 };
111 }
112
113 Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
114 let trait_item_def_id = tcx.trait_item_of(def_id).unwrap();
115 let trait_assoc_predicates = tcx.explicit_predicates_of(trait_item_def_id);
116
117 let impl_assoc_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
118 let impl_def_id = tcx.parent(fn_def_id);
119 let impl_trait_ref_args =
120 tcx.impl_trait_ref(impl_def_id).unwrap().instantiate_identity().args;
121
122 let impl_assoc_args =
123 impl_assoc_identity_args.rebase_onto(tcx, impl_def_id, impl_trait_ref_args);
124
125 let impl_predicates = trait_assoc_predicates.instantiate_own(tcx, impl_assoc_args);
126
127 return ty::GenericPredicates {
128 parent: Some(impl_def_id),
129 predicates: tcx.arena.alloc_from_iter(impl_predicates),
130 };
131 }
132
133 None => {}
134 }
135
136 let hir_id = tcx.local_def_id_to_hir_id(def_id);
137 let node = tcx.hir_node(hir_id);
138
139 if let Some(sig) = node.fn_sig()
140 && let Some(sig_id) = sig.decl.opt_delegation_sig_id()
141 {
142 return inherit_predicates_for_delegation_item(tcx, def_id, sig_id);
143 }
144
145 let mut is_trait = None;
146 let mut is_default_impl_trait = None;
147
148 let icx = ItemCtxt::new(tcx, def_id);
149
150 const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
151
152 let mut predicates: FxIndexSet<(ty::Clause<'_>, Span)> = FxIndexSet::default();
155
156 let hir_generics = node.generics().unwrap_or(NO_GENERICS);
157 if let Node::Item(item) = node {
158 match item.kind {
159 ItemKind::Impl(impl_) => {
160 if let Some(of_trait) = impl_.of_trait
161 && of_trait.defaultness.is_default()
162 {
163 is_default_impl_trait = tcx
164 .impl_trait_ref(def_id)
165 .map(|t| ty::Binder::dummy(t.instantiate_identity()));
166 }
167 }
168 ItemKind::Trait(_, _, _, _, _, self_bounds, ..)
169 | ItemKind::TraitAlias(_, _, self_bounds) => {
170 is_trait = Some((self_bounds, item.span));
171 }
172 _ => {}
173 }
174 };
175
176 let generics = tcx.generics_of(def_id);
177
178 if let Some((self_bounds, span)) = is_trait {
183 let mut bounds = Vec::new();
184 icx.lowerer().lower_bounds(
185 tcx.types.self_param,
186 self_bounds,
187 &mut bounds,
188 ty::List::empty(),
189 PredicateFilter::All,
190 );
191 icx.lowerer().add_sizedness_bounds(
192 &mut bounds,
193 tcx.types.self_param,
194 self_bounds,
195 None,
196 Some(def_id),
197 span,
198 );
199 icx.lowerer().add_default_super_traits(
200 def_id,
201 &mut bounds,
202 self_bounds,
203 hir_generics,
204 span,
205 );
206 predicates.extend(bounds);
207 }
208
209 if let Some(trait_ref) = is_default_impl_trait {
218 predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id)));
219 }
220
221 for param in hir_generics.params {
225 match param.kind {
226 GenericParamKind::Lifetime { .. } => (),
227 GenericParamKind::Type { .. } => {
228 let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
229 let mut bounds = Vec::new();
230 icx.lowerer().add_sizedness_bounds(
232 &mut bounds,
233 param_ty,
234 &[],
235 Some((param.def_id, hir_generics.predicates)),
236 None,
237 param.span,
238 );
239 icx.lowerer().add_default_traits(
240 &mut bounds,
241 param_ty,
242 &[],
243 Some((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 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 if bound_pred.bounds.is_empty() {
270 if let ty::Param(_) = ty.kind() {
271 } else {
273 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 );
293 predicates.extend(bounds);
294 }
295
296 hir::WherePredicateKind::RegionPredicate(region_pred) => {
297 let r1 = icx
298 .lowerer()
299 .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
300 predicates.extend(region_pred.bounds.iter().map(|bound| {
301 let (r2, span) = match bound {
302 hir::GenericBound::Outlives(lt) => (
303 icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
304 lt.ident.span,
305 ),
306 bound => {
307 span_bug!(
308 bound.span(),
309 "lifetime param bounds must be outlives, but found {bound:?}"
310 )
311 }
312 };
313 let pred =
314 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)).upcast(tcx);
315 (pred, span)
316 }))
317 }
318
319 hir::WherePredicateKind::EqPredicate(..) => {
320 }
322 }
323 }
324
325 if tcx.features().generic_const_exprs() {
326 predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
327 }
328
329 let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
330 let allow_unstable_feature_attr =
334 find_attr!(attrs, AttributeKind::UnstableFeatureBound(i) => i)
335 .map(|i| i.as_slice())
336 .unwrap_or_default();
337
338 for (feat_name, span) in allow_unstable_feature_attr {
339 predicates.insert((ty::ClauseKind::UnstableFeature(*feat_name).upcast(tcx), *span));
340 }
341
342 let mut predicates: Vec<_> = predicates.into_iter().collect();
343
344 if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
350 let self_ty = tcx.type_of(def_id).instantiate_identity();
351 let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
352 cgp::setup_constraining_predicates(
353 tcx,
354 &mut predicates,
355 trait_ref,
356 &mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
357 );
358 }
359
360 if let Node::OpaqueTy(..) = node {
364 compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
365 debug!(?predicates);
366 }
367
368 ty::GenericPredicates {
369 parent: generics.parent,
370 predicates: tcx.arena.alloc_from_iter(predicates),
371 }
372}
373
374fn compute_bidirectional_outlives_predicates<'tcx>(
377 tcx: TyCtxt<'tcx>,
378 opaque_own_params: &[ty::GenericParamDef],
379 predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
380) {
381 for param in opaque_own_params {
382 let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
383 if let ty::ReEarlyParam(..) = orig_lifetime.kind() {
384 let dup_lifetime = ty::Region::new_early_param(
385 tcx,
386 ty::EarlyParamRegion { index: param.index, name: param.name },
387 );
388 let span = tcx.def_span(param.def_id);
389 predicates.push((
390 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime))
391 .upcast(tcx),
392 span,
393 ));
394 predicates.push((
395 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime))
396 .upcast(tcx),
397 span,
398 ));
399 }
400 }
401}
402
403#[instrument(level = "debug", skip(tcx, predicates), ret)]
404fn const_evaluatable_predicates_of<'tcx>(
405 tcx: TyCtxt<'tcx>,
406 def_id: LocalDefId,
407 predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
408) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
409 struct ConstCollector<'tcx> {
410 tcx: TyCtxt<'tcx>,
411 preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
412 }
413
414 fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
415 let hir_id = tcx.local_def_id_to_hir_id(def);
416 let (_, parent_node) = tcx
417 .hir_parent_iter(hir_id)
418 .skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
419 .next()
420 .unwrap();
421 matches!(
422 parent_node,
423 Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
424 )
425 }
426
427 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
428 fn visit_const(&mut self, c: ty::Const<'tcx>) {
429 if let ty::ConstKind::Unevaluated(uv) = c.kind() {
430 if let Some(local) = uv.def.as_local()
431 && is_const_param_default(self.tcx, local)
432 {
433 return;
441 }
442
443 let span = self.tcx.def_span(uv.def);
444 self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
445 }
446 }
447 }
448
449 let hir_id = tcx.local_def_id_to_hir_id(def_id);
450 let node = tcx.hir_node(hir_id);
451
452 let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
453
454 for (clause, _sp) in predicates {
455 clause.visit_with(&mut collector);
456 }
457
458 if let hir::Node::Item(item) = node
459 && let hir::ItemKind::Impl(_) = item.kind
460 {
461 if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
462 debug!("visit impl trait_ref");
463 of_trait.instantiate_identity().visit_with(&mut collector);
464 }
465
466 debug!("visit self_ty");
467 let self_ty = tcx.type_of(def_id);
468 self_ty.instantiate_identity().visit_with(&mut collector);
469 }
470
471 if let Some(_) = tcx.hir_fn_sig_by_hir_id(hir_id) {
472 debug!("visit fn sig");
473 let fn_sig = tcx.fn_sig(def_id);
474 let fn_sig = fn_sig.instantiate_identity();
475 debug!(?fn_sig);
476 fn_sig.visit_with(&mut collector);
477 }
478
479 collector.preds
480}
481
482pub(super) fn trait_explicit_predicates_and_bounds(
483 tcx: TyCtxt<'_>,
484 def_id: LocalDefId,
485) -> ty::GenericPredicates<'_> {
486 assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
487 gather_explicit_predicates_of(tcx, def_id)
488}
489
490pub(super) fn explicit_predicates_of<'tcx>(
491 tcx: TyCtxt<'tcx>,
492 def_id: LocalDefId,
493) -> ty::GenericPredicates<'tcx> {
494 let def_kind = tcx.def_kind(def_id);
495 if let DefKind::Trait = def_kind {
496 let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
499 let trait_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
500
501 let is_assoc_item_ty = |ty: Ty<'tcx>| {
502 if let ty::Alias(ty::Projection, projection) = ty.kind() {
512 projection.args == trait_identity_args
513 && !tcx.is_impl_trait_in_trait(projection.def_id)
515 && tcx.parent(projection.def_id) == def_id.to_def_id()
516 } else {
517 false
518 }
519 };
520
521 let predicates: Vec<_> = predicates_and_bounds
522 .predicates
523 .iter()
524 .copied()
525 .filter(|(pred, _)| match pred.kind().skip_binder() {
526 ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
527 ty::ClauseKind::Projection(proj) => {
528 !is_assoc_item_ty(proj.projection_term.self_ty())
529 }
530 ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
531 _ => true,
532 })
533 .collect();
534 if predicates.len() == predicates_and_bounds.predicates.len() {
535 predicates_and_bounds
536 } else {
537 ty::GenericPredicates {
538 parent: predicates_and_bounds.parent,
539 predicates: tcx.arena.alloc_slice(&predicates),
540 }
541 }
542 } else {
543 if matches!(def_kind, DefKind::AnonConst)
544 && tcx.features().generic_const_exprs()
545 && let Some(defaulted_param_def_id) =
546 tcx.hir_opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
547 {
548 let parent_def_id = tcx.local_parent(def_id);
561 let parent_preds = tcx.explicit_predicates_of(parent_def_id);
562
563 let filtered_predicates = parent_preds
567 .predicates
568 .into_iter()
569 .filter(|(pred, _)| {
570 if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
571 match ct.kind() {
572 ty::ConstKind::Param(param_const) => {
573 let defaulted_param_idx = tcx
574 .generics_of(parent_def_id)
575 .param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
576 param_const.index < defaulted_param_idx
577 }
578 _ => bug!(
579 "`ConstArgHasType` in `predicates_of`\
580 that isn't a `Param` const"
581 ),
582 }
583 } else {
584 true
585 }
586 })
587 .cloned();
588 return GenericPredicates {
589 parent: parent_preds.parent,
590 predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
591 };
592 }
593 gather_explicit_predicates_of(tcx, def_id)
594 }
595}
596
597pub(super) fn explicit_super_predicates_of<'tcx>(
601 tcx: TyCtxt<'tcx>,
602 trait_def_id: LocalDefId,
603) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
604 implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
605}
606
607pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>(
608 tcx: TyCtxt<'tcx>,
609 (trait_def_id, assoc_ident): (DefId, Ident),
610) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
611 implied_predicates_with_filter(
612 tcx,
613 trait_def_id,
614 PredicateFilter::SelfTraitThatDefines(assoc_ident),
615 )
616}
617
618pub(super) fn explicit_implied_predicates_of<'tcx>(
619 tcx: TyCtxt<'tcx>,
620 trait_def_id: LocalDefId,
621) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
622 implied_predicates_with_filter(
623 tcx,
624 trait_def_id.to_def_id(),
625 if tcx.is_trait_alias(trait_def_id.to_def_id()) {
626 PredicateFilter::All
627 } else {
628 PredicateFilter::SelfAndAssociatedTypeBounds
629 },
630 )
631}
632
633pub(super) fn implied_predicates_with_filter<'tcx>(
637 tcx: TyCtxt<'tcx>,
638 trait_def_id: DefId,
639 filter: PredicateFilter,
640) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
641 let Some(trait_def_id) = trait_def_id.as_local() else {
642 assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_));
645 return tcx.explicit_super_predicates_of(trait_def_id);
646 };
647
648 let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else {
649 bug!("trait_def_id {trait_def_id:?} is not an item");
650 };
651
652 let (generics, superbounds) = match item.kind {
653 hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
654 hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
655 _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
656 };
657
658 let icx = ItemCtxt::new(tcx, trait_def_id);
659
660 let self_param_ty = tcx.types.self_param;
661 let mut bounds = Vec::new();
662 icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
663 match filter {
664 PredicateFilter::All
665 | PredicateFilter::SelfOnly
666 | PredicateFilter::SelfTraitThatDefines(_)
667 | PredicateFilter::SelfAndAssociatedTypeBounds => {
668 icx.lowerer().add_default_super_traits(
669 trait_def_id,
670 &mut bounds,
671 superbounds,
672 generics,
673 item.span,
674 );
675 }
676 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
678 }
679
680 let where_bounds_that_match =
681 icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);
682
683 let implied_bounds =
685 &*tcx.arena.alloc_from_iter(bounds.into_iter().chain(where_bounds_that_match));
686 debug!(?implied_bounds);
687
688 match filter {
693 PredicateFilter::SelfOnly => {
694 for &(pred, span) in implied_bounds {
695 debug!("superbound: {:?}", pred);
696 if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
697 && bound.polarity == ty::PredicatePolarity::Positive
698 {
699 tcx.at(span).explicit_super_predicates_of(bound.def_id());
700 }
701 }
702 }
703 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
704 for &(pred, span) in implied_bounds {
705 debug!("superbound: {:?}", pred);
706 if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
707 && bound.polarity == ty::PredicatePolarity::Positive
708 {
709 tcx.at(span).explicit_implied_predicates_of(bound.def_id());
710 }
711 }
712 }
713 _ => {}
714 }
715
716 assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
717
718 ty::EarlyBinder::bind(implied_bounds)
719}
720
721pub(super) fn assert_only_contains_predicates_from<'tcx>(
725 filter: PredicateFilter,
726 bounds: &'tcx [(ty::Clause<'tcx>, Span)],
727 ty: Ty<'tcx>,
728) {
729 if !cfg!(debug_assertions) {
730 return;
731 }
732
733 match filter {
734 PredicateFilter::SelfOnly => {
735 for (clause, _) in bounds {
736 match clause.kind().skip_binder() {
737 ty::ClauseKind::Trait(trait_predicate) => {
738 assert_eq!(
739 trait_predicate.self_ty(),
740 ty,
741 "expected `Self` predicate when computing \
742 `{filter:?}` implied bounds: {clause:?}"
743 );
744 }
745 ty::ClauseKind::Projection(projection_predicate) => {
746 assert_eq!(
747 projection_predicate.self_ty(),
748 ty,
749 "expected `Self` predicate when computing \
750 `{filter:?}` implied bounds: {clause:?}"
751 );
752 }
753 ty::ClauseKind::TypeOutlives(outlives_predicate) => {
754 assert_eq!(
755 outlives_predicate.0, ty,
756 "expected `Self` predicate when computing \
757 `{filter:?}` implied bounds: {clause:?}"
758 );
759 }
760 ty::ClauseKind::HostEffect(host_effect_predicate) => {
761 assert_eq!(
762 host_effect_predicate.self_ty(),
763 ty,
764 "expected `Self` predicate when computing \
765 `{filter:?}` implied bounds: {clause:?}"
766 );
767 }
768
769 ty::ClauseKind::RegionOutlives(_)
770 | ty::ClauseKind::ConstArgHasType(_, _)
771 | ty::ClauseKind::WellFormed(_)
772 | ty::ClauseKind::UnstableFeature(_)
773 | ty::ClauseKind::ConstEvaluatable(_) => {
774 bug!(
775 "unexpected non-`Self` predicate when computing \
776 `{filter:?}` implied bounds: {clause:?}"
777 );
778 }
779 }
780 }
781 }
782 PredicateFilter::SelfTraitThatDefines(_) => {
783 for (clause, _) in bounds {
784 match clause.kind().skip_binder() {
785 ty::ClauseKind::Trait(trait_predicate) => {
786 assert_eq!(
787 trait_predicate.self_ty(),
788 ty,
789 "expected `Self` predicate when computing \
790 `{filter:?}` implied bounds: {clause:?}"
791 );
792 }
793
794 ty::ClauseKind::Projection(_)
795 | ty::ClauseKind::TypeOutlives(_)
796 | ty::ClauseKind::RegionOutlives(_)
797 | ty::ClauseKind::ConstArgHasType(_, _)
798 | ty::ClauseKind::WellFormed(_)
799 | ty::ClauseKind::ConstEvaluatable(_)
800 | ty::ClauseKind::UnstableFeature(_)
801 | ty::ClauseKind::HostEffect(..) => {
802 bug!(
803 "unexpected non-`Self` predicate when computing \
804 `{filter:?}` implied bounds: {clause:?}"
805 );
806 }
807 }
808 }
809 }
810 PredicateFilter::ConstIfConst => {
811 for (clause, _) in bounds {
812 match clause.kind().skip_binder() {
813 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
814 trait_ref: _,
815 constness: ty::BoundConstness::Maybe,
816 }) => {}
817 _ => {
818 bug!(
819 "unexpected non-`HostEffect` predicate when computing \
820 `{filter:?}` implied bounds: {clause:?}"
821 );
822 }
823 }
824 }
825 }
826 PredicateFilter::SelfConstIfConst => {
827 for (clause, _) in bounds {
828 match clause.kind().skip_binder() {
829 ty::ClauseKind::HostEffect(pred) => {
830 assert_eq!(
831 pred.constness,
832 ty::BoundConstness::Maybe,
833 "expected `[const]` predicate when computing `{filter:?}` \
834 implied bounds: {clause:?}",
835 );
836 assert_eq!(
837 pred.trait_ref.self_ty(),
838 ty,
839 "expected `Self` predicate when computing `{filter:?}` \
840 implied bounds: {clause:?}"
841 );
842 }
843 _ => {
844 bug!(
845 "unexpected non-`HostEffect` predicate when computing \
846 `{filter:?}` implied bounds: {clause:?}"
847 );
848 }
849 }
850 }
851 }
852 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
853 }
854}
855
856#[instrument(level = "trace", skip(tcx))]
859pub(super) fn type_param_predicates<'tcx>(
860 tcx: TyCtxt<'tcx>,
861 (item_def_id, def_id, assoc_ident): (LocalDefId, LocalDefId, Ident),
862) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
863 match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
864 Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
865 return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_ident));
866 }
867 Some(ty::ImplTraitInTraitData::Impl { .. }) => {
868 unreachable!("should not be lowering bounds on RPITIT in impl")
869 }
870 None => {}
871 }
872
873 let param_id = tcx.local_def_id_to_hir_id(def_id);
878 let param_owner = tcx.hir_ty_param_owner(def_id);
879
880 let parent = if item_def_id == param_owner {
882 None
884 } else {
885 tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local())
886 };
887
888 let result = if let Some(parent) = parent {
889 let icx = ItemCtxt::new(tcx, parent);
890 icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_ident)
891 } else {
892 ty::EarlyBinder::bind(&[] as &[_])
893 };
894 let mut extend = None;
895
896 let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id);
897
898 let hir_node = tcx.hir_node(item_hir_id);
899 let Some(hir_generics) = hir_node.generics() else {
900 return result;
901 };
902
903 if let Node::Item(item) = hir_node
904 && let hir::ItemKind::Trait(..) = item.kind
905 && param_id == item_hir_id
907 {
908 let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id());
909 extend = Some((identity_trait_ref.upcast(tcx), item.span));
910 }
911
912 let icx = ItemCtxt::new(tcx, item_def_id);
913 let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics(
914 hir_generics,
915 def_id,
916 PredicateFilter::SelfTraitThatDefines(assoc_ident),
917 ));
918
919 let bounds =
920 &*tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates));
921
922 let self_ty = match tcx.def_kind(def_id) {
924 DefKind::TyParam => Ty::new_param(
925 tcx,
926 tcx.generics_of(item_def_id)
927 .param_def_id_to_index(tcx, def_id.to_def_id())
928 .expect("expected generic param to be owned by item"),
929 tcx.item_name(def_id.to_def_id()),
930 ),
931 DefKind::Trait | DefKind::TraitAlias => tcx.types.self_param,
932 _ => unreachable!(),
933 };
934 assert_only_contains_predicates_from(
935 PredicateFilter::SelfTraitThatDefines(assoc_ident),
936 bounds,
937 self_ty,
938 );
939
940 ty::EarlyBinder::bind(bounds)
941}
942
943impl<'tcx> ItemCtxt<'tcx> {
944 #[instrument(level = "trace", skip(self, hir_generics))]
950 fn probe_ty_param_bounds_in_generics(
951 &self,
952 hir_generics: &'tcx hir::Generics<'tcx>,
953 param_def_id: LocalDefId,
954 filter: PredicateFilter,
955 ) -> Vec<(ty::Clause<'tcx>, Span)> {
956 let mut bounds = Vec::new();
957
958 for predicate in hir_generics.predicates {
959 let hir_id = predicate.hir_id;
960 let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind else {
961 continue;
962 };
963
964 match filter {
965 _ if predicate.is_param_bound(param_def_id.to_def_id()) => {
966 }
968 PredicateFilter::All => {
969 }
971 PredicateFilter::SelfOnly
972 | PredicateFilter::SelfTraitThatDefines(_)
973 | PredicateFilter::SelfConstIfConst
974 | PredicateFilter::SelfAndAssociatedTypeBounds => continue,
975 PredicateFilter::ConstIfConst => unreachable!(),
976 }
977
978 let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty);
979
980 let bound_vars = self.tcx.late_bound_vars(hir_id);
981 self.lowerer().lower_bounds(
982 bound_ty,
983 predicate.bounds,
984 &mut bounds,
985 bound_vars,
986 filter,
987 );
988 }
989
990 bounds
991 }
992}
993
994pub(super) fn const_conditions<'tcx>(
995 tcx: TyCtxt<'tcx>,
996 def_id: LocalDefId,
997) -> ty::ConstConditions<'tcx> {
998 if !tcx.is_conditionally_const(def_id) {
999 bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}");
1000 }
1001
1002 match tcx.opt_rpitit_info(def_id.to_def_id()) {
1003 Some(
1005 ty::ImplTraitInTraitData::Impl { fn_def_id }
1006 | ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
1007 ) => return tcx.const_conditions(fn_def_id),
1008 None => {}
1009 }
1010
1011 let (generics, trait_def_id_and_supertraits, has_parent) = match tcx.hir_node_by_def_id(def_id)
1012 {
1013 Node::Item(item) => match item.kind {
1014 hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
1015 hir::ItemKind::Fn { generics, .. } => (generics, None, false),
1016 hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => {
1017 (generics, Some((item.owner_id.def_id, supertraits)), false)
1018 }
1019 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1020 },
1021 Node::TraitItem(item) => match item.kind {
1026 hir::TraitItemKind::Fn(_, _) | hir::TraitItemKind::Type(_, _) => {
1027 (item.generics, None, true)
1028 }
1029 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1030 },
1031 Node::ImplItem(item) => match item.kind {
1032 hir::ImplItemKind::Fn(_, _) | hir::ImplItemKind::Type(_) => {
1033 (item.generics, None, tcx.is_conditionally_const(tcx.local_parent(def_id)))
1034 }
1035 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1036 },
1037 Node::ForeignItem(item) => match item.kind {
1038 hir::ForeignItemKind::Fn(_, _, generics) => (generics, None, false),
1039 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1040 },
1041 Node::OpaqueTy(opaque) => match opaque.origin {
1042 hir::OpaqueTyOrigin::FnReturn { parent, .. } => return tcx.const_conditions(parent),
1043 hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => {
1044 unreachable!()
1045 }
1046 },
1047 Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(),
1049 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1050 };
1051
1052 let icx = ItemCtxt::new(tcx, def_id);
1053 let mut bounds = Vec::new();
1054
1055 for pred in generics.predicates {
1056 match pred.kind {
1057 hir::WherePredicateKind::BoundPredicate(bound_pred) => {
1058 let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
1059 let bound_vars = tcx.late_bound_vars(pred.hir_id);
1060 icx.lowerer().lower_bounds(
1061 ty,
1062 bound_pred.bounds.iter(),
1063 &mut bounds,
1064 bound_vars,
1065 PredicateFilter::ConstIfConst,
1066 );
1067 }
1068 _ => {}
1069 }
1070 }
1071
1072 if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
1073 bounds.push((
1075 ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
1076 .to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
1077 DUMMY_SP,
1078 ));
1079
1080 icx.lowerer().lower_bounds(
1081 tcx.types.self_param,
1082 supertraits,
1083 &mut bounds,
1084 ty::List::empty(),
1085 PredicateFilter::ConstIfConst,
1086 );
1087 }
1088
1089 ty::ConstConditions {
1090 parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
1091 predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| {
1092 (
1093 clause.kind().map_bound(|clause| match clause {
1094 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1095 trait_ref,
1096 constness: ty::BoundConstness::Maybe,
1097 }) => trait_ref,
1098 _ => bug!("converted {clause:?}"),
1099 }),
1100 span,
1101 )
1102 })),
1103 }
1104}
1105
1106pub(super) fn explicit_implied_const_bounds<'tcx>(
1107 tcx: TyCtxt<'tcx>,
1108 def_id: LocalDefId,
1109) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
1110 if !tcx.is_conditionally_const(def_id) {
1111 bug!(
1112 "explicit_implied_const_bounds invoked for item that is not conditionally const: {def_id:?}"
1113 );
1114 }
1115
1116 let bounds = match tcx.opt_rpitit_info(def_id.to_def_id()) {
1117 Some(ty::ImplTraitInTraitData::Trait { .. }) => {
1120 explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1121 }
1122 Some(ty::ImplTraitInTraitData::Impl { .. }) => {
1123 span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds")
1124 }
1125 None => match tcx.hir_node_by_def_id(def_id) {
1126 Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
1127 implied_predicates_with_filter(
1128 tcx,
1129 def_id.to_def_id(),
1130 PredicateFilter::SelfConstIfConst,
1131 )
1132 }
1133 Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. })
1134 | Node::OpaqueTy(_) => {
1135 explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1136 }
1137 _ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"),
1138 },
1139 };
1140
1141 bounds.map_bound(|bounds| {
1142 &*tcx.arena.alloc_from_iter(bounds.iter().copied().map(|(clause, span)| {
1143 (
1144 clause.kind().map_bound(|clause| match clause {
1145 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1146 trait_ref,
1147 constness: ty::BoundConstness::Maybe,
1148 }) => trait_ref,
1149 _ => bug!("converted {clause:?}"),
1150 }),
1151 span,
1152 )
1153 }))
1154 })
1155}