trait_sel: skip elaboration of sizedness supertrait
As a performance optimization, skip elaborating the supertraits of `Sized`, and if a `MetaSized` obligation is being checked, then look for a `Sized` predicate in the parameter environment. This makes the `ParamEnv` smaller which should improve compiler performance as it avoids all the iteration over the larger `ParamEnv`.
This commit is contained in:
@@ -215,6 +215,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
}
|
||||
|
||||
selcx.infcx.probe(|_| {
|
||||
let bound = util::lazily_elaborate_sizedness_candidate(
|
||||
selcx.infcx,
|
||||
obligation,
|
||||
bound,
|
||||
);
|
||||
|
||||
// We checked the polarity already
|
||||
match selcx.match_normalize_trait_ref(
|
||||
obligation,
|
||||
@@ -259,14 +265,21 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
.caller_bounds()
|
||||
.iter()
|
||||
.filter_map(|p| p.as_trait_clause())
|
||||
// Micro-optimization: filter out predicates relating to different traits.
|
||||
.filter(|p| p.def_id() == stack.obligation.predicate.def_id())
|
||||
// Micro-optimization: filter out predicates with different polarities.
|
||||
.filter(|p| p.polarity() == stack.obligation.predicate.polarity());
|
||||
|
||||
let drcx = DeepRejectCtxt::relate_rigid_rigid(self.tcx());
|
||||
let obligation_args = stack.obligation.predicate.skip_binder().trait_ref.args;
|
||||
// Keep only those bounds which may apply, and propagate overflow if it occurs.
|
||||
for bound in bounds {
|
||||
let bound =
|
||||
util::lazily_elaborate_sizedness_candidate(self.infcx, stack.obligation, bound);
|
||||
|
||||
// Micro-optimization: filter out predicates relating to different traits.
|
||||
if bound.def_id() != stack.obligation.predicate.def_id() {
|
||||
continue;
|
||||
}
|
||||
|
||||
let bound_trait_ref = bound.map_bound(|t| t.trait_ref);
|
||||
if !drcx.args_may_unify(obligation_args, bound_trait_ref.skip_binder().args) {
|
||||
continue;
|
||||
|
||||
@@ -166,10 +166,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
)
|
||||
.break_value()
|
||||
.expect("expected to index into clause that exists");
|
||||
let candidate = candidate_predicate
|
||||
let candidate_predicate = candidate_predicate
|
||||
.as_trait_clause()
|
||||
.expect("projection candidate is not a trait predicate")
|
||||
.map_bound(|t| t.trait_ref);
|
||||
.expect("projection candidate is not a trait predicate");
|
||||
let candidate_predicate =
|
||||
util::lazily_elaborate_sizedness_candidate(self.infcx, obligation, candidate_predicate);
|
||||
|
||||
let candidate = candidate_predicate.map_bound(|t| t.trait_ref);
|
||||
|
||||
let candidate = self.infcx.instantiate_binder_with_fresh_vars(
|
||||
obligation.cause.span,
|
||||
@@ -226,6 +229,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
) -> PredicateObligations<'tcx> {
|
||||
debug!(?obligation, ?param, "confirm_param_candidate");
|
||||
|
||||
let param = util::lazily_elaborate_sizedness_candidate(
|
||||
self.infcx,
|
||||
obligation,
|
||||
param.upcast(self.infcx.tcx),
|
||||
)
|
||||
.map_bound(|p| p.trait_ref);
|
||||
|
||||
// During evaluation, we already checked that this
|
||||
// where-clause trait-ref could be unified with the obligation
|
||||
// trait-ref. Repeat that unification now without any
|
||||
|
||||
Reference in New Issue
Block a user