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::bounds::Bounds;
17use crate::collect::ItemCtxt;
18use crate::constrained_generic_params as cgp;
19use crate::delegation::inherit_predicates_for_delegation_item;
20use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter, RegionInferReason};
21
22#[instrument(level = "debug", skip(tcx))]
26pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
27 let mut result = tcx.explicit_predicates_of(def_id);
28 debug!("predicates_of: explicit_predicates_of({:?}) = {:?}", def_id, result);
29
30 let inferred_outlives = tcx.inferred_outlives_of(def_id);
31 if !inferred_outlives.is_empty() {
32 debug!("predicates_of: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives,);
33 let inferred_outlives_iter =
34 inferred_outlives.iter().map(|(clause, span)| ((*clause).upcast(tcx), *span));
35 if result.predicates.is_empty() {
36 result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter);
37 } else {
38 result.predicates = tcx.arena.alloc_from_iter(
39 result.predicates.into_iter().copied().chain(inferred_outlives_iter),
40 );
41 }
42 }
43
44 if tcx.is_trait(def_id) {
45 let span = DUMMY_SP;
63
64 result.predicates = tcx.arena.alloc_from_iter(
65 result
66 .predicates
67 .iter()
68 .copied()
69 .chain(std::iter::once((ty::TraitRef::identity(tcx, def_id).upcast(tcx), span))),
70 );
71 }
72
73 debug!("predicates_of({:?}) = {:?}", def_id, result);
74 result
75}
76
77#[instrument(level = "trace", skip(tcx), ret)]
80fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
81 use rustc_hir::*;
82
83 match tcx.opt_rpitit_info(def_id.to_def_id()) {
84 Some(ImplTraitInTraitData::Trait { fn_def_id, .. }) => {
85 let mut predicates = Vec::new();
86
87 let identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
92 predicates
93 .extend(tcx.explicit_predicates_of(fn_def_id).instantiate_own(tcx, identity_args));
94
95 compute_bidirectional_outlives_predicates(
100 tcx,
101 &tcx.generics_of(def_id.to_def_id()).own_params
102 [tcx.generics_of(fn_def_id).own_params.len()..],
103 &mut predicates,
104 );
105
106 return ty::GenericPredicates {
107 parent: Some(tcx.parent(def_id.to_def_id())),
108 predicates: tcx.arena.alloc_from_iter(predicates),
109 };
110 }
111
112 Some(ImplTraitInTraitData::Impl { fn_def_id }) => {
113 let assoc_item = tcx.associated_item(def_id);
114 let trait_assoc_predicates =
115 tcx.explicit_predicates_of(assoc_item.trait_item_def_id.unwrap());
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 impl_.defaultness.is_default() {
161 is_default_impl_trait = tcx
162 .impl_trait_ref(def_id)
163 .map(|t| ty::Binder::dummy(t.instantiate_identity()));
164 }
165 }
166
167 ItemKind::Trait(_, _, _, self_bounds, ..) | ItemKind::TraitAlias(_, self_bounds) => {
168 is_trait = Some(self_bounds);
169 }
170 _ => {}
171 }
172 };
173
174 let generics = tcx.generics_of(def_id);
175
176 if let Some(self_bounds) = is_trait {
181 let mut bounds = Bounds::default();
182 icx.lowerer().lower_bounds(
183 tcx.types.self_param,
184 self_bounds,
185 &mut bounds,
186 ty::List::empty(),
187 PredicateFilter::All,
188 );
189 predicates.extend(bounds.clauses());
190 }
191
192 if let Some(trait_ref) = is_default_impl_trait {
201 predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id)));
202 }
203
204 for param in hir_generics.params {
208 match param.kind {
209 GenericParamKind::Lifetime { .. } => (),
210 GenericParamKind::Type { .. } => {
211 let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
212 let mut bounds = Bounds::default();
213 icx.lowerer().add_sized_bound(
215 &mut bounds,
216 param_ty,
217 &[],
218 Some((param.def_id, hir_generics.predicates)),
219 param.span,
220 );
221 trace!(?bounds);
222 predicates.extend(bounds.clauses());
223 trace!(?predicates);
224 }
225 hir::GenericParamKind::Const { .. } => {
226 let param_def_id = param.def_id.to_def_id();
227 let ct_ty = tcx
228 .type_of(param_def_id)
229 .no_bound_vars()
230 .expect("const parameters cannot be generic");
231 let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
232 predicates
233 .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
234 }
235 }
236 }
237
238 trace!(?predicates);
239 for predicate in hir_generics.predicates {
241 match predicate.kind {
242 hir::WherePredicateKind::BoundPredicate(bound_pred) => {
243 let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
244
245 let bound_vars = tcx.late_bound_vars(predicate.hir_id);
246 if bound_pred.bounds.is_empty() {
250 if let ty::Param(_) = ty.kind() {
251 } else {
258 let span = bound_pred.bounded_ty.span;
259 let predicate = ty::Binder::bind_with_vars(
260 ty::ClauseKind::WellFormed(ty.into()),
261 bound_vars,
262 );
263 predicates.insert((predicate.upcast(tcx), span));
264 }
265 }
266
267 let mut bounds = Bounds::default();
268 icx.lowerer().lower_bounds(
269 ty,
270 bound_pred.bounds,
271 &mut bounds,
272 bound_vars,
273 PredicateFilter::All,
274 );
275 predicates.extend(bounds.clauses());
276 }
277
278 hir::WherePredicateKind::RegionPredicate(region_pred) => {
279 let r1 = icx
280 .lowerer()
281 .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
282 predicates.extend(region_pred.bounds.iter().map(|bound| {
283 let (r2, span) = match bound {
284 hir::GenericBound::Outlives(lt) => (
285 icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
286 lt.ident.span,
287 ),
288 bound => {
289 span_bug!(
290 bound.span(),
291 "lifetime param bounds must be outlives, but found {bound:?}"
292 )
293 }
294 };
295 let pred =
296 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)).upcast(tcx);
297 (pred, span)
298 }))
299 }
300
301 hir::WherePredicateKind::EqPredicate(..) => {
302 }
304 }
305 }
306
307 if tcx.features().generic_const_exprs() {
308 predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
309 }
310
311 let mut predicates: Vec<_> = predicates.into_iter().collect();
312
313 if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
319 let self_ty = tcx.type_of(def_id).instantiate_identity();
320 let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
321 cgp::setup_constraining_predicates(
322 tcx,
323 &mut predicates,
324 trait_ref,
325 &mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
326 );
327 }
328
329 if let Node::OpaqueTy(..) = node {
333 compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
334 debug!(?predicates);
335 }
336
337 ty::GenericPredicates {
338 parent: generics.parent,
339 predicates: tcx.arena.alloc_from_iter(predicates),
340 }
341}
342
343fn compute_bidirectional_outlives_predicates<'tcx>(
346 tcx: TyCtxt<'tcx>,
347 opaque_own_params: &[ty::GenericParamDef],
348 predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
349) {
350 for param in opaque_own_params {
351 let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
352 if let ty::ReEarlyParam(..) = *orig_lifetime {
353 let dup_lifetime = ty::Region::new_early_param(
354 tcx,
355 ty::EarlyParamRegion { index: param.index, name: param.name },
356 );
357 let span = tcx.def_span(param.def_id);
358 predicates.push((
359 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime))
360 .upcast(tcx),
361 span,
362 ));
363 predicates.push((
364 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime))
365 .upcast(tcx),
366 span,
367 ));
368 }
369 }
370}
371
372#[instrument(level = "debug", skip(tcx, predicates), ret)]
373fn const_evaluatable_predicates_of<'tcx>(
374 tcx: TyCtxt<'tcx>,
375 def_id: LocalDefId,
376 predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
377) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
378 struct ConstCollector<'tcx> {
379 tcx: TyCtxt<'tcx>,
380 preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
381 }
382
383 fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
384 let hir_id = tcx.local_def_id_to_hir_id(def);
385 let (_, parent_node) = tcx
386 .hir()
387 .parent_iter(hir_id)
388 .skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
389 .next()
390 .unwrap();
391 matches!(
392 parent_node,
393 Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
394 )
395 }
396
397 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
398 fn visit_const(&mut self, c: ty::Const<'tcx>) {
399 if let ty::ConstKind::Unevaluated(uv) = c.kind() {
400 if is_const_param_default(self.tcx, uv.def.expect_local()) {
401 return;
409 }
410
411 let span = self.tcx.def_span(uv.def);
412 self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
413 }
414 }
415 }
416
417 let hir_id = tcx.local_def_id_to_hir_id(def_id);
418 let node = tcx.hir_node(hir_id);
419
420 let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
421
422 for (clause, _sp) in predicates {
423 clause.visit_with(&mut collector);
424 }
425
426 if let hir::Node::Item(item) = node
427 && let hir::ItemKind::Impl(_) = item.kind
428 {
429 if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
430 debug!("visit impl trait_ref");
431 of_trait.instantiate_identity().visit_with(&mut collector);
432 }
433
434 debug!("visit self_ty");
435 let self_ty = tcx.type_of(def_id);
436 self_ty.instantiate_identity().visit_with(&mut collector);
437 }
438
439 if let Some(_) = tcx.hir().fn_sig_by_hir_id(hir_id) {
440 debug!("visit fn sig");
441 let fn_sig = tcx.fn_sig(def_id);
442 let fn_sig = fn_sig.instantiate_identity();
443 debug!(?fn_sig);
444 fn_sig.visit_with(&mut collector);
445 }
446
447 collector.preds
448}
449
450pub(super) fn trait_explicit_predicates_and_bounds(
451 tcx: TyCtxt<'_>,
452 def_id: LocalDefId,
453) -> ty::GenericPredicates<'_> {
454 assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
455 gather_explicit_predicates_of(tcx, def_id)
456}
457
458pub(super) fn explicit_predicates_of<'tcx>(
459 tcx: TyCtxt<'tcx>,
460 def_id: LocalDefId,
461) -> ty::GenericPredicates<'tcx> {
462 let def_kind = tcx.def_kind(def_id);
463 if let DefKind::Trait = def_kind {
464 let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
467 let trait_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
468
469 let is_assoc_item_ty = |ty: Ty<'tcx>| {
470 if let ty::Alias(ty::Projection, projection) = ty.kind() {
480 projection.args == trait_identity_args
481 && !tcx.is_impl_trait_in_trait(projection.def_id)
483 && tcx.associated_item(projection.def_id).container_id(tcx)
484 == def_id.to_def_id()
485 } else {
486 false
487 }
488 };
489
490 let predicates: Vec<_> = predicates_and_bounds
491 .predicates
492 .iter()
493 .copied()
494 .filter(|(pred, _)| match pred.kind().skip_binder() {
495 ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
496 ty::ClauseKind::Projection(proj) => {
497 !is_assoc_item_ty(proj.projection_term.self_ty())
498 }
499 ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
500 _ => true,
501 })
502 .collect();
503 if predicates.len() == predicates_and_bounds.predicates.len() {
504 predicates_and_bounds
505 } else {
506 ty::GenericPredicates {
507 parent: predicates_and_bounds.parent,
508 predicates: tcx.arena.alloc_slice(&predicates),
509 }
510 }
511 } else {
512 if matches!(def_kind, DefKind::AnonConst)
513 && tcx.features().generic_const_exprs()
514 && let Some(defaulted_param_def_id) =
515 tcx.hir().opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
516 {
517 let parent_def_id = tcx.local_parent(def_id);
530 let parent_preds = tcx.explicit_predicates_of(parent_def_id);
531
532 let filtered_predicates = parent_preds
536 .predicates
537 .into_iter()
538 .filter(|(pred, _)| {
539 if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
540 match ct.kind() {
541 ty::ConstKind::Param(param_const) => {
542 let defaulted_param_idx = tcx
543 .generics_of(parent_def_id)
544 .param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
545 param_const.index < defaulted_param_idx
546 }
547 _ => bug!(
548 "`ConstArgHasType` in `predicates_of`\
549 that isn't a `Param` const"
550 ),
551 }
552 } else {
553 true
554 }
555 })
556 .cloned();
557 return GenericPredicates {
558 parent: parent_preds.parent,
559 predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
560 };
561 }
562 gather_explicit_predicates_of(tcx, def_id)
563 }
564}
565
566pub(super) fn explicit_super_predicates_of<'tcx>(
570 tcx: TyCtxt<'tcx>,
571 trait_def_id: LocalDefId,
572) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
573 implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
574}
575
576pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>(
577 tcx: TyCtxt<'tcx>,
578 (trait_def_id, assoc_name): (DefId, Ident),
579) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
580 implied_predicates_with_filter(
581 tcx,
582 trait_def_id,
583 PredicateFilter::SelfTraitThatDefines(assoc_name),
584 )
585}
586
587pub(super) fn explicit_implied_predicates_of<'tcx>(
588 tcx: TyCtxt<'tcx>,
589 trait_def_id: LocalDefId,
590) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
591 implied_predicates_with_filter(
592 tcx,
593 trait_def_id.to_def_id(),
594 if tcx.is_trait_alias(trait_def_id.to_def_id()) {
595 PredicateFilter::All
596 } else {
597 PredicateFilter::SelfAndAssociatedTypeBounds
598 },
599 )
600}
601
602pub(super) fn implied_predicates_with_filter<'tcx>(
606 tcx: TyCtxt<'tcx>,
607 trait_def_id: DefId,
608 filter: PredicateFilter,
609) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
610 let Some(trait_def_id) = trait_def_id.as_local() else {
611 assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_));
614 return tcx.explicit_super_predicates_of(trait_def_id);
615 };
616
617 let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else {
618 bug!("trait_def_id {trait_def_id:?} is not an item");
619 };
620
621 let (generics, superbounds) = match item.kind {
622 hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
623 hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits),
624 _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
625 };
626
627 let icx = ItemCtxt::new(tcx, trait_def_id);
628
629 let self_param_ty = tcx.types.self_param;
630 let mut bounds = Bounds::default();
631 icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
632
633 let where_bounds_that_match =
634 icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);
635
636 let implied_bounds =
638 &*tcx.arena.alloc_from_iter(bounds.clauses().chain(where_bounds_that_match));
639 debug!(?implied_bounds);
640
641 match filter {
646 PredicateFilter::SelfOnly => {
647 for &(pred, span) in implied_bounds {
648 debug!("superbound: {:?}", pred);
649 if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
650 && bound.polarity == ty::PredicatePolarity::Positive
651 {
652 tcx.at(span).explicit_super_predicates_of(bound.def_id());
653 }
654 }
655 }
656 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
657 for &(pred, span) in implied_bounds {
658 debug!("superbound: {:?}", pred);
659 if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
660 && bound.polarity == ty::PredicatePolarity::Positive
661 {
662 tcx.at(span).explicit_implied_predicates_of(bound.def_id());
663 }
664 }
665 }
666 _ => {}
667 }
668
669 assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
670
671 ty::EarlyBinder::bind(implied_bounds)
672}
673
674pub(super) fn assert_only_contains_predicates_from<'tcx>(
678 filter: PredicateFilter,
679 bounds: &'tcx [(ty::Clause<'tcx>, Span)],
680 ty: Ty<'tcx>,
681) {
682 if !cfg!(debug_assertions) {
683 return;
684 }
685
686 match filter {
687 PredicateFilter::SelfOnly => {
688 for (clause, _) in bounds {
689 match clause.kind().skip_binder() {
690 ty::ClauseKind::Trait(trait_predicate) => {
691 assert_eq!(
692 trait_predicate.self_ty(),
693 ty,
694 "expected `Self` predicate when computing \
695 `{filter:?}` implied bounds: {clause:?}"
696 );
697 }
698 ty::ClauseKind::Projection(projection_predicate) => {
699 assert_eq!(
700 projection_predicate.self_ty(),
701 ty,
702 "expected `Self` predicate when computing \
703 `{filter:?}` implied bounds: {clause:?}"
704 );
705 }
706 ty::ClauseKind::TypeOutlives(outlives_predicate) => {
707 assert_eq!(
708 outlives_predicate.0, ty,
709 "expected `Self` predicate when computing \
710 `{filter:?}` implied bounds: {clause:?}"
711 );
712 }
713 ty::ClauseKind::HostEffect(host_effect_predicate) => {
714 assert_eq!(
715 host_effect_predicate.self_ty(),
716 ty,
717 "expected `Self` predicate when computing \
718 `{filter:?}` implied bounds: {clause:?}"
719 );
720 }
721
722 ty::ClauseKind::RegionOutlives(_)
723 | ty::ClauseKind::ConstArgHasType(_, _)
724 | ty::ClauseKind::WellFormed(_)
725 | ty::ClauseKind::ConstEvaluatable(_) => {
726 bug!(
727 "unexpected non-`Self` predicate when computing \
728 `{filter:?}` implied bounds: {clause:?}"
729 );
730 }
731 }
732 }
733 }
734 PredicateFilter::SelfTraitThatDefines(_) => {
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
746 ty::ClauseKind::Projection(_)
747 | ty::ClauseKind::TypeOutlives(_)
748 | ty::ClauseKind::RegionOutlives(_)
749 | ty::ClauseKind::ConstArgHasType(_, _)
750 | ty::ClauseKind::WellFormed(_)
751 | ty::ClauseKind::ConstEvaluatable(_)
752 | ty::ClauseKind::HostEffect(..) => {
753 bug!(
754 "unexpected non-`Self` predicate when computing \
755 `{filter:?}` implied bounds: {clause:?}"
756 );
757 }
758 }
759 }
760 }
761 PredicateFilter::ConstIfConst => {
762 for (clause, _) in bounds {
763 match clause.kind().skip_binder() {
764 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
765 trait_ref: _,
766 constness: ty::BoundConstness::Maybe,
767 }) => {}
768 _ => {
769 bug!(
770 "unexpected non-`HostEffect` predicate when computing \
771 `{filter:?}` implied bounds: {clause:?}"
772 );
773 }
774 }
775 }
776 }
777 PredicateFilter::SelfConstIfConst => {
778 for (clause, _) in bounds {
779 match clause.kind().skip_binder() {
780 ty::ClauseKind::HostEffect(pred) => {
781 assert_eq!(
782 pred.constness,
783 ty::BoundConstness::Maybe,
784 "expected `~const` predicate when computing `{filter:?}` \
785 implied bounds: {clause:?}",
786 );
787 assert_eq!(
788 pred.trait_ref.self_ty(),
789 ty,
790 "expected `Self` predicate when computing `{filter:?}` \
791 implied bounds: {clause:?}"
792 );
793 }
794 _ => {
795 bug!(
796 "unexpected non-`HostEffect` predicate when computing \
797 `{filter:?}` implied bounds: {clause:?}"
798 );
799 }
800 }
801 }
802 }
803 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
804 }
805}
806
807#[instrument(level = "trace", skip(tcx))]
810pub(super) fn type_param_predicates<'tcx>(
811 tcx: TyCtxt<'tcx>,
812 (item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident),
813) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
814 match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
815 Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
816 return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_name));
817 }
818 Some(ty::ImplTraitInTraitData::Impl { .. }) => {
819 unreachable!("should not be lowering bounds on RPITIT in impl")
820 }
821 None => {}
822 }
823
824 let param_id = tcx.local_def_id_to_hir_id(def_id);
829 let param_owner = tcx.hir().ty_param_owner(def_id);
830
831 let parent = if item_def_id == param_owner {
833 None
835 } else {
836 tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local())
837 };
838
839 let result = if let Some(parent) = parent {
840 let icx = ItemCtxt::new(tcx, parent);
841 icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_name)
842 } else {
843 ty::EarlyBinder::bind(&[] as &[_])
844 };
845 let mut extend = None;
846
847 let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id);
848
849 let hir_node = tcx.hir_node(item_hir_id);
850 let Some(hir_generics) = hir_node.generics() else {
851 return result;
852 };
853
854 if let Node::Item(item) = hir_node
855 && let hir::ItemKind::Trait(..) = item.kind
856 && param_id == item_hir_id
858 {
859 let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id());
860 extend = Some((identity_trait_ref.upcast(tcx), item.span));
861 }
862
863 let icx = ItemCtxt::new(tcx, item_def_id);
864 let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics(
865 hir_generics,
866 def_id,
867 PredicateFilter::SelfTraitThatDefines(assoc_name),
868 ));
869
870 let bounds =
871 &*tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates));
872
873 let self_ty = match tcx.def_kind(def_id) {
875 DefKind::TyParam => Ty::new_param(
876 tcx,
877 tcx.generics_of(item_def_id)
878 .param_def_id_to_index(tcx, def_id.to_def_id())
879 .expect("expected generic param to be owned by item"),
880 tcx.item_name(def_id.to_def_id()),
881 ),
882 DefKind::Trait | DefKind::TraitAlias => tcx.types.self_param,
883 _ => unreachable!(),
884 };
885 assert_only_contains_predicates_from(
886 PredicateFilter::SelfTraitThatDefines(assoc_name),
887 bounds,
888 self_ty,
889 );
890
891 ty::EarlyBinder::bind(bounds)
892}
893
894impl<'tcx> ItemCtxt<'tcx> {
895 #[instrument(level = "trace", skip(self, hir_generics))]
901 fn probe_ty_param_bounds_in_generics(
902 &self,
903 hir_generics: &'tcx hir::Generics<'tcx>,
904 param_def_id: LocalDefId,
905 filter: PredicateFilter,
906 ) -> Vec<(ty::Clause<'tcx>, Span)> {
907 let mut bounds = Bounds::default();
908
909 for predicate in hir_generics.predicates {
910 let hir_id = predicate.hir_id;
911 let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind else {
912 continue;
913 };
914
915 match filter {
916 _ if predicate.is_param_bound(param_def_id.to_def_id()) => {
917 }
919 PredicateFilter::All => {
920 }
922 PredicateFilter::SelfOnly
923 | PredicateFilter::SelfTraitThatDefines(_)
924 | PredicateFilter::SelfConstIfConst
925 | PredicateFilter::SelfAndAssociatedTypeBounds => continue,
926 PredicateFilter::ConstIfConst => unreachable!(),
927 }
928
929 let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty);
930
931 let bound_vars = self.tcx.late_bound_vars(hir_id);
932 self.lowerer().lower_bounds(
933 bound_ty,
934 predicate.bounds,
935 &mut bounds,
936 bound_vars,
937 filter,
938 );
939 }
940
941 bounds.clauses().collect()
942 }
943}
944
945pub(super) fn const_conditions<'tcx>(
952 tcx: TyCtxt<'tcx>,
953 def_id: LocalDefId,
954) -> ty::ConstConditions<'tcx> {
955 if !tcx.is_conditionally_const(def_id) {
956 bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}");
957 }
958
959 match tcx.opt_rpitit_info(def_id.to_def_id()) {
960 Some(
962 ty::ImplTraitInTraitData::Impl { fn_def_id }
963 | ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
964 ) => return tcx.const_conditions(fn_def_id),
965 None => {}
966 }
967
968 let (generics, trait_def_id_and_supertraits, has_parent) = match tcx.hir_node_by_def_id(def_id)
969 {
970 Node::Item(item) => match item.kind {
971 hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
972 hir::ItemKind::Fn { generics, .. } => (generics, None, false),
973 hir::ItemKind::Trait(_, _, generics, supertraits, _) => {
974 (generics, Some((item.owner_id.def_id, supertraits)), false)
975 }
976 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
977 },
978 Node::TraitItem(item) => match item.kind {
983 hir::TraitItemKind::Fn(_, _) | hir::TraitItemKind::Type(_, _) => {
984 (item.generics, None, true)
985 }
986 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
987 },
988 Node::ImplItem(item) => match item.kind {
989 hir::ImplItemKind::Fn(_, _) | hir::ImplItemKind::Type(_) => {
990 (item.generics, None, tcx.is_conditionally_const(tcx.local_parent(def_id)))
991 }
992 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
993 },
994 Node::ForeignItem(item) => match item.kind {
995 hir::ForeignItemKind::Fn(_, _, generics) => (generics, None, false),
996 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
997 },
998 Node::OpaqueTy(opaque) => match opaque.origin {
999 hir::OpaqueTyOrigin::FnReturn { parent, .. } => return tcx.const_conditions(parent),
1000 hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => {
1001 unreachable!()
1002 }
1003 },
1004 Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(),
1006 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1007 };
1008
1009 let icx = ItemCtxt::new(tcx, def_id);
1010 let mut bounds = Bounds::default();
1011
1012 for pred in generics.predicates {
1013 match pred.kind {
1014 hir::WherePredicateKind::BoundPredicate(bound_pred) => {
1015 let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
1016 let bound_vars = tcx.late_bound_vars(pred.hir_id);
1017 icx.lowerer().lower_bounds(
1018 ty,
1019 bound_pred.bounds.iter(),
1020 &mut bounds,
1021 bound_vars,
1022 PredicateFilter::ConstIfConst,
1023 );
1024 }
1025 _ => {}
1026 }
1027 }
1028
1029 if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
1030 bounds.push_const_bound(
1031 tcx,
1032 ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())),
1033 ty::BoundConstness::Maybe,
1034 DUMMY_SP,
1035 );
1036
1037 icx.lowerer().lower_bounds(
1038 tcx.types.self_param,
1039 supertraits,
1040 &mut bounds,
1041 ty::List::empty(),
1042 PredicateFilter::ConstIfConst,
1043 );
1044 }
1045
1046 ty::ConstConditions {
1047 parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
1048 predicates: tcx.arena.alloc_from_iter(bounds.clauses().map(|(clause, span)| {
1049 (
1050 clause.kind().map_bound(|clause| match clause {
1051 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1052 trait_ref,
1053 constness: ty::BoundConstness::Maybe,
1054 }) => trait_ref,
1055 _ => bug!("converted {clause:?}"),
1056 }),
1057 span,
1058 )
1059 })),
1060 }
1061}
1062
1063pub(super) fn explicit_implied_const_bounds<'tcx>(
1064 tcx: TyCtxt<'tcx>,
1065 def_id: LocalDefId,
1066) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
1067 if !tcx.is_conditionally_const(def_id) {
1068 bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}");
1069 }
1070
1071 let bounds = match tcx.opt_rpitit_info(def_id.to_def_id()) {
1072 Some(ty::ImplTraitInTraitData::Trait { .. }) => {
1075 explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1076 }
1077 Some(ty::ImplTraitInTraitData::Impl { .. }) => {
1078 span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds")
1079 }
1080 None => match tcx.hir_node_by_def_id(def_id) {
1081 Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
1082 implied_predicates_with_filter(
1083 tcx,
1084 def_id.to_def_id(),
1085 PredicateFilter::SelfConstIfConst,
1086 )
1087 }
1088 Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. })
1089 | Node::OpaqueTy(_) => {
1090 explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1091 }
1092 _ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"),
1093 },
1094 };
1095
1096 bounds.map_bound(|bounds| {
1097 &*tcx.arena.alloc_from_iter(bounds.iter().copied().map(|(clause, span)| {
1098 (
1099 clause.kind().map_bound(|clause| match clause {
1100 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1101 trait_ref,
1102 constness: ty::BoundConstness::Maybe,
1103 }) => trait_ref,
1104 _ => bug!("converted {clause:?}"),
1105 }),
1106 span,
1107 )
1108 }))
1109 })
1110}