33
44use rustc_data_structures::fx::FxIndexMap;
55use rustc_hir::LangItem;
6- use rustc_hir::def::DefKind;
7- use rustc_middle::ty::fold::FnMutDelegate;
86use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
97use rustc_span::Span;
10- use rustc_span::def_id::DefId;
11-
12- use crate::hir_ty_lowering::PredicateFilter;
138
149/// Collects together a list of type bounds. These lists of bounds occur in many places
1510/// in Rust's syntax:
@@ -47,12 +42,9 @@ impl<'tcx> Bounds<'tcx> {
4742 pub(crate) fn push_trait_bound(
4843 &mut self,
4944 tcx: TyCtxt<'tcx>,
50- defining_def_id: DefId,
5145 bound_trait_ref: ty::PolyTraitRef<'tcx>,
5246 span: Span,
5347 polarity: ty::PredicatePolarity,
54- constness: Option<ty::BoundConstness>,
55- predicate_filter: PredicateFilter,
5648 ) {
5749 let clause = (
5850 bound_trait_ref
@@ -68,137 +60,6 @@ impl<'tcx> Bounds<'tcx> {
6860 } else {
6961 self.clauses.push(clause);
7062 }
71-
72- // FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
73- // Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
74- // type bounds.
75- if !tcx.features().effects() {
76- return;
77- }
78- match predicate_filter {
79- PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
80- return;
81- }
82- PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
83- // Ok.
84- }
85- }
86-
87- // For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
88- // associated type of `<T as Tr>` and make sure that the effect is compatible.
89- let compat_val = match (tcx.def_kind(defining_def_id), constness) {
90- // FIXME(effects): revisit the correctness of this
91- (_, Some(ty::BoundConstness::Const)) => tcx.consts.false_,
92- // body owners that can have trait bounds
93- (
94- DefKind::Const | DefKind::Fn | DefKind::AssocFn,
95- Some(ty::BoundConstness::ConstIfConst),
96- ) => tcx.expected_host_effect_param_for_body(defining_def_id),
97-
98- (_, None) => {
99- if !tcx.is_const_trait(bound_trait_ref.def_id()) {
100- return;
101- }
102- tcx.consts.true_
103- }
104- (DefKind::Trait, Some(ty::BoundConstness::ConstIfConst)) => {
105- // we are in a trait, where `bound_trait_ref` could be:
106- // (1) a super trait `trait Foo: ~const Bar`.
107- // - This generates `<Self as Foo>::Effects: TyCompat<<Self as Bar>::Effects>`
108- //
109- // (2) a where clause `where for<..> Something: ~const Bar`.
110- // - This generates `for<..> <Self as Foo>::Effects: TyCompat<<Something as Bar>::Effects>`
111- let Some(own_fx) = tcx.associated_type_for_effects(defining_def_id) else {
112- tcx.dcx().span_delayed_bug(span, "should not have allowed `~const` on a trait that doesn't have `#[const_trait]`");
113- return;
114- };
115- let own_fx_ty = Ty::new_projection(
116- tcx,
117- own_fx,
118- ty::GenericArgs::identity_for_item(tcx, own_fx),
119- );
120- let Some(their_fx) = tcx.associated_type_for_effects(bound_trait_ref.def_id())
121- else {
122- tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
123- return;
124- };
125- let their_fx_ty =
126- Ty::new_projection(tcx, their_fx, bound_trait_ref.skip_binder().args);
127- let compat = tcx.require_lang_item(LangItem::EffectsTyCompat, Some(span));
128- let clause = bound_trait_ref
129- .map_bound(|_| {
130- let trait_ref = ty::TraitRef::new(tcx, compat, [own_fx_ty, their_fx_ty]);
131- ty::ClauseKind::Trait(ty::TraitPredicate {
132- trait_ref,
133- polarity: ty::PredicatePolarity::Positive,
134- })
135- })
136- .upcast(tcx);
137-
138- self.clauses.push((clause, span));
139- return;
140- }
141-
142- (DefKind::Impl { of_trait: true }, Some(ty::BoundConstness::ConstIfConst)) => {
143- // this is a where clause on an impl header.
144- // push `<T as Tr>::Effects` into the set for the `Min` bound.
145- let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
146- tcx.dcx().span_delayed_bug(span, "`~const` on trait without Effects assoc");
147- return;
148- };
149-
150- let ty = bound_trait_ref
151- .map_bound(|trait_ref| Ty::new_projection(tcx, assoc, trait_ref.args));
152-
153- // When the user has written `for<'a, T> X<'a, T>: ~const Foo`, replace the
154- // binders to dummy ones i.e. `X<'static, ()>` so they can be referenced in
155- // the `Min` associated type properly (which doesn't allow using `for<>`)
156- // This should work for any bound variables as long as they don't have any
157- // bounds e.g. `for<T: Trait>`.
158- // FIXME(effects) reconsider this approach to allow compatibility with `for<T: Tr>`
159- let ty = tcx.replace_bound_vars_uncached(ty, FnMutDelegate {
160- regions: &mut |_| tcx.lifetimes.re_static,
161- types: &mut |_| tcx.types.unit,
162- consts: &mut |_| unimplemented!("`~const` does not support const binders"),
163- });
164-
165- self.effects_min_tys.insert(ty, span);
166- return;
167- }
168- // for
169- // ```
170- // trait Foo { type Bar: ~const Trait }
171- // ```
172- // ensure that `<Self::Bar as Trait>::Effects: TyCompat<Self::Effects>`.
173- //
174- // FIXME(effects) this is equality for now, which wouldn't be helpful for a non-const implementor
175- // that uses a `Bar` that implements `Trait` with `Maybe` effects.
176- (DefKind::AssocTy, Some(ty::BoundConstness::ConstIfConst)) => {
177- // FIXME(effects): implement this
178- return;
179- }
180- // probably illegal in this position.
181- (_, Some(ty::BoundConstness::ConstIfConst)) => {
182- tcx.dcx().span_delayed_bug(span, "invalid `~const` encountered");
183- return;
184- }
185- };
186- // create a new projection type `<T as Tr>::Effects`
187- let Some(assoc) = tcx.associated_type_for_effects(bound_trait_ref.def_id()) else {
188- tcx.dcx().span_delayed_bug(
189- span,
190- "`~const` trait bound has no effect assoc yet no errors encountered?",
191- );
192- return;
193- };
194- let self_ty = Ty::new_projection(tcx, assoc, bound_trait_ref.skip_binder().args);
195- // make `<T as Tr>::Effects: Compat<runtime>`
196- let new_trait_ref =
197- ty::TraitRef::new(tcx, tcx.require_lang_item(LangItem::EffectsCompat, Some(span)), [
198- ty::GenericArg::from(self_ty),
199- compat_val.into(),
200- ]);
201- self.clauses.push((bound_trait_ref.rebind(new_trait_ref).upcast(tcx), span));
20263 }
20364
20465 pub(crate) fn push_projection_bound(
0 commit comments