|
1 |
| -use rustc_data_structures::fx::FxIndexSet; |
| 1 | +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; |
2 | 2 | use rustc_hir as hir;
|
| 3 | +use rustc_hir::def::DefKind; |
3 | 4 | use rustc_index::bit_set::BitSet;
|
| 5 | +#[cfg(not(bootstrap))] |
| 6 | +use rustc_middle::ty::ir::TypeVisitable; |
4 | 7 | use rustc_middle::ty::{
|
5 |
| - self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, |
| 8 | + self, ir::TypeVisitor, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, |
| 9 | + TypeSuperVisitable, |
6 | 10 | };
|
7 | 11 | use rustc_session::config::TraitSolver;
|
8 | 12 | use rustc_span::def_id::{DefId, CRATE_DEF_ID};
|
@@ -136,6 +140,19 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
|
136 | 140 | predicates.extend(environment);
|
137 | 141 | }
|
138 | 142 |
|
| 143 | + if tcx.def_kind(def_id) == DefKind::AssocFn |
| 144 | + && tcx.associated_item(def_id).container == ty::AssocItemContainer::TraitContainer |
| 145 | + { |
| 146 | + let sig = tcx.fn_sig(def_id).subst_identity(); |
| 147 | + sig.visit_with(&mut ImplTraitInTraitFinder { |
| 148 | + tcx, |
| 149 | + fn_def_id: def_id, |
| 150 | + bound_vars: sig.bound_vars(), |
| 151 | + predicates: &mut predicates, |
| 152 | + seen: FxHashSet::default(), |
| 153 | + }); |
| 154 | + } |
| 155 | + |
139 | 156 | let local_did = def_id.as_local();
|
140 | 157 | let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
|
141 | 158 |
|
@@ -222,6 +239,46 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
|
222 | 239 | traits::normalize_param_env_or_error(tcx, unnormalized_env, cause)
|
223 | 240 | }
|
224 | 241 |
|
| 242 | +/// Walk through a function type, gathering all RPITITs and installing a |
| 243 | +/// `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))` predicate into the |
| 244 | +/// predicates list. This allows us to observe that an RPITIT projects to |
| 245 | +/// its corresponding opaque within the body of a default-body trait method. |
| 246 | +struct ImplTraitInTraitFinder<'a, 'tcx> { |
| 247 | + tcx: TyCtxt<'tcx>, |
| 248 | + predicates: &'a mut Vec<Predicate<'tcx>>, |
| 249 | + fn_def_id: DefId, |
| 250 | + bound_vars: &'tcx ty::List<ty::BoundVariableKind>, |
| 251 | + seen: FxHashSet<DefId>, |
| 252 | +} |
| 253 | + |
| 254 | +impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> { |
| 255 | + fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> { |
| 256 | + if let ty::Alias(ty::Projection, alias_ty) = *ty.kind() |
| 257 | + && self.tcx.def_kind(alias_ty.def_id) == DefKind::ImplTraitPlaceholder |
| 258 | + && self.tcx.impl_trait_in_trait_parent(alias_ty.def_id) == self.fn_def_id |
| 259 | + && self.seen.insert(alias_ty.def_id) |
| 260 | + { |
| 261 | + self.predicates.push( |
| 262 | + ty::Binder::bind_with_vars( |
| 263 | + ty::ProjectionPredicate { |
| 264 | + projection_ty: alias_ty, |
| 265 | + term: self.tcx.mk_alias(ty::Opaque, alias_ty).into(), |
| 266 | + }, |
| 267 | + self.bound_vars, |
| 268 | + ) |
| 269 | + .to_predicate(self.tcx), |
| 270 | + ); |
| 271 | + |
| 272 | + for bound in self.tcx.item_bounds(alias_ty.def_id).subst_iter(self.tcx, alias_ty.substs) |
| 273 | + { |
| 274 | + bound.visit_with(self); |
| 275 | + } |
| 276 | + } |
| 277 | + |
| 278 | + ty.super_visit_with(self) |
| 279 | + } |
| 280 | +} |
| 281 | + |
225 | 282 | /// Elaborate the environment.
|
226 | 283 | ///
|
227 | 284 | /// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s
|
|
0 commit comments