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

};

122129123130

let external_constraints =

124-

self.compute_external_query_constraints(normalization_nested_goals)?;

131+

self.compute_external_query_constraints(certainty, normalization_nested_goals);

125132

let (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)]

171178

fn compute_external_query_constraints(

172179

&self,

180+

certainty: Certainty,

173181

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+

};

197211198212

let 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, _)| {

201215

self.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