@@ -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