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