@@ -271,64 +271,32 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
271
271
& mut self ,
272
272
goal : Goal < ' tcx , G > ,
273
273
) -> Vec < Candidate < ' tcx > > {
274
- debug_assert_eq ! ( goal, self . resolve_vars_if_possible( goal) ) ;
275
- if let Some ( ambig) = self . assemble_self_ty_infer_ambiguity_response ( goal) {
276
- return vec ! [ ambig] ;
277
- }
278
-
279
- let mut candidates = self . assemble_candidates_via_self_ty ( goal, 0 ) ;
280
-
281
- self . assemble_unsize_to_dyn_candidate ( goal, & mut candidates) ;
282
-
283
- self . assemble_blanket_impl_candidates ( goal, & mut candidates) ;
284
-
285
- self . assemble_param_env_candidates ( goal, & mut candidates) ;
286
-
287
- self . assemble_coherence_unknowable_candidates ( goal, & mut candidates) ;
288
-
289
- candidates
290
- }
291
-
292
- /// `?0: Trait` is ambiguous, because it may be satisfied via a builtin rule,
293
- /// object bound, alias bound, etc. We are unable to determine this until we can at
294
- /// least structurally resolve the type one layer.
295
- ///
296
- /// It would also require us to consider all impls of the trait, which is both pretty
297
- /// bad for perf and would also constrain the self type if there is just a single impl.
298
- fn assemble_self_ty_infer_ambiguity_response < G : GoalKind < ' tcx > > (
299
- & mut self ,
300
- goal : Goal < ' tcx , G > ,
301
- ) -> Option < Candidate < ' tcx > > {
302
- if goal. predicate . self_ty ( ) . is_ty_var ( ) {
303
- debug ! ( "adding self_ty_infer_ambiguity_response" ) ;
274
+ let dummy_candidate = |this : & mut EvalCtxt < ' _ , ' tcx > , certainty| {
304
275
let source = CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ;
305
- let result = self
306
- . evaluate_added_goals_and_make_canonical_response ( Certainty :: AMBIGUOUS )
307
- . unwrap ( ) ;
308
- let mut dummy_probe = self . inspect . new_probe ( ) ;
276
+ let result = this. evaluate_added_goals_and_make_canonical_response ( certainty) . unwrap ( ) ;
277
+ let mut dummy_probe = this. inspect . new_probe ( ) ;
309
278
dummy_probe. probe_kind ( ProbeKind :: TraitCandidate { source, result : Ok ( result) } ) ;
310
- self . inspect . finish_probe ( dummy_probe) ;
311
- Some ( Candidate { source, result } )
312
- } else {
313
- None
279
+ this. inspect . finish_probe ( dummy_probe) ;
280
+ vec ! [ Candidate { source, result } ]
281
+ } ;
282
+
283
+ let Some ( normalized_self_ty) =
284
+ self . try_normalize_ty ( goal. param_env , goal. predicate . self_ty ( ) )
285
+ else {
286
+ debug ! ( "overflow while evaluating self type" ) ;
287
+ return dummy_candidate ( self , Certainty :: OVERFLOW ) ;
288
+ } ;
289
+
290
+ if normalized_self_ty. is_ty_var ( ) {
291
+ debug ! ( "self type has been normalized to infer" ) ;
292
+ return dummy_candidate ( self , Certainty :: AMBIGUOUS ) ;
314
293
}
315
- }
316
294
317
- /// Assemble candidates which apply to the self type. This only looks at candidate which
318
- /// apply to the specific self type and ignores all others.
319
- ///
320
- /// Returns `None` if the self type is still ambiguous.
321
- fn assemble_candidates_via_self_ty < G : GoalKind < ' tcx > > (
322
- & mut self ,
323
- goal : Goal < ' tcx , G > ,
324
- num_steps : usize ,
325
- ) -> Vec < Candidate < ' tcx > > {
295
+ let goal =
296
+ goal. with ( self . tcx ( ) , goal. predicate . with_self_ty ( self . tcx ( ) , normalized_self_ty) ) ;
326
297
debug_assert_eq ! ( goal, self . resolve_vars_if_possible( goal) ) ;
327
- if let Some ( ambig) = self . assemble_self_ty_infer_ambiguity_response ( goal) {
328
- return vec ! [ ambig] ;
329
- }
330
298
331
- let mut candidates = Vec :: new ( ) ;
299
+ let mut candidates = vec ! [ ] ;
332
300
333
301
self . assemble_non_blanket_impl_candidates ( goal, & mut candidates) ;
334
302
@@ -338,61 +306,15 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
338
306
339
307
self . assemble_object_bound_candidates ( goal, & mut candidates) ;
340
308
341
- self . assemble_candidates_after_normalizing_self_ty ( goal, & mut candidates, num_steps) ;
342
- candidates
343
- }
309
+ self . assemble_unsize_to_dyn_candidate ( goal, & mut candidates) ;
344
310
345
- /// If the self type of a goal is an alias we first try to normalize the self type
346
- /// and compute the candidates for the normalized self type in case that succeeds.
347
- ///
348
- /// These candidates are used in addition to the ones with the alias as a self type.
349
- /// We do this to simplify both builtin candidates and for better performance.
350
- ///
351
- /// We generate the builtin candidates on the fly by looking at the self type, e.g.
352
- /// add `FnPtr` candidates if the self type is a function pointer. Handling builtin
353
- /// candidates while the self type is still an alias seems difficult. This is similar
354
- /// to `try_structurally_resolve_type` during hir typeck (FIXME once implemented).
355
- ///
356
- /// Looking at all impls for some trait goal is prohibitively expensive. We therefore
357
- /// only look at implementations with a matching self type. Because of this function,
358
- /// we can avoid looking at all existing impls if the self type is an alias.
359
- #[ instrument( level = "debug" , skip_all) ]
360
- fn assemble_candidates_after_normalizing_self_ty < G : GoalKind < ' tcx > > (
361
- & mut self ,
362
- goal : Goal < ' tcx , G > ,
363
- candidates : & mut Vec < Candidate < ' tcx > > ,
364
- num_steps : usize ,
365
- ) {
366
- let tcx = self . tcx ( ) ;
367
- let & ty:: Alias ( _, alias) = goal. predicate . self_ty ( ) . kind ( ) else { return } ;
368
-
369
- candidates. extend ( self . probe ( |_| ProbeKind :: NormalizedSelfTyAssembly ) . enter ( |ecx| {
370
- if tcx. recursion_limit ( ) . value_within_limit ( num_steps) {
371
- let normalized_ty = ecx. next_ty_infer ( ) ;
372
- let normalizes_to_goal =
373
- goal. with ( tcx, ty:: NormalizesTo { alias, term : normalized_ty. into ( ) } ) ;
374
- ecx. add_goal ( GoalSource :: Misc , normalizes_to_goal) ;
375
- if let Err ( NoSolution ) = ecx. try_evaluate_added_goals ( ) {
376
- debug ! ( "self type normalization failed" ) ;
377
- return vec ! [ ] ;
378
- }
379
- let normalized_ty = ecx. resolve_vars_if_possible ( normalized_ty) ;
380
- debug ! ( ?normalized_ty, "self type normalized" ) ;
381
- // NOTE: Alternatively we could call `evaluate_goal` here and only
382
- // have a `Normalized` candidate. This doesn't work as long as we
383
- // use `CandidateSource` in winnowing.
384
- let goal = goal. with ( tcx, goal. predicate . with_self_ty ( tcx, normalized_ty) ) ;
385
- ecx. assemble_candidates_via_self_ty ( goal, num_steps + 1 )
386
- } else {
387
- match ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: OVERFLOW ) {
388
- Ok ( result) => vec ! [ Candidate {
389
- source: CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ,
390
- result,
391
- } ] ,
392
- Err ( NoSolution ) => vec ! [ ] ,
393
- }
394
- }
395
- } ) ) ;
311
+ self . assemble_blanket_impl_candidates ( goal, & mut candidates) ;
312
+
313
+ self . assemble_param_env_candidates ( goal, & mut candidates) ;
314
+
315
+ self . assemble_coherence_unknowable_candidates ( goal, & mut candidates) ;
316
+
317
+ candidates
396
318
}
397
319
398
320
#[ instrument( level = "debug" , skip_all) ]
0 commit comments