Skip to content

Commit 4ef7257

Browse files
Rollup merge of rust-lang#112442 - compiler-errors:next-solver-deduplicate-region-constraints, r=lcnr
Deduplicate identical region constraints in new solver the new solver doesn't track whether we've already proven a goal like the fulfillment context's obligation forest does, so we may be instantiating a canonical response (and specifically, its nested region obligations) quite a few times. This may lead to exponentially gathering up identical region constraints for things like auto traits, so let's deduplicate region constraints when in `compute_external_query_constraints`. r? ``@lcnr``
2 parents f83c8e4 + d5e25d4 commit 4ef7257

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

Diff for: compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
1212
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
1313
use crate::solve::{CanonicalResponse, QueryResult, Response};
14+
use rustc_data_structures::fx::FxHashSet;
1415
use rustc_index::IndexVec;
1516
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
1617
use rustc_infer::infer::canonical::CanonicalVarValues;
@@ -147,7 +148,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
147148
// Cannot use `take_registered_region_obligations` as we may compute the response
148149
// inside of a `probe` whenever we have multiple choices inside of the solver.
149150
let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
150-
let region_constraints = self.infcx.with_region_constraints(|region_constraints| {
151+
let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| {
151152
make_query_region_constraints(
152153
self.tcx(),
153154
region_obligations
@@ -157,6 +158,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
157158
)
158159
});
159160

161+
let mut seen = FxHashSet::default();
162+
region_constraints.outlives.retain(|outlives| seen.insert(*outlives));
163+
160164
let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
161165
// Only return opaque type keys for newly-defined opaques
162166
opaque_types.retain(|(a, _)| {

Diff for: tests/ui/traits/new-solver/dedup-regions.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// compile-flags: -Ztrait-solver=next
2+
// check-pass
3+
4+
struct A(*mut ());
5+
6+
unsafe impl Send for A where A: 'static {}
7+
8+
macro_rules! mk {
9+
($name:ident $ty:ty) => {
10+
struct $name($ty, $ty, $ty, $ty, $ty, $ty, $ty, $ty, $ty, $ty);
11+
};
12+
}
13+
14+
mk!(B A);
15+
mk!(C B);
16+
mk!(D C);
17+
mk!(E D);
18+
mk!(F E);
19+
mk!(G F);
20+
mk!(H G);
21+
mk!(I H);
22+
mk!(J I);
23+
mk!(K J);
24+
mk!(L K);
25+
mk!(M L);
26+
27+
fn needs_send<T: Send>() {}
28+
29+
fn main() {
30+
needs_send::<M>();
31+
}

0 commit comments

Comments
 (0)