Rollup merge of #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``
This commit is contained in:
commit
4ef7257018
2 changed files with 36 additions and 1 deletions
|
@ -11,6 +11,7 @@
|
||||||
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
|
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
|
||||||
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
|
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
|
||||||
use crate::solve::{CanonicalResponse, QueryResult, Response};
|
use crate::solve::{CanonicalResponse, QueryResult, Response};
|
||||||
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_index::IndexVec;
|
use rustc_index::IndexVec;
|
||||||
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
|
use rustc_infer::infer::canonical::query_response::make_query_region_constraints;
|
||||||
use rustc_infer::infer::canonical::CanonicalVarValues;
|
use rustc_infer::infer::canonical::CanonicalVarValues;
|
||||||
|
@ -147,7 +148,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
// Cannot use `take_registered_region_obligations` as we may compute the response
|
// Cannot use `take_registered_region_obligations` as we may compute the response
|
||||||
// inside of a `probe` whenever we have multiple choices inside of the solver.
|
// inside of a `probe` whenever we have multiple choices inside of the solver.
|
||||||
let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
|
let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
|
||||||
let region_constraints = self.infcx.with_region_constraints(|region_constraints| {
|
let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| {
|
||||||
make_query_region_constraints(
|
make_query_region_constraints(
|
||||||
self.tcx(),
|
self.tcx(),
|
||||||
region_obligations
|
region_obligations
|
||||||
|
@ -157,6 +158,9 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let mut seen = FxHashSet::default();
|
||||||
|
region_constraints.outlives.retain(|outlives| seen.insert(*outlives));
|
||||||
|
|
||||||
let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
|
let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
|
||||||
// Only return opaque type keys for newly-defined opaques
|
// Only return opaque type keys for newly-defined opaques
|
||||||
opaque_types.retain(|(a, _)| {
|
opaque_types.retain(|(a, _)| {
|
||||||
|
|
31
tests/ui/traits/new-solver/dedup-regions.rs
Normal file
31
tests/ui/traits/new-solver/dedup-regions.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// compile-flags: -Ztrait-solver=next
|
||||||
|
// check-pass
|
||||||
|
|
||||||
|
struct A(*mut ());
|
||||||
|
|
||||||
|
unsafe impl Send for A where A: 'static {}
|
||||||
|
|
||||||
|
macro_rules! mk {
|
||||||
|
($name:ident $ty:ty) => {
|
||||||
|
struct $name($ty, $ty, $ty, $ty, $ty, $ty, $ty, $ty, $ty, $ty);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
mk!(B A);
|
||||||
|
mk!(C B);
|
||||||
|
mk!(D C);
|
||||||
|
mk!(E D);
|
||||||
|
mk!(F E);
|
||||||
|
mk!(G F);
|
||||||
|
mk!(H G);
|
||||||
|
mk!(I H);
|
||||||
|
mk!(J I);
|
||||||
|
mk!(K J);
|
||||||
|
mk!(L K);
|
||||||
|
mk!(M L);
|
||||||
|
|
||||||
|
fn needs_send<T: Send>() {}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
needs_send::<M>();
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue