|
1 | 1 | use std::marker::PhantomData;
|
2 | 2 |
|
3 | 3 | use smallvec::smallvec;
|
| 4 | +use tracing::trace; |
4 | 5 |
|
5 | 6 | use crate::data_structures::HashSet;
|
6 | 7 | use crate::inherent::*;
|
| 8 | +use crate::lang_items::TraitSolverLangItem; |
7 | 9 | use crate::outlives::{push_outlives_components, Component};
|
8 |
| -use crate::{self as ty, Interner, Upcast as _}; |
| 10 | +use crate::{self as ty, AliasTy, Interner, Upcast as _}; |
9 | 11 |
|
10 | 12 | /// "Elaboration" is the process of identifying all the predicates that
|
11 | 13 | /// are implied by a source predicate. Currently, this basically means
|
@@ -89,6 +91,55 @@ impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
|
89 | 91 | return;
|
90 | 92 | }
|
91 | 93 |
|
| 94 | + // N.B. this is a bit of a hack to get implied bounds for effects working.. |
| 95 | + if cx.is_lang_item(data.def_id(), TraitSolverLangItem::EffectsCompat) |
| 96 | + && matches!(self.mode, Filter::All) |
| 97 | + { |
| 98 | + // first, ensure that the predicate we've got looks like a `<T as Tr>::Fx: EffectsCompat<somebool>`. |
| 99 | + // our plan is to gather information such that we elaborate into `<T as SuperTr>::Fx: EffectsCompat<somebool>` |
| 100 | + // when we know that `trait Tr: ~const SuperTr`. |
| 101 | + if let ty::Alias(ty::AliasTyKind::Projection, alias_ty) = data.self_ty().kind() |
| 102 | + { |
| 103 | + // look for effects-level bounds that look like `<Self as Tr>::Fx: TyCompat<<Self as SuperTr>::Fx>`, |
| 104 | + // which is proof to us that `Tr: ~const SuperTr`. |
| 105 | + let bounds = cx.explicit_implied_predicates_of(cx.parent(alias_ty.def_id)); |
| 106 | + let expected_args_with_self = |
| 107 | + I::GenericArgs::identity_for_item(cx, alias_ty.def_id); |
| 108 | + let elaborated = bounds.iter_identity().filter_map(|(clause, _)| { |
| 109 | + let ty::ClauseKind::Trait(data2) = clause.kind().skip_binder() else { |
| 110 | + return None; |
| 111 | + }; |
| 112 | + if !cx |
| 113 | + .is_lang_item(data2.def_id(), TraitSolverLangItem::EffectsTyCompat) |
| 114 | + { |
| 115 | + return None; |
| 116 | + }; |
| 117 | + let ty2 = data2.trait_ref.args.type_at(1); |
| 118 | + let ty::Alias(ty::AliasTyKind::Projection, alias_ty2) = ty2.kind() |
| 119 | + else { |
| 120 | + return None; |
| 121 | + }; |
| 122 | + if alias_ty2.args != expected_args_with_self { |
| 123 | + return None; |
| 124 | + }; |
| 125 | + |
| 126 | + // important: create `<T as SuperTr>::Fx`, this will need to use the original `alias_ty`'s args |
| 127 | + // for the `T` as Self type. |
| 128 | + let alias_new = |
| 129 | + AliasTy::new_from_args(cx, alias_ty2.def_id, alias_ty.args); |
| 130 | + let alias = |
| 131 | + I::Ty::new_alias(cx, ty::AliasTyKind::Projection, alias_new); |
| 132 | + let mut data = data; |
| 133 | + let mut new_args = data.trait_ref.args.to_vec(); |
| 134 | + new_args[0] = alias.into(); |
| 135 | + data.trait_ref.args = cx.mk_args(&new_args); |
| 136 | + |
| 137 | + Some(elaboratable.child(bound_clause.rebind(data).upcast(cx))) |
| 138 | + }); |
| 139 | + self.extend_deduped(elaborated); |
| 140 | + } |
| 141 | + } |
| 142 | + |
92 | 143 | let map_to_child_clause =
|
93 | 144 | |(index, (clause, span)): (usize, (I::Clause, I::Span))| {
|
94 | 145 | elaboratable.child_with_derived_cause(
|
|
0 commit comments