Skip to content

Commit b4eaef1

Browse files
committed
apply micro optimizations to DeepRejectCtxt
1 parent 6738c1e commit b4eaef1

File tree

9 files changed

+97
-118
lines changed

9 files changed

+97
-118
lines changed

compiler/rustc_hir_typeck/src/method/suggest.rs

+3-7
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use rustc_hir::lang_items::LangItem;
2121
use rustc_hir::{self as hir, ExprKind, HirId, Node, PathSegment, QPath};
2222
use rustc_infer::infer::{self, RegionVariableOrigin};
2323
use rustc_middle::bug;
24-
use rustc_middle::ty::fast_reject::{simplify_type, DeepRejectCtxt, TreatParams};
24+
use rustc_middle::ty::fast_reject::{new_reject_ctxt, simplify_type, DeepRejectCtxt, TreatParams};
2525
use rustc_middle::ty::print::{
2626
with_crate_prefix, with_forced_trimmed_paths, PrintTraitRefExt as _,
2727
};
@@ -2234,12 +2234,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22342234
let target_ty = self
22352235
.autoderef(sugg_span, rcvr_ty)
22362236
.find(|(rcvr_ty, _)| {
2237-
DeepRejectCtxt::new(
2238-
self.tcx,
2239-
TreatParams::AsRigid,
2240-
TreatParams::InstantiateWithInfer,
2241-
)
2242-
.types_may_unify(*rcvr_ty, impl_ty)
2237+
new_reject_ctxt!(self.tcx, AsRigid, InstantiateWithInfer)
2238+
.types_may_unify(*rcvr_ty, impl_ty)
22432239
})
22442240
.map_or(impl_ty, |(ty, _)| ty)
22452241
.peel_refs();
+3-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use rustc_hir::def_id::DefId;
22
pub use rustc_type_ir::fast_reject::*;
3+
pub use rustc_type_ir::new_reject_ctxt;
34

4-
use super::TyCtxt;
5-
6-
pub type DeepRejectCtxt<'tcx> = rustc_type_ir::fast_reject::DeepRejectCtxt<TyCtxt<'tcx>>;
5+
pub type DeepRejectCtxt<I, const LHS: bool, const RHS: bool> =
6+
rustc_type_ir::fast_reject::DeepRejectCtxt<I, LHS, RHS>;
77

88
pub type SimplifiedType = rustc_type_ir::fast_reject::SimplifiedType<DefId>;

compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs

+5-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod weak_types;
66
use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams};
77
use rustc_type_ir::inherent::*;
88
use rustc_type_ir::lang_items::TraitSolverLangItem;
9-
use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
9+
use rustc_type_ir::{self as ty, new_reject_ctxt, Interner, NormalizesTo, Upcast as _};
1010
use tracing::instrument;
1111

1212
use crate::delegate::SolverDelegate;
@@ -144,12 +144,10 @@ where
144144

145145
let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
146146
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
147-
if !DeepRejectCtxt::new(ecx.cx(), TreatParams::AsRigid, TreatParams::InstantiateWithInfer)
148-
.args_may_unify(
149-
goal.predicate.alias.trait_ref(cx).args,
150-
impl_trait_ref.skip_binder().args,
151-
)
152-
{
147+
if !new_reject_ctxt!(ecx.cx(), AsRigid, InstantiateWithInfer).args_may_unify(
148+
goal.predicate.alias.trait_ref(cx).args,
149+
impl_trait_ref.skip_binder().args,
150+
) {
153151
return Err(NoSolution);
154152
}
155153

compiler/rustc_next_trait_solver/src/solve/trait_goals.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams};
66
use rustc_type_ir::inherent::*;
77
use rustc_type_ir::lang_items::TraitSolverLangItem;
88
use rustc_type_ir::visit::TypeVisitableExt as _;
9-
use rustc_type_ir::{self as ty, elaborate, Interner, TraitPredicate, Upcast as _};
9+
use rustc_type_ir::{
10+
self as ty, elaborate, new_reject_ctxt, Interner, TraitPredicate, Upcast as _,
11+
};
1012
use tracing::{instrument, trace};
1113

1214
use crate::delegate::SolverDelegate;
@@ -47,7 +49,7 @@ where
4749
let cx = ecx.cx();
4850

