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

`