drop region constraints for ambiguous goals · rust-lang/rust@24b5466 (original) (raw)
`@@ -99,6 +99,13 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
`
99
99
`` previous call to try_evaluate_added_goals!
"
``
100
100
`);
`
101
101
``
``
102
`+
// 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
+
102
109
`// When normalizing, we've replaced the expected term with an unconstrained
`
103
110
`// inference variable. This means that we dropped information which could
`
104
111
`// have been important. We handle this by instead returning the nested goals
`
`@@ -121,7 +128,7 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
`
121
128
`};
`
122
129
``
123
130
`let external_constraints =
`
124
``
`-
self.compute_external_query_constraints(normalization_nested_goals)?;
`
``
131
`+
self.compute_external_query_constraints(certainty, normalization_nested_goals);
`
125
132
`let (var_values, mut external_constraints) =
`
126
133
`(self.var_values, external_constraints).fold_with(&mut EagerResolver::new(self.infcx));
`
127
134
`// Remove any trivial region constraints once we've resolved regions
`
`@@ -170,38 +177,45 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
`
170
177
`#[instrument(level = "trace", skip(self), ret)]
`
171
178
`fn compute_external_query_constraints(
`
172
179
`&self,
`
``
180
`+
certainty: Certainty,
`
173
181
`normalization_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
`+
};
`
197
211
``
198
212
`let mut opaque_types = self.infcx.clone_opaque_types_for_query_response();
`
199
213
`// Only return opaque type keys for newly-defined opaques
`
200
214
` opaque_types.retain(|(a, _)| {
`
201
215
`self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
`
202
216
`});
`
203
217
``
204
``
`-
Ok(ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals })
`
``
218
`+
ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
`
205
219
`}
`
206
220
``
207
221
`/// After calling a canonical query, we apply the constraints returned
`