@@ -253,82 +253,39 @@ pub(super) trait GoalKind<'tcx>:
253253 ecx : & mut EvalCtxt < ' _ , ' tcx > ,
254254 goal : Goal < ' tcx , Self > ,
255255 ) -> 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 > ;
267256}
268257
269258impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
270259 pub ( super ) fn assemble_and_evaluate_candidates < G : GoalKind < ' tcx > > (
271260 & mut self ,
272261 goal : Goal < ' tcx , G > ,
273262 ) -> 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| {
304264 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 ( ) ;
309267 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 ) ;
314282 }
315- }
316283
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) ) ;
326286 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- }
330287
331- let mut candidates = Vec :: new ( ) ;
288+ let mut candidates = vec ! [ ] ;
332289
333290 self . assemble_non_blanket_impl_candidates ( goal, & mut candidates) ;
334291
@@ -338,61 +295,13 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
338295
339296 self . assemble_object_bound_candidates ( goal, & mut candidates) ;
340297
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) ;
344299
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
396305 }
397306
398307 #[ instrument( level = "debug" , skip_all) ]
@@ -500,24 +409,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
500409 }
501410 }
502411
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-
521412 #[ instrument( level = "debug" , skip_all) ]
522413 fn assemble_blanket_impl_candidates < G : GoalKind < ' tcx > > (
523414 & mut self ,
0 commit comments