4951
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
50-
if !DeepRejectCtxt::new(ecx.cx(), TreatParams::AsRigid, TreatParams::InstantiateWithInfer)
52+
if !new_reject_ctxt!(ecx.cx(), AsRigid, InstantiateWithInfer)
5153
.args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
5254
{
5355
return Err(NoSolution);

compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs

+7-19
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use rustc_hir as hir;
44
use rustc_hir::def::DefKind;
55
use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
66
use rustc_middle::ty::error::{ExpectedFound, TypeError};
7-
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
7+
use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams};
88
use rustc_middle::ty::print::{FmtPrinter, Printer};
99
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty};
1010
use rustc_span::def_id::DefId;
@@ -316,12 +316,8 @@ impl<T> Trait<T> for X {
316316
{
317317
let mut has_matching_impl = false;
318318
tcx.for_each_relevant_impl(def_id, values.found, |did| {
319-
if DeepRejectCtxt::new(
320-
tcx,
321-
TreatParams::AsRigid,
322-
TreatParams::InstantiateWithInfer,
323-
)
324-
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
319+
if new_reject_ctxt!(tcx, AsRigid, InstantiateWithInfer)
320+
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
325321
{
326322
has_matching_impl = true;
327323
}
@@ -341,12 +337,8 @@ impl<T> Trait<T> for X {
341337
{
342338
let mut has_matching_impl = false;
343339
tcx.for_each_relevant_impl(def_id, values.expected, |did| {
344-
if DeepRejectCtxt::new(
345-
tcx,
346-
TreatParams::AsRigid,
347-
TreatParams::InstantiateWithInfer,
348-
)
349-
.types_may_unify(values.expected, tcx.type_of(did).skip_binder())
340+
if new_reject_ctxt!(tcx, AsRigid, InstantiateWithInfer)
341+
.types_may_unify(values.expected, tcx.type_of(did).skip_binder())
350342
{
351343
has_matching_impl = true;
352344
}
@@ -365,12 +357,8 @@ impl<T> Trait<T> for X {
365357
{
366358
let mut has_matching_impl = false;
367359
tcx.for_each_relevant_impl(def_id, values.found, |did| {
368-
if DeepRejectCtxt::new(
369-
tcx,
370-
TreatParams::AsRigid,
371-
TreatParams::InstantiateWithInfer,
372-
)
373-
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
360+
if new_reject_ctxt!(tcx, AsRigid, InstantiateWithInfer)
361+
.types_may_unify(values.found, tcx.type_of(did).skip_binder())
374362
{
375363
has_matching_impl = true;
376364
}

compiler/rustc_trait_selection/src/traits/coherence.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use rustc_middle::bug;
1515
use rustc_middle::traits::query::NoSolution;
1616
use rustc_middle::traits::solve::{CandidateSource, Certainty, Goal};
1717
use rustc_middle::traits::specialization_graph::OverlapMode;
18-
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
18+
use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams};
1919
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
2020
use rustc_middle::ty::{self, Ty, TyCtxt};
2121
pub use rustc_next_trait_solver::coherence::*;
@@ -94,11 +94,7 @@ pub fn overlapping_impls(
9494
// Before doing expensive operations like entering an inference context, do
9595
// a quick check via fast_reject to tell if the impl headers could possibly
9696
// unify.
97-
let drcx = DeepRejectCtxt::new(
98-
tcx,
99-
TreatParams::InstantiateWithInfer,
100-
TreatParams::InstantiateWithInfer,
101-
);
97+
let drcx = new_reject_ctxt!(tcx, InstantiateWithInfer, InstantiateWithInfer);
10298
let impl1_ref = tcx.impl_trait_ref(impl1_def_id);
10399
let impl2_ref = tcx.impl_trait_ref(impl2_def_id);
104100
let may_overlap = match (impl1_ref, impl2_ref) {

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

+2-6
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use hir::LangItem;
1313
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
1414
use rustc_hir as hir;
1515
use rustc_infer::traits::{Obligation, ObligationCause, PolyTraitObligation, SelectionError};
16-
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
16+
use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt, TreatParams};
1717
use rustc_middle::ty::{self, ToPolyTraitRef, Ty, TypeVisitableExt};
1818
use rustc_middle::{bug, span_bug};
1919

@@ -580,11 +580,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
580580
return;
581581
}
582582

583-
let drcx = DeepRejectCtxt::new(
584-
self.tcx(),
585-
TreatParams::AsRigid,
586-
TreatParams::InstantiateWithInfer,
587-
);
583+
let drcx = new_reject_ctxt!(self.tcx(), AsRigid, InstantiateWithInfer);
588584
let obligation_args = obligation.predicate.skip_binder().trait_ref.args;
589585
self.tcx().for_each_relevant_impl(
590586
obligation.predicate.def_id(),

compiler/rustc_type_ir/src/fast_reject.rs

+68-62
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ impl<DefId> SimplifiedType<DefId> {
173173

174174
/// Given generic arguments, could they be unified after
175175
/// replacing parameters with inference variables or placeholders.
176-
/// This behavior is toggled using the `TreatParams` fields.
176+
/// This behavior is toggled using the const generics.
177177
///
178178
/// We use this to quickly reject impl/wc candidates without needing
179179
/// to instantiate generic arguments/having to enter a probe.
@@ -182,15 +182,31 @@ impl<DefId> SimplifiedType<DefId> {
182182
/// impls only have to overlap for some value, so we treat parameters
183183
/// on both sides like inference variables.
184184
#[derive(Debug, Clone, Copy)]
185-
pub struct DeepRejectCtxt<I: Interner> {
186-
treat_lhs_params: TreatParams,
187-
treat_rhs_params: TreatParams,
185+
pub struct DeepRejectCtxt<I: Interner, const TREAT_LHS_PARAMS: bool, const TREAT_RHS_PARAMS: bool> {
188186
_interner: PhantomData<I>,
189187
}
190188

191-
impl<I: Interner> DeepRejectCtxt<I> {
192-
pub fn new(_interner: I, treat_lhs_params: TreatParams, treat_rhs_params: TreatParams) -> Self {
193-
DeepRejectCtxt { treat_lhs_params, treat_rhs_params, _interner: PhantomData }
189+
impl TreatParams {
190+
pub const fn into_bool(&self) -> bool {
191+
match *self {
192+
TreatParams::InstantiateWithInfer => true,
193+
TreatParams::AsRigid => false,
194+
}
195+
}
196+
}
197+
198+
#[macro_export]
199+
macro_rules! new_reject_ctxt {
200+
($interner:expr, $lhs:ident, $rhs:ident) => {
201+
DeepRejectCtxt::<_, {TreatParams::$lhs.into_bool()}, {TreatParams::$rhs.into_bool()}>::new($interner)
202+
}
203+
}
204+
205+
impl<I: Interner, const TREAT_LHS_PARAMS: bool, const TREAT_RHS_PARAMS: bool>
206+
DeepRejectCtxt<I, TREAT_LHS_PARAMS, TREAT_RHS_PARAMS>
207+
{
208+
pub fn new(_interner: I) -> Self {
209+
DeepRejectCtxt { _interner: PhantomData }
194210
}
195211

196212
pub fn args_may_unify(
@@ -215,45 +231,6 @@ impl<I: Interner> DeepRejectCtxt<I> {
215231

216232
pub fn types_may_unify(self, lhs: I::Ty, rhs: I::Ty) -> bool {
217233
match (lhs.kind(), rhs.kind()) {
218-
(ty::Error(_), _) | (_, ty::Error(_)) => true,
219-
220-
// As we're walking the whole type, it may encounter projections
221-
// inside of binders and what not, so we're just going to assume that
222-
// projections can unify with other stuff.
223-
//
224-
// Looking forward to lazy normalization this is the safer strategy anyways.
225-
(ty::Alias(..), _) | (_, ty::Alias(..)) => true,
226-
227-
// Bound type variables may unify with rigid types e.g. when using
228-
// non-lifetime binders.
229-
(ty::Bound(..), _) | (_, ty::Bound(..)) => true,
230-
231-
(ty::Infer(var), _) => self.var_and_ty_may_unify(var, rhs),
232-
(_, ty::Infer(var)) => self.var_and_ty_may_unify(var, lhs),
233-
234-
(ty::Param(lhs), ty::Param(rhs)) => {
235-
match (self.treat_lhs_params, self.treat_rhs_params) {
236-
(TreatParams::AsRigid, TreatParams::AsRigid) => lhs == rhs,
237-
(TreatParams::InstantiateWithInfer, _)
238-
| (_, TreatParams::InstantiateWithInfer) => true,
239-
}
240-
}
241-
(ty::Param(_), _) => self.treat_lhs_params == TreatParams::InstantiateWithInfer,
242-
(_, ty::Param(_)) => self.treat_rhs_params == TreatParams::InstantiateWithInfer,
243-
244-
// Placeholder types don't unify with anything on their own.
245-
(ty::Placeholder(lhs), ty::Placeholder(rhs)) => lhs == rhs,
246-
247-
// Purely rigid types, use structural equivalence.
248-
(ty::Bool, ty::Bool)
249-
| (ty::Char, ty::Char)
250-
| (ty::Int(_), ty::Int(_))
251-
| (ty::Uint(_), ty::Uint(_))
252-
| (ty::Float(_), ty::Float(_))
253-
| (ty::Str, ty::Str)
254-
| (ty::Never, ty::Never)
255-
| (ty::Foreign(_), ty::Foreign(_)) => lhs == rhs,
256-
257234
(ty::Ref(_, lhs_ty, lhs_mutbl), ty::Ref(_, rhs_ty, rhs_mutbl)) => {
258235
lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty)
259236
}
@@ -262,37 +239,63 @@ impl<I: Interner> DeepRejectCtxt<I> {
262239
lhs_def == rhs_def && self.args_may_unify(lhs_args, rhs_args)
263240
}
264241

265-
(ty::Pat(lhs_ty, _), ty::Pat(rhs_ty, _)) => {
266-
// FIXME(pattern_types): take pattern into account
267-
self.types_may_unify(lhs_ty, rhs_ty)
268-
}
242+
(ty::Infer(var), _) => self.var_and_ty_may_unify(var, rhs),
243+
(_, ty::Infer(var)) => self.var_and_ty_may_unify(var, lhs),
269244

270-
(ty::Slice(lhs_ty), ty::Slice(rhs_ty)) => self.types_may_unify(lhs_ty, rhs_ty),
245+
(ty::Int(_), ty::Int(_)) | (ty::Uint(_), ty::Uint(_)) => lhs == rhs,
271246

272-
(ty::Array(lhs_ty, lhs_len), ty::Array(rhs_ty, rhs_len)) => {
273-
self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len)
274-
}
247+
(ty::Param(lhs), ty::Param(rhs)) => match (TREAT_LHS_PARAMS, TREAT_RHS_PARAMS) {
248+
(false, false) => lhs == rhs,
249+
(true, _) | (_, true) => true,
250+
},
251+
252+
// As we're walking the whole type, it may encounter projections
253+
// inside of binders and what not, so we're just going to assume that
254+
// projections can unify with other stuff.
255+
//
256+
// Looking forward to lazy normalization this is the safer strategy anyways.
257+
(ty::Alias(..), _) | (_, ty::Alias(..)) => true,
258+
259+
(ty::Bound(..), _) | (_, ty::Bound(..)) => true,
260+
261+
(ty::Param(_), _) => TREAT_LHS_PARAMS,
262+
(_, ty::Param(_)) => TREAT_RHS_PARAMS,
275263

276264
(ty::Tuple(lhs), ty::Tuple(rhs)) => {
277265
lhs.len() == rhs.len()
278266
&& iter::zip(lhs.iter(), rhs.iter())
279267
.all(|(lhs, rhs)| self.types_may_unify(lhs, rhs))
280268
}
281269

270+
(ty::Array(lhs_ty, lhs_len), ty::Array(rhs_ty, rhs_len)) => {
271+
self.types_may_unify(lhs_ty, rhs_ty) && self.consts_may_unify(lhs_len, rhs_len)
272+
}
273+
282274
(ty::RawPtr(lhs_ty, lhs_mutbl), ty::RawPtr(rhs_ty, rhs_mutbl)) => {
283275
lhs_mutbl == rhs_mutbl && self.types_may_unify(lhs_ty, rhs_ty)
284276
}
285277

278+
(ty::Slice(lhs_ty), ty::Slice(rhs_ty)) => self.types_may_unify(lhs_ty, rhs_ty),
279+
280+
(ty::Float(_), ty::Float(_))
281+
| (ty::Str, ty::Str)
282+
| (ty::Bool, ty::Bool)
283+
| (ty::Char, ty::Char)
284+
| (ty::Never, ty::Never)
285+
| (ty::Foreign(_), ty::Foreign(_)) => lhs == rhs,
286+
286287
(ty::Dynamic(lhs_preds, ..), ty::Dynamic(rhs_preds, ..)) => {
287288
// Ideally we would walk the existential predicates here or at least
288289
// compare their length. But considering that the relevant `Relate` impl
289290
// actually sorts and deduplicates these, that doesn't work.
290291
lhs_preds.principal_def_id() == rhs_preds.principal_def_id()
291292
}
292293

294+
// Placeholder types don't unify with anything on their own.
295+
(ty::Placeholder(lhs), ty::Placeholder(rhs)) => lhs == rhs,
296+
293297
(ty::FnPtr(lhs_sig_tys, lhs_hdr), ty::FnPtr(rhs_sig_tys, rhs_hdr)) => {
294298
let lhs_sig_tys = lhs_sig_tys.skip_binder().inputs_and_output;
295-
296299
let rhs_sig_tys = rhs_sig_tys.skip_binder().inputs_and_output;
297300

298301
lhs_hdr == rhs_hdr
@@ -313,7 +316,14 @@ impl<I: Interner> DeepRejectCtxt<I> {
313316
ty::CoroutineWitness(rhs_def_id, rhs_args),
314317
) => lhs_def_id == rhs_def_id && self.args_may_unify(lhs_args, rhs_args),
315318

316-
(ty::Placeholder(_), _)
319+
(ty::Pat(lhs_ty, _), ty::Pat(rhs_ty, _)) => {
320+
// FIXME(pattern_types): take pattern into account
321+
self.types_may_unify(lhs_ty, rhs_ty)
322+
}
323+
324+
(ty::Error(..), _)
325+
| (_, ty::Error(..))
326+
| (ty::Placeholder(_), _)
317327
| (_, ty::Placeholder(_))
318328
| (ty::Bool, _)
319329
| (_, ty::Bool)
@@ -371,12 +381,8 @@ impl<I: Interner> DeepRejectCtxt<I> {
371381
(ty::ConstKind::Value(..), ty::ConstKind::Placeholder(_))
372382
| (ty::ConstKind::Placeholder(_), ty::ConstKind::Value(..)) => false,
373383

374-
(ty::ConstKind::Param(_), ty::ConstKind::Value(..)) => {
375-
self.treat_lhs_params == TreatParams::InstantiateWithInfer
376-
}
377-
(ty::ConstKind::Value(..), ty::ConstKind::Param(_)) => {
378-
self.treat_rhs_params == TreatParams::InstantiateWithInfer
379-
}
384+
(ty::ConstKind::Param(_), ty::ConstKind::Value(..)) => TREAT_LHS_PARAMS,
385+
(ty::ConstKind::Value(..), ty::ConstKind::Param(_)) => TREAT_RHS_PARAMS,
380386

381387
_ => true,
382388
}

src/librustdoc/html/render/write_shared.rs

+3-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use indexmap::IndexMap;
99
use itertools::Itertools;
1010
use rustc_data_structures::flock;
1111
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
12-
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
12+
use rustc_middle::ty::fast_reject::{new_reject_ctxt, DeepRejectCtxt};
1313
use rustc_span::def_id::DefId;
1414
use rustc_span::Symbol;
1515
use serde::ser::SerializeSeq;
@@ -507,11 +507,8 @@ else if (window.initSearch) window.initSearch(searchIndex);
507507
// Be aware of `tests/rustdoc/type-alias/deeply-nested-112515.rs` which might regress.
508508
let Some(impl_did) = impl_item_id.as_def_id() else { continue };
509509
let for_ty = self.cx.tcx().type_of(impl_did).skip_binder();
510-
let reject_cx = DeepRejectCtxt::new(
511-
self.cx.tcx(),
512-
TreatParams::InstantiateWithInfer,
513-
TreatParams::InstantiateWithInfer,
514-
);
510+
let reject_cx =
511+
new_reject_ctxt!(self.cx.tcx(), InstantiateWithInfer, InstantiateWithInfer);
515512
if !reject_cx.types_may_unify(aliased_ty, for_ty) {
516513
continue;
517514
}

0 commit comments

Comments
 (0)