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