@@ -253,82 +253,39 @@ pub(super) trait GoalKind<'tcx>:
253
253
ecx : & mut EvalCtxt < ' _ , ' tcx > ,
254
254
goal : Goal < ' tcx , Self > ,
255
255
) -> Vec < ( CanonicalResponse < ' tcx > , BuiltinImplSource ) > ;
256
-
257
- /// Consider the `Unsize` candidate corresponding to coercing a sized type
258
- /// into a `dyn Trait`.
259
- ///
260
- /// This is computed separately from the rest of the `Unsize` candidates
261
- /// since it is only done once per self type, and not once per
262
- /// *normalization step* (in `assemble_candidates_via_self_ty`).
263
- fn consider_unsize_to_dyn_candidate (
264
- ecx : & mut EvalCtxt < ' _ , ' tcx > ,
265
- goal : Goal < ' tcx , Self > ,
266
- ) -> QueryResult < ' tcx > ;
267
256
}
268
257
269
258
impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
270
259
pub ( super ) fn assemble_and_evaluate_candidates < G : GoalKind < ' tcx > > (
271
260
& mut self ,
272
261
goal : Goal < ' tcx , G > ,
273
262
) -> 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" ) ;
263
+ let dummy_candidate = |this : & mut EvalCtxt < ' _ , ' tcx > , certainty| {
304
264
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 ( ) ;
265
+ let result = this. evaluate_added_goals_and_make_canonical_response ( certainty) . unwrap ( ) ;
266
+ let mut dummy_probe = this. inspect . new_probe ( ) ;
309
267
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
268
+ this. inspect . finish_probe ( dummy_probe) ;
269
+ vec ! [ Candidate { source, result } ]
270
+ } ;
271
+
272
+ let Some ( normalized_self_ty) =
273
+ self . try_normalize_ty ( goal. param_env , goal. predicate . self_ty ( ) )
274
+ else {
275
+ debug ! ( "overflow while evaluating self type" ) ;
276
+ return dummy_candidate ( self , Certainty :: OVERFLOW ) ;
277
+ } ;
278
+
279
+ if normalized_self_ty. is_ty_var ( ) {
280
+ debug ! ( "self type has been normalized to infer" ) ;
281
+ return dummy_candidate ( self , Certainty :: AMBIGUOUS ) ;
314
282
}
315
- }
316
283
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 > > {
284
+ let goal =
285
+ goal. with ( self . tcx ( ) , goal. predicate . with_self_ty ( self . tcx ( ) , normalized_self_ty) ) ;
326
286
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
287
331
- let mut candidates = Vec :: new ( ) ;
288
+ let mut candidates = vec ! [ ] ;
332
289
333
290
self . assemble_non_blanket_impl_candidates ( goal, & mut candidates) ;
334
291
@@ -338,61 +295,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
338
295
339
296
self . assemble_object_bound_candidates ( goal, & mut candidates) ;
340
297
341
- self . assemble_candidates_after_normalizing_self_ty ( goal, & mut candidates, num_steps) ;
342
- candidates
343
- }
298
+ self . assemble_blanket_impl_candidates ( goal, & mut candidates) ;
344
299
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
- } ) ) ;
300
+ self . assemble_param_env_candidates ( goal, & mut candidates) ;
301
+
302
+ self . assemble_coherence_unknowable_candidates ( goal, & mut candidates) ;
303
+
304
+ candidates
396
305
}
397
306
398
307
#[ instrument( level = "debug" , skip_all) ]
@@ -500,24 +409,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
500
409
}
501
410
}
502
411
503
- #[ instrument( level = "debug" , skip_all) ]
504
- fn assemble_unsize_to_dyn_candidate < G : GoalKind < ' tcx > > (
505
- & mut self ,
506
- goal : Goal < ' tcx , G > ,
507
- candidates : & mut Vec < Candidate < ' tcx > > ,
508
- ) {
509
- let tcx = self . tcx ( ) ;
510
- if tcx. lang_items ( ) . unsize_trait ( ) == Some ( goal. predicate . trait_def_id ( tcx) ) {
511
- match G :: consider_unsize_to_dyn_candidate ( self , goal) {
512
- Ok ( result) => candidates. push ( Candidate {
513
- source : CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ,
514
- result,
515
- } ) ,
516
- Err ( NoSolution ) => ( ) ,
517
- }
518
- }
519
- }
520
-
521
412
#[ instrument( level = "debug" , skip_all) ]
522
413
fn assemble_blanket_impl_candidates < G : GoalKind < ' tcx > > (
523
414
& mut self ,
0 commit comments