@@ -99,6 +99,13 @@ impl<'tcx> EvalCtxt<'_, InferCtxt<'tcx>> {
9999 previous call to `try_evaluate_added_goals!`"
100100 ) ;
101101
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+
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 } ;
122129
123130 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+ } ;
197211
198212 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 } ) ;
203217
204- Ok ( ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } )
218+ ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
205219 }
206220
207221 /// After calling a canonical query, we apply the constraints returned
0 commit comments