1use std::assert_matches::assert_matches;
2
3use hir::Node;
4use rustc_attr_data_structures::{AttributeKind, find_attr};
5use rustc_data_structures::fx::FxIndexSet;
6use rustc_hir as hir;
7use rustc_hir::def::DefKind;
8use rustc_hir::def_id::{DefId, LocalDefId};
9use rustc_middle::ty::{
10 self, GenericPredicates, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast,
11};
12use rustc_middle::{bug, span_bug};
13use rustc_span::{DUMMY_SP, Ident, Span};
14use tracing::{debug, instrument, trace};
15
16use super::item_bounds::explicit_item_bounds_with_filter;
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 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, span)) = is_trait {
187 let mut bounds = Vec::new();
188 icx.lowerer().lower_bounds(
189 tcx.types.self_param,
190 self_bounds,
191 &mut bounds,
192 ty::List::empty(),
193 PredicateFilter::All,
194 );
195 icx.lowerer().add_sizedness_bounds(
196 &mut bounds,
197 tcx.types.self_param,
198 self_bounds,
199 None,
200 Some(def_id),
201 span,
202 );
203 icx.lowerer().add_default_super_traits(
204 def_id,
205 &mut bounds,
206 self_bounds,
207 hir_generics,
208 span,
209 );
210 predicates.extend(bounds);
211 }
212
213 if let Some(trait_ref) = is_default_impl_trait {
222 predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id)));
223 }
224
225 for param in hir_generics.params {
229 match param.kind {
230 GenericParamKind::Lifetime { .. } => (),
231 GenericParamKind::Type { .. } => {
232 let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
233 let mut bounds = Vec::new();
234 icx.lowerer().add_sizedness_bounds(
236 &mut bounds,
237 param_ty,
238 &[],
239 Some((param.def_id, hir_generics.predicates)),
240 None,
241 param.span,
242 );
243 icx.lowerer().add_default_traits(
244 &mut bounds,
245 param_ty,
246 &[],
247 Some((param.def_id, hir_generics.predicates)),
248 param.span,
249 );
250 trace!(?bounds);
251 predicates.extend(bounds);
252 trace!(?predicates);
253 }
254 hir::GenericParamKind::Const { .. } => {
255 let param_def_id = param.def_id.to_def_id();
256 let ct_ty = tcx.type_of(param_def_id).instantiate_identity();
257 let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id);
258 predicates
259 .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span));
260 }
261 }
262 }
263
264 trace!(?predicates);
265 for predicate in hir_generics.predicates {
267 match predicate.kind {
268 hir::WherePredicateKind::BoundPredicate(bound_pred) => {
269 let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
270 let bound_vars = tcx.late_bound_vars(predicate.hir_id);
271
272 if bound_pred.bounds.is_empty() {
274 if let ty::Param(_) = ty.kind() {
275 } else {
277 let span = bound_pred.bounded_ty.span;
281 let predicate = ty::Binder::bind_with_vars(
282 ty::ClauseKind::WellFormed(ty.into()),
283 bound_vars,
284 );
285 predicates.insert((predicate.upcast(tcx), span));
286 }
287 }
288
289 let mut bounds = Vec::new();
290 icx.lowerer().lower_bounds(
291 ty,
292 bound_pred.bounds,
293 &mut bounds,
294 bound_vars,
295 PredicateFilter::All,
296 );
297 predicates.extend(bounds);
298 }
299
300 hir::WherePredicateKind::RegionPredicate(region_pred) => {
301 let r1 = icx
302 .lowerer()
303 .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate);
304 predicates.extend(region_pred.bounds.iter().map(|bound| {
305 let (r2, span) = match bound {
306 hir::GenericBound::Outlives(lt) => (
307 icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate),
308 lt.ident.span,
309 ),
310 bound => {
311 span_bug!(
312 bound.span(),
313 "lifetime param bounds must be outlives, but found {bound:?}"
314 )
315 }
316 };
317 let pred =
318 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)).upcast(tcx);
319 (pred, span)
320 }))
321 }
322
323 hir::WherePredicateKind::EqPredicate(..) => {
324 }
326 }
327 }
328
329 if tcx.features().generic_const_exprs() {
330 predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates));
331 }
332
333 let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(def_id));
334 let allow_unstable_feature_attr =
338 find_attr!(attrs, AttributeKind::UnstableFeatureBound(i) => i)
339 .map(|i| i.as_slice())
340 .unwrap_or_default();
341
342 for (feat_name, span) in allow_unstable_feature_attr {
343 predicates.insert((ty::ClauseKind::UnstableFeature(*feat_name).upcast(tcx), *span));
344 }
345
346 let mut predicates: Vec<_> = predicates.into_iter().collect();
347
348 if let Node::Item(&Item { kind: ItemKind::Impl { .. }, .. }) = node {
354 let self_ty = tcx.type_of(def_id).instantiate_identity();
355 let trait_ref = tcx.impl_trait_ref(def_id).map(ty::EarlyBinder::instantiate_identity);
356 cgp::setup_constraining_predicates(
357 tcx,
358 &mut predicates,
359 trait_ref,
360 &mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
361 );
362 }
363
364 if let Node::OpaqueTy(..) = node {
368 compute_bidirectional_outlives_predicates(tcx, &generics.own_params, &mut predicates);
369 debug!(?predicates);
370 }
371
372 ty::GenericPredicates {
373 parent: generics.parent,
374 predicates: tcx.arena.alloc_from_iter(predicates),
375 }
376}
377
378fn compute_bidirectional_outlives_predicates<'tcx>(
381 tcx: TyCtxt<'tcx>,
382 opaque_own_params: &[ty::GenericParamDef],
383 predicates: &mut Vec<(ty::Clause<'tcx>, Span)>,
384) {
385 for param in opaque_own_params {
386 let orig_lifetime = tcx.map_opaque_lifetime_to_parent_lifetime(param.def_id.expect_local());
387 if let ty::ReEarlyParam(..) = orig_lifetime.kind() {
388 let dup_lifetime = ty::Region::new_early_param(
389 tcx,
390 ty::EarlyParamRegion { index: param.index, name: param.name },
391 );
392 let span = tcx.def_span(param.def_id);
393 predicates.push((
394 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime))
395 .upcast(tcx),
396 span,
397 ));
398 predicates.push((
399 ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime))
400 .upcast(tcx),
401 span,
402 ));
403 }
404 }
405}
406
407#[instrument(level = "debug", skip(tcx, predicates), ret)]
408fn const_evaluatable_predicates_of<'tcx>(
409 tcx: TyCtxt<'tcx>,
410 def_id: LocalDefId,
411 predicates: &FxIndexSet<(ty::Clause<'tcx>, Span)>,
412) -> FxIndexSet<(ty::Clause<'tcx>, Span)> {
413 struct ConstCollector<'tcx> {
414 tcx: TyCtxt<'tcx>,
415 preds: FxIndexSet<(ty::Clause<'tcx>, Span)>,
416 }
417
418 fn is_const_param_default(tcx: TyCtxt<'_>, def: LocalDefId) -> bool {
419 let hir_id = tcx.local_def_id_to_hir_id(def);
420 let (_, parent_node) = tcx
421 .hir_parent_iter(hir_id)
422 .skip_while(|(_, n)| matches!(n, Node::ConstArg(..)))
423 .next()
424 .unwrap();
425 matches!(
426 parent_node,
427 Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { .. }, .. })
428 )
429 }
430
431 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ConstCollector<'tcx> {
432 fn visit_const(&mut self, c: ty::Const<'tcx>) {
433 if let ty::ConstKind::Unevaluated(uv) = c.kind() {
434 if let Some(local) = uv.def.as_local()
435 && is_const_param_default(self.tcx, local)
436 {
437 return;
445 }
446
447 let span = self.tcx.def_span(uv.def);
448 self.preds.insert((ty::ClauseKind::ConstEvaluatable(c).upcast(self.tcx), span));
449 }
450 }
451 }
452
453 let hir_id = tcx.local_def_id_to_hir_id(def_id);
454 let node = tcx.hir_node(hir_id);
455
456 let mut collector = ConstCollector { tcx, preds: FxIndexSet::default() };
457
458 for (clause, _sp) in predicates {
459 clause.visit_with(&mut collector);
460 }
461
462 if let hir::Node::Item(item) = node
463 && let hir::ItemKind::Impl(_) = item.kind
464 {
465 if let Some(of_trait) = tcx.impl_trait_ref(def_id) {
466 debug!("visit impl trait_ref");
467 of_trait.instantiate_identity().visit_with(&mut collector);
468 }
469
470 debug!("visit self_ty");
471 let self_ty = tcx.type_of(def_id);
472 self_ty.instantiate_identity().visit_with(&mut collector);
473 }
474
475 if let Some(_) = tcx.hir_fn_sig_by_hir_id(hir_id) {
476 debug!("visit fn sig");
477 let fn_sig = tcx.fn_sig(def_id);
478 let fn_sig = fn_sig.instantiate_identity();
479 debug!(?fn_sig);
480 fn_sig.visit_with(&mut collector);
481 }
482
483 collector.preds
484}
485
486pub(super) fn trait_explicit_predicates_and_bounds(
487 tcx: TyCtxt<'_>,
488 def_id: LocalDefId,
489) -> ty::GenericPredicates<'_> {
490 assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
491 gather_explicit_predicates_of(tcx, def_id)
492}
493
494pub(super) fn explicit_predicates_of<'tcx>(
495 tcx: TyCtxt<'tcx>,
496 def_id: LocalDefId,
497) -> ty::GenericPredicates<'tcx> {
498 let def_kind = tcx.def_kind(def_id);
499 if let DefKind::Trait = def_kind {
500 let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
503 let trait_identity_args = ty::GenericArgs::identity_for_item(tcx, def_id);
504
505 let is_assoc_item_ty = |ty: Ty<'tcx>| {
506 if let ty::Alias(ty::Projection, projection) = ty.kind() {
516 projection.args == trait_identity_args
517 && !tcx.is_impl_trait_in_trait(projection.def_id)
519 && tcx.associated_item(projection.def_id).container_id(tcx)
520 == def_id.to_def_id()
521 } else {
522 false
523 }
524 };
525
526 let predicates: Vec<_> = predicates_and_bounds
527 .predicates
528 .iter()
529 .copied()
530 .filter(|(pred, _)| match pred.kind().skip_binder() {
531 ty::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()),
532 ty::ClauseKind::Projection(proj) => {
533 !is_assoc_item_ty(proj.projection_term.self_ty())
534 }
535 ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0),
536 _ => true,
537 })
538 .collect();
539 if predicates.len() == predicates_and_bounds.predicates.len() {
540 predicates_and_bounds
541 } else {
542 ty::GenericPredicates {
543 parent: predicates_and_bounds.parent,
544 predicates: tcx.arena.alloc_slice(&predicates),
545 }
546 }
547 } else {
548 if matches!(def_kind, DefKind::AnonConst)
549 && tcx.features().generic_const_exprs()
550 && let Some(defaulted_param_def_id) =
551 tcx.hir_opt_const_param_default_param_def_id(tcx.local_def_id_to_hir_id(def_id))
552 {
553 let parent_def_id = tcx.local_parent(def_id);
566 let parent_preds = tcx.explicit_predicates_of(parent_def_id);
567
568 let filtered_predicates = parent_preds
572 .predicates
573 .into_iter()
574 .filter(|(pred, _)| {
575 if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() {
576 match ct.kind() {
577 ty::ConstKind::Param(param_const) => {
578 let defaulted_param_idx = tcx
579 .generics_of(parent_def_id)
580 .param_def_id_to_index[&defaulted_param_def_id.to_def_id()];
581 param_const.index < defaulted_param_idx
582 }
583 _ => bug!(
584 "`ConstArgHasType` in `predicates_of`\
585 that isn't a `Param` const"
586 ),
587 }
588 } else {
589 true
590 }
591 })
592 .cloned();
593 return GenericPredicates {
594 parent: parent_preds.parent,
595 predicates: { tcx.arena.alloc_from_iter(filtered_predicates) },
596 };
597 }
598 gather_explicit_predicates_of(tcx, def_id)
599 }
600}
601
602pub(super) fn explicit_super_predicates_of<'tcx>(
606 tcx: TyCtxt<'tcx>,
607 trait_def_id: LocalDefId,
608) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
609 implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
610}
611
612pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>(
613 tcx: TyCtxt<'tcx>,
614 (trait_def_id, assoc_ident): (DefId, Ident),
615) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
616 implied_predicates_with_filter(
617 tcx,
618 trait_def_id,
619 PredicateFilter::SelfTraitThatDefines(assoc_ident),
620 )
621}
622
623pub(super) fn explicit_implied_predicates_of<'tcx>(
624 tcx: TyCtxt<'tcx>,
625 trait_def_id: LocalDefId,
626) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
627 implied_predicates_with_filter(
628 tcx,
629 trait_def_id.to_def_id(),
630 if tcx.is_trait_alias(trait_def_id.to_def_id()) {
631 PredicateFilter::All
632 } else {
633 PredicateFilter::SelfAndAssociatedTypeBounds
634 },
635 )
636}
637
638pub(super) fn implied_predicates_with_filter<'tcx>(
642 tcx: TyCtxt<'tcx>,
643 trait_def_id: DefId,
644 filter: PredicateFilter,
645) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
646 let Some(trait_def_id) = trait_def_id.as_local() else {
647 assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_));
650 return tcx.explicit_super_predicates_of(trait_def_id);
651 };
652
653 let Node::Item(item) = tcx.hir_node_by_def_id(trait_def_id) else {
654 bug!("trait_def_id {trait_def_id:?} is not an item");
655 };
656
657 let (generics, superbounds) = match item.kind {
658 hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
659 hir::ItemKind::TraitAlias(_, generics, supertraits) => (generics, supertraits),
660 _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
661 };
662
663 let icx = ItemCtxt::new(tcx, trait_def_id);
664
665 let self_param_ty = tcx.types.self_param;
666 let mut bounds = Vec::new();
667 icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
668 match filter {
669 PredicateFilter::All
670 | PredicateFilter::SelfOnly
671 | PredicateFilter::SelfTraitThatDefines(_)
672 | PredicateFilter::SelfAndAssociatedTypeBounds => {
673 icx.lowerer().add_default_super_traits(
674 trait_def_id,
675 &mut bounds,
676 superbounds,
677 generics,
678 item.span,
679 );
680 }
681 PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
683 }
684
685 let where_bounds_that_match =
686 icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);
687
688 let implied_bounds =
690 &*tcx.arena.alloc_from_iter(bounds.into_iter().chain(where_bounds_that_match));
691 debug!(?implied_bounds);
692
693 match filter {
698 PredicateFilter::SelfOnly => {
699 for &(pred, span) in implied_bounds {
700 debug!("superbound: {:?}", pred);
701 if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
702 && bound.polarity == ty::PredicatePolarity::Positive
703 {
704 tcx.at(span).explicit_super_predicates_of(bound.def_id());
705 }
706 }
707 }
708 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
709 for &(pred, span) in implied_bounds {
710 debug!("superbound: {:?}", pred);
711 if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder()
712 && bound.polarity == ty::PredicatePolarity::Positive
713 {
714 tcx.at(span).explicit_implied_predicates_of(bound.def_id());
715 }
716 }
717 }
718 _ => {}
719 }
720
721 assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
722
723 ty::EarlyBinder::bind(implied_bounds)
724}
725
726pub(super) fn assert_only_contains_predicates_from<'tcx>(
730 filter: PredicateFilter,
731 bounds: &'tcx [(ty::Clause<'tcx>, Span)],
732 ty: Ty<'tcx>,
733) {
734 if !cfg!(debug_assertions) {
735 return;
736 }
737
738 match filter {
739 PredicateFilter::SelfOnly => {
740 for (clause, _) in bounds {
741 match clause.kind().skip_binder() {
742 ty::ClauseKind::Trait(trait_predicate) => {
743 assert_eq!(
744 trait_predicate.self_ty(),
745 ty,
746 "expected `Self` predicate when computing \
747 `{filter:?}` implied bounds: {clause:?}"
748 );
749 }
750 ty::ClauseKind::Projection(projection_predicate) => {
751 assert_eq!(
752 projection_predicate.self_ty(),
753 ty,
754 "expected `Self` predicate when computing \
755 `{filter:?}` implied bounds: {clause:?}"
756 );
757 }
758 ty::ClauseKind::TypeOutlives(outlives_predicate) => {
759 assert_eq!(
760 outlives_predicate.0, ty,
761 "expected `Self` predicate when computing \
762 `{filter:?}` implied bounds: {clause:?}"
763 );
764 }
765 ty::ClauseKind::HostEffect(host_effect_predicate) => {
766 assert_eq!(
767 host_effect_predicate.self_ty(),
768 ty,
769 "expected `Self` predicate when computing \
770 `{filter:?}` implied bounds: {clause:?}"
771 );
772 }
773
774 ty::ClauseKind::RegionOutlives(_)
775 | ty::ClauseKind::ConstArgHasType(_, _)
776 | ty::ClauseKind::WellFormed(_)
777 | ty::ClauseKind::UnstableFeature(_)
778 | ty::ClauseKind::ConstEvaluatable(_) => {
779 bug!(
780 "unexpected non-`Self` predicate when computing \
781 `{filter:?}` implied bounds: {clause:?}"
782 );
783 }
784 }
785 }
786 }
787 PredicateFilter::SelfTraitThatDefines(_) => {
788 for (clause, _) in bounds {
789 match clause.kind().skip_binder() {
790 ty::ClauseKind::Trait(trait_predicate) => {
791 assert_eq!(
792 trait_predicate.self_ty(),
793 ty,
794 "expected `Self` predicate when computing \
795 `{filter:?}` implied bounds: {clause:?}"
796 );
797 }
798
799 ty::ClauseKind::Projection(_)
800 | ty::ClauseKind::TypeOutlives(_)
801 | ty::ClauseKind::RegionOutlives(_)
802 | ty::ClauseKind::ConstArgHasType(_, _)
803 | ty::ClauseKind::WellFormed(_)
804 | ty::ClauseKind::ConstEvaluatable(_)
805 | ty::ClauseKind::UnstableFeature(_)
806 | ty::ClauseKind::HostEffect(..) => {
807 bug!(
808 "unexpected non-`Self` predicate when computing \
809 `{filter:?}` implied bounds: {clause:?}"
810 );
811 }
812 }
813 }
814 }
815 PredicateFilter::ConstIfConst => {
816 for (clause, _) in bounds {
817 match clause.kind().skip_binder() {
818 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
819 trait_ref: _,
820 constness: ty::BoundConstness::Maybe,
821 }) => {}
822 _ => {
823 bug!(
824 "unexpected non-`HostEffect` predicate when computing \
825 `{filter:?}` implied bounds: {clause:?}"
826 );
827 }
828 }
829 }
830 }
831 PredicateFilter::SelfConstIfConst => {
832 for (clause, _) in bounds {
833 match clause.kind().skip_binder() {
834 ty::ClauseKind::HostEffect(pred) => {
835 assert_eq!(
836 pred.constness,
837 ty::BoundConstness::Maybe,
838 "expected `[const]` predicate when computing `{filter:?}` \
839 implied bounds: {clause:?}",
840 );
841 assert_eq!(
842 pred.trait_ref.self_ty(),
843 ty,
844 "expected `Self` predicate when computing `{filter:?}` \
845 implied bounds: {clause:?}"
846 );
847 }
848 _ => {
849 bug!(
850 "unexpected non-`HostEffect` predicate when computing \
851 `{filter:?}` implied bounds: {clause:?}"
852 );
853 }
854 }
855 }
856 }
857 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
858 }
859}
860
861#[instrument(level = "trace", skip(tcx))]
864pub(super) fn type_param_predicates<'tcx>(
865 tcx: TyCtxt<'tcx>,
866 (item_def_id, def_id, assoc_ident): (LocalDefId, LocalDefId, Ident),
867) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
868 match tcx.opt_rpitit_info(item_def_id.to_def_id()) {
869 Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
870 return tcx.type_param_predicates((opaque_def_id.expect_local(), def_id, assoc_ident));
871 }
872 Some(ty::ImplTraitInTraitData::Impl { .. }) => {
873 unreachable!("should not be lowering bounds on RPITIT in impl")
874 }
875 None => {}
876 }
877
878 let param_id = tcx.local_def_id_to_hir_id(def_id);
883 let param_owner = tcx.hir_ty_param_owner(def_id);
884
885 let parent = if item_def_id == param_owner {
887 None
889 } else {
890 tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local())
891 };
892
893 let result = if let Some(parent) = parent {
894 let icx = ItemCtxt::new(tcx, parent);
895 icx.probe_ty_param_bounds(DUMMY_SP, def_id, assoc_ident)
896 } else {
897 ty::EarlyBinder::bind(&[] as &[_])
898 };
899 let mut extend = None;
900
901 let item_hir_id = tcx.local_def_id_to_hir_id(item_def_id);
902
903 let hir_node = tcx.hir_node(item_hir_id);
904 let Some(hir_generics) = hir_node.generics() else {
905 return result;
906 };
907
908 if let Node::Item(item) = hir_node
909 && let hir::ItemKind::Trait(..) = item.kind
910 && param_id == item_hir_id
912 {
913 let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id());
914 extend = Some((identity_trait_ref.upcast(tcx), item.span));
915 }
916
917 let icx = ItemCtxt::new(tcx, item_def_id);
918 let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics(
919 hir_generics,
920 def_id,
921 PredicateFilter::SelfTraitThatDefines(assoc_ident),
922 ));
923
924 let bounds =
925 &*tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates));
926
927 let self_ty = match tcx.def_kind(def_id) {
929 DefKind::TyParam => Ty::new_param(
930 tcx,
931 tcx.generics_of(item_def_id)
932 .param_def_id_to_index(tcx, def_id.to_def_id())
933 .expect("expected generic param to be owned by item"),
934 tcx.item_name(def_id.to_def_id()),
935 ),
936 DefKind::Trait | DefKind::TraitAlias => tcx.types.self_param,
937 _ => unreachable!(),
938 };
939 assert_only_contains_predicates_from(
940 PredicateFilter::SelfTraitThatDefines(assoc_ident),
941 bounds,
942 self_ty,
943 );
944
945 ty::EarlyBinder::bind(bounds)
946}
947
948impl<'tcx> ItemCtxt<'tcx> {
949 #[instrument(level = "trace", skip(self, hir_generics))]
955 fn probe_ty_param_bounds_in_generics(
956 &self,
957 hir_generics: &'tcx hir::Generics<'tcx>,
958 param_def_id: LocalDefId,
959 filter: PredicateFilter,
960 ) -> Vec<(ty::Clause<'tcx>, Span)> {
961 let mut bounds = Vec::new();
962
963 for predicate in hir_generics.predicates {
964 let hir_id = predicate.hir_id;
965 let hir::WherePredicateKind::BoundPredicate(predicate) = predicate.kind else {
966 continue;
967 };
968
969 match filter {
970 _ if predicate.is_param_bound(param_def_id.to_def_id()) => {
971 }
973 PredicateFilter::All => {
974 }
976 PredicateFilter::SelfOnly
977 | PredicateFilter::SelfTraitThatDefines(_)
978 | PredicateFilter::SelfConstIfConst
979 | PredicateFilter::SelfAndAssociatedTypeBounds => continue,
980 PredicateFilter::ConstIfConst => unreachable!(),
981 }
982
983 let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty);
984
985 let bound_vars = self.tcx.late_bound_vars(hir_id);
986 self.lowerer().lower_bounds(
987 bound_ty,
988 predicate.bounds,
989 &mut bounds,
990 bound_vars,
991 filter,
992 );
993 }
994
995 bounds
996 }
997}
998
999pub(super) fn const_conditions<'tcx>(
1000 tcx: TyCtxt<'tcx>,
1001 def_id: LocalDefId,
1002) -> ty::ConstConditions<'tcx> {
1003 if !tcx.is_conditionally_const(def_id) {
1004 bug!("const_conditions invoked for item that is not conditionally const: {def_id:?}");
1005 }
1006
1007 match tcx.opt_rpitit_info(def_id.to_def_id()) {
1008 Some(
1010 ty::ImplTraitInTraitData::Impl { fn_def_id }
1011 | ty::ImplTraitInTraitData::Trait { fn_def_id, .. },
1012 ) => return tcx.const_conditions(fn_def_id),
1013 None => {}
1014 }
1015
1016 let (generics, trait_def_id_and_supertraits, has_parent) = match tcx.hir_node_by_def_id(def_id)
1017 {
1018 Node::Item(item) => match item.kind {
1019 hir::ItemKind::Impl(impl_) => (impl_.generics, None, false),
1020 hir::ItemKind::Fn { generics, .. } => (generics, None, false),
1021 hir::ItemKind::Trait(_, _, _, _, generics, supertraits, _) => {
1022 (generics, Some((item.owner_id.def_id, supertraits)), false)
1023 }
1024 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1025 },
1026 Node::TraitItem(item) => match item.kind {
1031 hir::TraitItemKind::Fn(_, _) | hir::TraitItemKind::Type(_, _) => {
1032 (item.generics, None, true)
1033 }
1034 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1035 },
1036 Node::ImplItem(item) => match item.kind {
1037 hir::ImplItemKind::Fn(_, _) | hir::ImplItemKind::Type(_) => {
1038 (item.generics, None, tcx.is_conditionally_const(tcx.local_parent(def_id)))
1039 }
1040 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1041 },
1042 Node::ForeignItem(item) => match item.kind {
1043 hir::ForeignItemKind::Fn(_, _, generics) => (generics, None, false),
1044 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1045 },
1046 Node::OpaqueTy(opaque) => match opaque.origin {
1047 hir::OpaqueTyOrigin::FnReturn { parent, .. } => return tcx.const_conditions(parent),
1048 hir::OpaqueTyOrigin::AsyncFn { .. } | hir::OpaqueTyOrigin::TyAlias { .. } => {
1049 unreachable!()
1050 }
1051 },
1052 Node::Ctor(hir::VariantData::Tuple { .. }) => return Default::default(),
1054 _ => bug!("const_conditions called on wrong item: {def_id:?}"),
1055 };
1056
1057 let icx = ItemCtxt::new(tcx, def_id);
1058 let mut bounds = Vec::new();
1059
1060 for pred in generics.predicates {
1061 match pred.kind {
1062 hir::WherePredicateKind::BoundPredicate(bound_pred) => {
1063 let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
1064 let bound_vars = tcx.late_bound_vars(pred.hir_id);
1065 icx.lowerer().lower_bounds(
1066 ty,
1067 bound_pred.bounds.iter(),
1068 &mut bounds,
1069 bound_vars,
1070 PredicateFilter::ConstIfConst,
1071 );
1072 }
1073 _ => {}
1074 }
1075 }
1076
1077 if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
1078 bounds.push((
1080 ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
1081 .to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
1082 DUMMY_SP,
1083 ));
1084
1085 icx.lowerer().lower_bounds(
1086 tcx.types.self_param,
1087 supertraits,
1088 &mut bounds,
1089 ty::List::empty(),
1090 PredicateFilter::ConstIfConst,
1091 );
1092 }
1093
1094 ty::ConstConditions {
1095 parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
1096 predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| {
1097 (
1098 clause.kind().map_bound(|clause| match clause {
1099 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1100 trait_ref,
1101 constness: ty::BoundConstness::Maybe,
1102 }) => trait_ref,
1103 _ => bug!("converted {clause:?}"),
1104 }),
1105 span,
1106 )
1107 })),
1108 }
1109}
1110
1111pub(super) fn explicit_implied_const_bounds<'tcx>(
1112 tcx: TyCtxt<'tcx>,
1113 def_id: LocalDefId,
1114) -> ty::EarlyBinder<'tcx, &'tcx [(ty::PolyTraitRef<'tcx>, Span)]> {
1115 if !tcx.is_conditionally_const(def_id) {
1116 bug!(
1117 "explicit_implied_const_bounds invoked for item that is not conditionally const: {def_id:?}"
1118 );
1119 }
1120
1121 let bounds = match tcx.opt_rpitit_info(def_id.to_def_id()) {
1122 Some(ty::ImplTraitInTraitData::Trait { .. }) => {
1125 explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1126 }
1127 Some(ty::ImplTraitInTraitData::Impl { .. }) => {
1128 span_bug!(tcx.def_span(def_id), "RPITIT in impl should not have item bounds")
1129 }
1130 None => match tcx.hir_node_by_def_id(def_id) {
1131 Node::Item(hir::Item { kind: hir::ItemKind::Trait(..), .. }) => {
1132 implied_predicates_with_filter(
1133 tcx,
1134 def_id.to_def_id(),
1135 PredicateFilter::SelfConstIfConst,
1136 )
1137 }
1138 Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), .. })
1139 | Node::OpaqueTy(_) => {
1140 explicit_item_bounds_with_filter(tcx, def_id, PredicateFilter::ConstIfConst)
1141 }
1142 _ => bug!("explicit_implied_const_bounds called on wrong item: {def_id:?}"),
1143 },
1144 };
1145
1146 bounds.map_bound(|bounds| {
1147 &*tcx.arena.alloc_from_iter(bounds.iter().copied().map(|(clause, span)| {
1148 (
1149 clause.kind().map_bound(|clause| match clause {
1150 ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
1151 trait_ref,
1152 constness: ty::BoundConstness::Maybe,
1153 }) => trait_ref,
1154 _ => bug!("converted {clause:?}"),
1155 }),
1156 span,
1157 )
1158 }))
1159 })
1160}