@@ -423,7 +423,55 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
423423 ecx. evaluate_added_goals_and_make_canonical_response ( certainty)
424424 }
425425
426- fn consider_builtin_unsize_candidates (
426+ fn consider_unsize_to_dyn_candidate (
427+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
428+ goal : Goal < ' tcx , Self > ,
429+ ) -> QueryResult < ' tcx > {
430+ ecx. probe ( |_| CandidateKind :: UnsizeAssembly ) . enter ( |ecx| {
431+ let a_ty = goal. predicate . self_ty ( ) ;
432+ // We need to normalize the b_ty since it's destructured as a `dyn Trait`.
433+ let Some ( b_ty) =
434+ ecx. try_normalize_ty ( goal. param_env , goal. predicate . trait_ref . args . type_at ( 1 ) ) ?
435+ else {
436+ return ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: OVERFLOW ) ;
437+ } ;
438+
439+ let ty:: Dynamic ( b_data, b_region, ty:: Dyn ) = * b_ty. kind ( ) else {
440+ return Err ( NoSolution ) ;
441+ } ;
442+
443+ let tcx = ecx. tcx ( ) ;
444+
445+ // Can only unsize to an object-safe trait.
446+ if b_data. principal_def_id ( ) . is_some_and ( |def_id| !tcx. check_is_object_safe ( def_id) ) {
447+ return Err ( NoSolution ) ;
448+ }
449+
450+ // Check that the type implements all of the predicates of the trait object.
451+ // (i.e. the principal, all of the associated types match, and any auto traits)
452+ ecx. add_goals ( b_data. iter ( ) . map ( |pred| goal. with ( tcx, pred. with_self_ty ( tcx, a_ty) ) ) ) ;
453+
454+ // The type must be `Sized` to be unsized.
455+ if let Some ( sized_def_id) = tcx. lang_items ( ) . sized_trait ( ) {
456+ ecx. add_goal ( goal. with ( tcx, ty:: TraitRef :: new ( tcx, sized_def_id, [ a_ty] ) ) ) ;
457+ } else {
458+ return Err ( NoSolution ) ;
459+ }
460+
461+ // The type must outlive the lifetime of the `dyn` we're unsizing into.
462+ ecx. add_goal ( goal. with ( tcx, ty:: OutlivesPredicate ( a_ty, b_region) ) ) ;
463+ ecx. evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
464+ } )
465+ }
466+
467+ /// ```ignore (builtin impl example)
468+ /// trait Trait {
469+ /// fn foo(&self);
470+ /// }
471+ /// // results in the following builtin impl
472+ /// impl<'a, T: Trait + 'a> Unsize<dyn Trait + 'a> for T {}
473+ /// ```
474+ fn consider_structural_builtin_unsize_candidates (
427475 ecx : & mut EvalCtxt < ' _ , ' tcx > ,
428476 goal : Goal < ' tcx , Self > ,
429477 ) -> Vec < ( CanonicalResponse < ' tcx > , BuiltinImplSource ) > {
@@ -468,11 +516,8 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
468516 goal, a_data, a_region, b_data, b_region,
469517 ) ,
470518
471- // `T` -> `dyn Trait` unsizing
472- ( _, & ty:: Dynamic ( b_data, b_region, ty:: Dyn ) ) => result_to_single (
473- ecx. consider_builtin_unsize_to_dyn ( goal, b_data, b_region) ,
474- BuiltinImplSource :: Misc ,
475- ) ,
519+ // `T` -> `dyn Trait` unsizing is handled separately in `consider_unsize_to_dyn_candidate`
520+ ( _, & ty:: Dynamic ( ..) ) => vec ! [ ] ,
476521
477522 // `[T; N]` -> `[T]` unsizing
478523 ( & ty:: Array ( a_elem_ty, ..) , & ty:: Slice ( b_elem_ty) ) => result_to_single (
@@ -572,43 +617,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
572617 responses
573618 }
574619
575- /// ```ignore (builtin impl example)
576- /// trait Trait {
577- /// fn foo(&self);
578- /// }
579- /// // results in the following builtin impl
580- /// impl<'a, T: Trait + 'a> Unsize<dyn Trait + 'a> for T {}
581- /// ```
582- fn consider_builtin_unsize_to_dyn (
583- & mut self ,
584- goal : Goal < ' tcx , ( Ty < ' tcx > , Ty < ' tcx > ) > ,
585- b_data : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
586- b_region : ty:: Region < ' tcx > ,
587- ) -> QueryResult < ' tcx > {
588- let tcx = self . tcx ( ) ;
589- let Goal { predicate : ( a_ty, _b_ty) , .. } = goal;
590-
591- // Can only unsize to an object-safe trait
592- if b_data. principal_def_id ( ) . is_some_and ( |def_id| !tcx. check_is_object_safe ( def_id) ) {
593- return Err ( NoSolution ) ;
594- }
595-
596- // Check that the type implements all of the predicates of the trait object.
597- // (i.e. the principal, all of the associated types match, and any auto traits)
598- self . add_goals ( b_data. iter ( ) . map ( |pred| goal. with ( tcx, pred. with_self_ty ( tcx, a_ty) ) ) ) ;
599-
600- // The type must be `Sized` to be unsized.
601- if let Some ( sized_def_id) = tcx. lang_items ( ) . sized_trait ( ) {
602- self . add_goal ( goal. with ( tcx, ty:: TraitRef :: new ( tcx, sized_def_id, [ a_ty] ) ) ) ;
603- } else {
604- return Err ( NoSolution ) ;
605- }
606-
607- // The type must outlive the lifetime of the `dyn` we're unsizing into.
608- self . add_goal ( goal. with ( tcx, ty:: OutlivesPredicate ( a_ty, b_region) ) ) ;
609- self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
610- }
611-
612620 fn consider_builtin_upcast_to_principal (
613621 & mut self ,
614622 goal : Goal < ' tcx , ( Ty < ' tcx > , Ty < ' tcx > ) > ,
0 commit comments