Auto merge of #125413 - lcnr:ambig-drop-region-constraints, r=compiler-errors
drop region constraints for ambiguous goals See the comment in `compute_external_query_constraints`. While the underlying issue is preexisting, this fixes a bug introduced by #125343. It slightly weakens the leak chec, even if we didn't have any test which was affected. I want to write such a test before merging this PR. r? `@compiler-errors`
This commit is contained in:
commit
b0f8618938
6 changed files with 171 additions and 24 deletions
|
@ -99,6 +99,13 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
|||
previous call to `try_evaluate_added_goals!`"
|
||||
);
|
||||
|
||||
// We only check for leaks from universes which were entered inside
|
||||
// of the query.
|
||||
self.infcx.leak_check(self.max_input_universe, None).map_err(|e| {
|
||||
trace!(?e, "failed the leak check");
|
||||
NoSolution
|
||||
})?;
|
||||
|
||||
// When normalizing, we've replaced the expected term with an unconstrained
|
||||
// inference variable. This means that we dropped information which could
|
||||
// have been important. We handle this by instead returning the nested goals
|
||||
|
@ -121,7 +128,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
|||
};
|
||||
|
||||
let external_constraints =
|
||||
self.compute_external_query_constraints(normalization_nested_goals)?;
|
||||
self.compute_external_query_constraints(certainty, normalization_nested_goals);
|
||||
let (var_values, mut external_constraints) =
|
||||
(self.var_values, external_constraints).fold_with(&mut EagerResolver::new(self.infcx));
|
||||
// Remove any trivial region constraints once we've resolved regions
|
||||
|
@ -170,30 +177,37 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
|||
#[instrument(level = "trace", skip(self), ret)]
|
||||
fn compute_external_query_constraints(
|
||||
&self,
|
||||
certainty: Certainty,
|
||||
normalization_nested_goals: NestedNormalizationGoals<'tcx>,
|
||||
) -> Result<ExternalConstraintsData<'tcx>, NoSolution> {
|
||||
// We only check for leaks from universes which were entered inside
|
||||
// of the query.
|
||||
self.infcx.leak_check(self.max_input_universe, None).map_err(|e| {
|
||||
trace!(?e, "failed the leak check");
|
||||
NoSolution
|
||||
})?;
|
||||
) -> ExternalConstraintsData<'tcx> {
|
||||
// We only return region constraints once the certainty is `Yes`. This
|
||||
// is necessary as we may drop nested goals on ambiguity, which may result
|
||||
// in unconstrained inference variables in the region constraints. It also
|
||||
// prevents us from emitting duplicate region constraints, avoiding some
|
||||
// unnecessary work. This slightly weakens the leak check in case it uses
|
||||
// region constraints from an ambiguous nested goal. This is tested in both
|
||||
// `tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs` and
|
||||
// `tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs`.
|
||||
let region_constraints = if certainty == Certainty::Yes {
|
||||
// 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.
|
||||
let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
|
||||
let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| {
|
||||
make_query_region_constraints(
|
||||
self.tcx(),
|
||||
region_obligations.iter().map(|r_o| {
|
||||
(r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())
|
||||
}),
|
||||
region_constraints,
|
||||
)
|
||||
});
|
||||
|
||||
// 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.
|
||||
let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
|
||||
let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| {
|
||||
make_query_region_constraints(
|
||||
self.tcx(),
|
||||
region_obligations
|
||||
.iter()
|
||||
.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
|
||||
region_constraints,
|
||||
)
|
||||
});
|
||||
|
||||
let mut seen = FxHashSet::default();
|
||||
region_constraints.outlives.retain(|outlives| seen.insert(*outlives));
|
||||
let mut seen = FxHashSet::default();
|
||||
region_constraints.outlives.retain(|outlives| seen.insert(*outlives));
|
||||
region_constraints
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
|
||||
let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
|
||||
// Only return opaque type keys for newly-defined opaques
|
||||
|
@ -201,7 +215,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
|
|||
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
|
||||
});
|
||||
|
||||
Ok(ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals })
|
||||
ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
|
||||
}
|
||||
|
||||
/// After calling a canonical query, we apply the constraints returned
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue