@@ -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 (
@@ -574,43 +619,6 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
574619 responses
575620 }
576621
577- /// ```ignore (builtin impl example)
578- /// trait Trait {
579- /// fn foo(&self);
580- /// }
581- /// // results in the following builtin impl
582- /// impl<'a, T: Trait + 'a> Unsize<dyn Trait + 'a> for T {}
583- /// ```
584- fn consider_builtin_unsize_to_dyn (
585- & mut self ,
586- goal : Goal < ' tcx , ( Ty < ' tcx > , Ty < ' tcx > ) > ,
587- b_data : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
588- b_region : ty:: Region < ' tcx > ,
589- ) -> QueryResult < ' tcx > {
590- let tcx = self . tcx ( ) ;
591- let Goal { predicate : ( a_ty, _b_ty) , .. } = goal;
592-
593- // Can only unsize to an object-safe trait
594- if b_data. principal_def_id ( ) . is_some_and ( |def_id| !tcx. check_is_object_safe ( def_id) ) {
595- return Err ( NoSolution ) ;
596- }
597-
598- // Check that the type implements all of the predicates of the trait object.
599- // (i.e. the principal, all of the associated types match, and any auto traits)
600- self . add_goals ( b_data. iter ( ) . map ( |pred| goal. with ( tcx, pred. with_self_ty ( tcx, a_ty) ) ) ) ;
601-
602- // The type must be `Sized` to be unsized.
603- if let Some ( sized_def_id) = tcx. lang_items ( ) . sized_trait ( ) {
604- self . add_goal ( goal. with ( tcx, ty:: TraitRef :: new ( tcx, sized_def_id, [ a_ty] ) ) ) ;
605- } else {
606- return Err ( NoSolution ) ;
607- }
608-
609- // The type must outlive the lifetime of the `dyn` we're unsizing into.
610- self . add_goal ( goal. with ( tcx, ty:: OutlivesPredicate ( a_ty, b_region) ) ) ;
611- self . evaluate_added_goals_and_make_canonical_response ( Certainty :: Yes )
612- }
613-
614622 fn consider_builtin_upcast_to_principal (
615623 & mut self ,
616624 goal : Goal < ' tcx , ( Ty < ' tcx > , Ty < ' tcx > ) > ,
0 commit comments