drop region constraints for ambiguous goals · rust-lang/rust@24b5466
@@ -99,6 +99,13 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
9999 previous call to `try_evaluate_added_goals!`"
100100);
101101102+// We only check for leaks from universes which were entered inside
103+// of the query.
104+self.infcx.leak_check(self.max_input_universe, None).map_err(|e| {
105+trace!(?e, "failed the leak check");
106+NoSolution
107+})?;
108+102109// When normalizing, we've replaced the expected term with an unconstrained
103110// inference variable. This means that we dropped information which could
104111// have been important. We handle this by instead returning the nested goals
@@ -121,7 +128,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
121128};
122129123130let external_constraints =
124-self.compute_external_query_constraints(normalization_nested_goals)?;
131+self.compute_external_query_constraints(certainty, normalization_nested_goals);
125132let (var_values, mut external_constraints) =
126133(self.var_values, external_constraints).fold_with(&mut EagerResolver::new(self.infcx));
127134// Remove any trivial region constraints once we've resolved regions
@@ -170,38 +177,45 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
170177 #[instrument(level = "trace", skip(self), ret)]
171178fn compute_external_query_constraints(
172179&self,
180+certainty: Certainty,
173181normalization_nested_goals: NestedNormalizationGoals<'tcx>,
174-) -> Result<ExternalConstraintsData<'tcx>, NoSolution> {
175-// We only check for leaks from universes which were entered inside
176-// of the query.
177-self.infcx.leak_check(self.max_input_universe, None).map_err(|e| {
178-trace!(?e, "failed the leak check");
179-NoSolution
180-})?;
181-182-// Cannot use `take_registered_region_obligations` as we may compute the response
183-// inside of a `probe` whenever we have multiple choices inside of the solver.
184-let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
185-let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| {
186-make_query_region_constraints(
187-self.tcx(),
188- region_obligations
189-.iter()
190-.map(|r_o| (r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())),
191- region_constraints,
192-)
193-});
194-195-let mut seen = FxHashSet::default();
196- region_constraints.outlives.retain(|outlives| seen.insert(*outlives));
182+) -> ExternalConstraintsData<'tcx> {
183+// We only return region constraints once the certainty is `Yes`. This
184+// is necessary as we may drop nested goals on ambiguity, which may result
185+// in unconstrained inference variables in the region constraints. It also
186+// prevents us from emitting duplicate region constraints, avoiding some
187+// unnecessary work. This slightly weakens the leak check in case it uses
188+// region constraints from an ambiguous nested goal. This is tested in both
189+// `tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs` and
190+// `tests/ui/higher-ranked/leak-check/leak-check-in-selection-6-ambig-unify.rs`.
191+let region_constraints = if certainty == Certainty::Yes {
192+// Cannot use `take_registered_region_obligations` as we may compute the response
193+// inside of a `probe` whenever we have multiple choices inside of the solver.
194+let region_obligations = self.infcx.inner.borrow().region_obligations().to_owned();
195+let mut region_constraints = self.infcx.with_region_constraints(|region_constraints| {
196+make_query_region_constraints(
197+self.tcx(),
198+ region_obligations.iter().map(|r_o| {
199+(r_o.sup_type, r_o.sub_region, r_o.origin.to_constraint_category())
200+}),
201+ region_constraints,
202+)
203+});
204+205+let mut seen = FxHashSet::default();
206+ region_constraints.outlives.retain(|outlives| seen.insert(*outlives));
207+ region_constraints
208+} else {
209+Default::default()
210+};
197211198212let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
199213// Only return opaque type keys for newly-defined opaques
200214 opaque_types.retain(|(a, _)| {
201215self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
202216});
203217204-Ok(ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals })
218+ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
205219}
206220207221/// After calling a canonical query, we apply the constraints returned