@@ -10,7 +10,7 @@ use std::ops::ControlFlow;
1010
1111use hir:: def_id:: DefId ;
1212use hir:: LangItem ;
13- use rustc_data_structures:: fx:: FxHashSet ;
13+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
1414use rustc_hir as hir;
1515use rustc_infer:: traits:: ObligationCause ;
1616use rustc_infer:: traits:: { Obligation , PolyTraitObligation , SelectionError } ;
@@ -968,52 +968,61 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
968968 //
969969 // We always perform upcasting coercions when we can because of reason
970970 // #2 (region bounds).
971- let auto_traits_compatible = b_data
972- . auto_traits ( )
973- // All of a's auto traits need to be in b's auto traits.
974- . all ( |b| a_data. auto_traits ( ) . any ( |a| a == b) ) ;
975- if auto_traits_compatible {
976- let principal_def_id_a = a_data. principal_def_id ( ) ;
977- let principal_def_id_b = b_data. principal_def_id ( ) ;
978- if principal_def_id_a == principal_def_id_b {
979- // no cyclic
971+ let principal_def_id_a = a_data. principal_def_id ( ) ;
972+ let principal_def_id_b = b_data. principal_def_id ( ) ;
973+ if principal_def_id_a == principal_def_id_b {
974+ // We may upcast to auto traits that are either explicitly listed in
975+ // the object type's bounds, or implied by the principal trait ref's
976+ // supertraits.
977+ let a_auto_traits: FxIndexSet < DefId > = a_data
978+ . auto_traits ( )
979+ . chain ( principal_def_id_a. into_iter ( ) . flat_map ( |principal_def_id| {
980+ util:: supertrait_def_ids ( self . tcx ( ) , principal_def_id)
981+ . filter ( |def_id| self . tcx ( ) . trait_is_auto ( * def_id) )
982+ } ) )
983+ . collect ( ) ;
984+ let auto_traits_compatible = b_data
985+ . auto_traits ( )
986+ // All of a's auto traits need to be in b's auto traits.
987+ . all ( |b| a_auto_traits. contains ( & b) ) ;
988+ if auto_traits_compatible {
980989 candidates. vec . push ( BuiltinUnsizeCandidate ) ;
981- } else if principal_def_id_a . is_some ( ) && principal_def_id_b . is_some ( ) {
982- // not casual unsizing, now check whether this is trait upcasting coercion.
983- let principal_a = a_data . principal ( ) . unwrap ( ) ;
984- let target_trait_did = principal_def_id_b . unwrap ( ) ;
985- let source_trait_ref = principal_a . with_self_ty ( self . tcx ( ) , source ) ;
986- if let Some ( deref_trait_ref ) = self . need_migrate_deref_output_trait_object (
987- source ,
988- obligation . param_env ,
989- & obligation. cause ,
990- ) {
991- if deref_trait_ref . def_id ( ) == target_trait_did {
992- return ;
993- }
990+ }
991+ } else if principal_def_id_a . is_some ( ) && principal_def_id_b . is_some ( ) {
992+ // not casual unsizing, now check whether this is trait upcasting coercion.
993+ let principal_a = a_data . principal ( ) . unwrap ( ) ;
994+ let target_trait_did = principal_def_id_b . unwrap ( ) ;
995+ let source_trait_ref = principal_a . with_self_ty ( self . tcx ( ) , source ) ;
996+ if let Some ( deref_trait_ref ) = self . need_migrate_deref_output_trait_object (
997+ source ,
998+ obligation. param_env ,
999+ & obligation . cause ,
1000+ ) {
1001+ if deref_trait_ref . def_id ( ) == target_trait_did {
1002+ return ;
9941003 }
1004+ }
9951005
996- for ( idx, upcast_trait_ref) in
997- util:: supertraits ( self . tcx ( ) , source_trait_ref) . enumerate ( )
998- {
999- self . infcx . probe ( |_| {
1000- if upcast_trait_ref. def_id ( ) == target_trait_did
1001- && let Ok ( nested) = self . match_upcast_principal (
1002- obligation,
1003- upcast_trait_ref,
1004- a_data,
1005- b_data,
1006- a_region,
1007- b_region,
1008- )
1009- {
1010- if nested. is_none ( ) {
1011- candidates. ambiguous = true ;
1012- }
1013- candidates. vec . push ( TraitUpcastingUnsizeCandidate ( idx) ) ;
1006+ for ( idx, upcast_trait_ref) in
1007+ util:: supertraits ( self . tcx ( ) , source_trait_ref) . enumerate ( )
1008+ {
1009+ self . infcx . probe ( |_| {
1010+ if upcast_trait_ref. def_id ( ) == target_trait_did
1011+ && let Ok ( nested) = self . match_upcast_principal (
1012+ obligation,
1013+ upcast_trait_ref,
1014+ a_data,
1015+ b_data,
1016+ a_region,
1017+ b_region,
1018+ )
1019+ {
1020+ if nested. is_none ( ) {
1021+ candidates. ambiguous = true ;
10141022 }
1015- } )
1016- }
1023+ candidates. vec . push ( TraitUpcastingUnsizeCandidate ( idx) ) ;
1024+ }
1025+ } )
10171026 }
10181027 }
10191028 }
0 commit comments