@@ -10,7 +10,7 @@ use std::ops::ControlFlow;
10
10
11
11
use hir:: def_id:: DefId ;
12
12
use hir:: LangItem ;
13
- use rustc_data_structures:: fx:: FxHashSet ;
13
+ use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
14
14
use rustc_hir as hir;
15
15
use rustc_infer:: traits:: ObligationCause ;
16
16
use rustc_infer:: traits:: { Obligation , PolyTraitObligation , SelectionError } ;
@@ -968,52 +968,61 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
968
968
//
969
969
// We always perform upcasting coercions when we can because of reason
970
970
// #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 {
980
989
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 ;
994
1003
}
1004
+ }
995
1005
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 ;
1014
1022
}
1015
- } )
1016
- }
1023
+ candidates. vec . push ( TraitUpcastingUnsizeCandidate ( idx) ) ;
1024
+ }
1025
+ } )
1017
1026
}
1018
1027
}
1019
1028
}
0 commit comments