Skip to content

Commit 4ebc6c8

Browse files
committed
fast-reject: add counter
1 parent f005c74 commit 4ebc6c8

File tree

6 files changed

+26
-15
lines changed

6 files changed

+26
-15
lines changed

compiler/rustc_trait_selection/src/traits/coherence.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ pub fn overlapping_impls(
9898
// Before doing expensive operations like entering an inference context, do
9999
// a quick check via fast_reject to tell if the impl headers could possibly
100100
// unify.
101-
let drcx = DeepRejectCtxt::relate_infer_infer(tcx);
101+
let mut drcx = DeepRejectCtxt::relate_infer_infer(tcx);
102102
let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
103103
let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
104104
let may_overlap = match (impl1_ref, impl2_ref) {

compiler/rustc_trait_selection/src/traits/effects.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ fn evaluate_host_effect_from_bounds<'tcx>(
7979
obligation: &HostEffectObligation<'tcx>,
8080
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
8181
let infcx = selcx.infcx;
82-
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
82+
let mut drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
8383
let mut candidate = None;
8484

8585
for predicate in obligation.param_env.caller_bounds() {

compiler/rustc_trait_selection/src/traits/project.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,7 @@ fn assemble_candidates_from_predicates<'cx, 'tcx>(
866866
potentially_unnormalized_candidates: bool,
867867
) {
868868
let infcx = selcx.infcx;
869-
let drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
869+
let mut drcx = DeepRejectCtxt::relate_rigid_rigid(selcx.tcx());
870870
for predicate in env_predicates {
871871
let bound_predicate = predicate.kind();
872872
if let ty::ClauseKind::Projection(data) = predicate.kind().skip_binder() {

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
232232
.filter(|p| p.def_id() == stack.obligation.predicate.def_id())
233233
.filter(|p| p.polarity() == stack.obligation.predicate.polarity());
234234

235-
let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
235+
let mut drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
236236
let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
237237
// Keep only those bounds which may apply, and propagate overflow if it occurs.
238238
for bound in bounds {
@@ -548,7 +548,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
548548
obligation: &PolyTraitObligation<'tcx>,
549549
candidates: &mut SelectionCandidateSet<'tcx>,
550550
) {
551-
let drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
551+
let mut drcx = DeepRejectCtxt::relate_rigid_infer(self.tcx());
552552
let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
553553
self.tcx().for_each_relevant_impl(
554554
obligation.predicate.def_id(),

compiler/rustc_type_ir/src/fast_reject.rs

+19-8
Original file line numberDiff line numberDiff line change
@@ -181,41 +181,46 @@ impl<DefId> SimplifiedType<DefId> {
181181
/// We also use this function during coherence. For coherence the
182182
/// impls only have to overlap for some value, so we treat parameters
183183
/// on both sides like inference variables.
184-
#[derive(Debug, Clone, Copy)]
184+
#[derive(Debug, Clone)]
185185
pub struct DeepRejectCtxt<
186186
I: Interner,
187187
const INSTANTIATE_LHS_WITH_INFER: bool,
188188
const INSTANTIATE_RHS_WITH_INFER: bool,
189189
> {
190190
_interner: PhantomData<I>,
191+
/// We bail if the walked types are too big to avoid hangs.
192+
///
193+
/// We could alternatively use a cache to deduplicate types but this
194+
/// feels like unnecessary effort.
195+
num_non_trivial_types: usize,
191196
}
192197

193198
impl<I: Interner> DeepRejectCtxt<I, false, false> {
194199
/// Treat parameters in both the lhs and the rhs as rigid.
195200
pub fn relate_rigid_rigid(_interner: I) -> DeepRejectCtxt<I, false, false> {
196-
DeepRejectCtxt { _interner: PhantomData }
201+
DeepRejectCtxt { _interner: PhantomData, num_non_trivial_types: 0 }
197202
}
198203
}
199204

200205
impl<I: Interner> DeepRejectCtxt<I, true, true> {
201206
/// Treat parameters in both the lhs and the rhs as infer vars.
202207
pub fn relate_infer_infer(_interner: I) -> DeepRejectCtxt<I, true, true> {
203-
DeepRejectCtxt { _interner: PhantomData }
208+
DeepRejectCtxt { _interner: PhantomData, num_non_trivial_types: 0 }
204209
}
205210
}
206211

207212
impl<I: Interner> DeepRejectCtxt<I, false, true> {
208213
/// Treat parameters in the lhs as rigid, and in rhs as infer vars.
209214
pub fn relate_rigid_infer(_interner: I) -> DeepRejectCtxt<I, false, true> {
210-
DeepRejectCtxt { _interner: PhantomData }
215+
DeepRejectCtxt { _interner: PhantomData, num_non_trivial_types: 0 }
211216
}
212217
}
213218

214219
impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_WITH_INFER: bool>
215220
DeepRejectCtxt<I, INSTANTIATE_LHS_WITH_INFER, INSTANTIATE_RHS_WITH_INFER>
216221
{
217222
pub fn args_may_unify(
218-
self,
223+
&mut self,
219224
obligation_args: I::GenericArgs,
220225
impl_args: I::GenericArgs,
221226
) -> bool {
@@ -234,7 +239,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
234239
})
235240
}
236241

237-
pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool {
242+
pub fn types_may_unify(&mut self, lhs: I::Ty, rhs: I::Ty) -> bool {
238243
match rhs.kind() {
239244
// Start by checking whether the `rhs` type may unify with
240245
// pretty much everything. Just return `true` in that case.
@@ -273,6 +278,12 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
273278
| ty::Placeholder(_) => {}
274279
};
275280

281+
self.num_non_trivial_types += 1;
282+
// Arbitrary cutoff.
283+
if self.num_non_trivial_types >= 1024 {
284+
return true;
285+
}
286+
276287
// For purely rigid types, use structural equivalence.
277288
match lhs.kind() {
278289
ty::Ref(_, lhs_ty, lhs_mutbl) => match rhs.kind() {
@@ -417,7 +428,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
417428
}
418429
}
419430

420-
pub fn consts_may_unify(self, lhs: I::Const, rhs: I::Const) -> bool {
431+
pub fn consts_may_unify(&mut self, lhs: I::Const, rhs: I::Const) -> bool {
421432
match rhs.kind() {
422433
ty::ConstKind::Param(_) => {
423434
if INSTANTIATE_RHS_WITH_INFER {
@@ -465,7 +476,7 @@ impl<I: Interner, const INSTANTIATE_LHS_WITH_INFER: bool, const INSTANTIATE_RHS_
465476
}
466477
}
467478

468-
fn var_and_ty_may_unify(self, var: ty::InferTy, ty: I::Ty) -> bool {
479+
fn var_and_ty_may_unify(&mut self, var: ty::InferTy, ty: I::Ty) -> bool {
469480
if !ty.is_known_rigid() {
470481
return true;
471482
}

src/librustdoc/html/render/write_shared.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -918,8 +918,8 @@ impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> {
918918
// Be aware of `tests/rustdoc/type-alias/deeply-nested-112515.rs` which might regress.
919919
let Some(impl_did) = impl_item_id.as_def_id() else { continue };
920920
let for_ty = self.cx.tcx().type_of(impl_did).skip_binder();
921-
let reject_cx = DeepRejectCtxt::relate_infer_infer(self.cx.tcx());
922-
if !reject_cx.types_may_unify(aliased_ty, for_ty) {
921+
let mut drcx = DeepRejectCtxt::relate_infer_infer(self.cx.tcx());
922+
if !drcx.types_may_unify(aliased_ty, for_ty) {
923923
continue;
924924
}
925925
// Avoid duplicates

0 commit comments

Comments
 (0)