Skip to content

Commit d42a3fb

Browse files
Assume we can normalize trait default method RPITITs in param-env instead
1 parent be55ad5 commit d42a3fb

File tree

3 files changed

+81
-4
lines changed

3 files changed

+81
-4
lines changed

compiler/rustc_hir_analysis/src/check/wfcheck.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1599,7 +1599,7 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>(
15991599
{
16001600
for arg in fn_output.walk() {
16011601
if let ty::GenericArgKind::Type(ty) = arg.unpack()
1602-
&& let ty::Alias(ty::Projection, proj) = ty.kind()
1602+
&& let ty::Alias(ty::Opaque, proj) = ty.kind()
16031603
&& tcx.def_kind(proj.def_id) == DefKind::ImplTraitPlaceholder
16041604
&& tcx.impl_trait_in_trait_parent(proj.def_id) == fn_def_id.to_def_id()
16051605
{

compiler/rustc_middle/src/ty/util.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
44
use crate::mir;
55
use crate::ty::layout::IntegerExt;
66
use crate::ty::{
7-
self, ir::TypeFolder, DefIdTree, FallibleTypeFolder, Ty, TyCtxt, TypeFoldable,
7+
self, ir::TypeFolder, DefIdTree, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable,
88
TypeSuperFoldable,
99
};
1010
use crate::ty::{GenericArgKind, SubstsRef};
@@ -865,6 +865,26 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> {
865865
}
866866
t
867867
}
868+
869+
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
870+
if let ty::PredicateKind::Clause(clause) = p.kind().skip_binder()
871+
&& let ty::Clause::Projection(projection_pred) = clause
872+
{
873+
p.kind()
874+
.rebind(ty::ProjectionPredicate {
875+
projection_ty: projection_pred.projection_ty.fold_with(self),
876+
// Don't fold the term on the RHS of the projection predicate.
877+
// This is because for default trait methods with RPITITs, we
878+
// install a `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))`
879+
// predicate, which would trivially cause a cycle when we do
880+
// anything that requires `ParamEnv::with_reveal_all_normalized`.
881+
term: projection_pred.term,
882+
})
883+
.to_predicate(self.tcx)
884+
} else {
885+
p.super_fold_with(self)
886+
}
887+
}
868888
}
869889

870890
impl<'tcx> Ty<'tcx> {

compiler/rustc_ty_utils/src/ty.rs

+59-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
use rustc_data_structures::fx::FxIndexSet;
1+
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
22
use rustc_hir as hir;
3+
use rustc_hir::def::DefKind;
34
use rustc_index::bit_set::BitSet;
5+
#[cfg(not(bootstrap))]
6+
use rustc_middle::ty::ir::TypeVisitable;
47
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,
610
};
711
use rustc_session::config::TraitSolver;
812
use rustc_span::def_id::{DefId, CRATE_DEF_ID};
@@ -136,6 +140,19 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
136140
predicates.extend(environment);
137141
}
138142

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+
139156
let local_did = def_id.as_local();
140157
let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
141158

@@ -222,6 +239,46 @@ fn param_env(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamEnv<'_> {
222239
traits::normalize_param_env_or_error(tcx, unnormalized_env, cause)
223240
}
224241

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+
225282
/// Elaborate the environment.
226283
///
227284
/// Collect a list of `Predicate`'s used for building the `ParamEnv`. Adds `TypeWellFormedFromEnv`'s

0 commit comments

Comments
 (0)