|
8 | 8 |
|
9 | 9 | use hir::def_id::DefId;
|
10 | 10 | use hir::LangItem;
|
| 11 | +use rustc_data_structures::fx::FxIndexSet; |
11 | 12 | use rustc_hir as hir;
|
12 | 13 | use rustc_infer::traits::ObligationCause;
|
13 | 14 | use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
|
@@ -807,52 +808,61 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
807 | 808 | //
|
808 | 809 | // We always perform upcasting coercions when we can because of reason
|
809 | 810 | // #2 (region bounds).
|
810 |
| - let auto_traits_compatible = b_data |
811 |
| - .auto_traits() |
812 |
| - // All of a's auto traits need to be in b's auto traits. |
813 |
| - .all(|b| a_data.auto_traits().any(|a| a == b)); |
814 |
| - if auto_traits_compatible { |
815 |
| - let principal_def_id_a = a_data.principal_def_id(); |
816 |
| - let principal_def_id_b = b_data.principal_def_id(); |
817 |
| - if principal_def_id_a == principal_def_id_b { |
818 |
| - // no cyclic |
| 811 | + let principal_def_id_a = a_data.principal_def_id(); |
| 812 | + let principal_def_id_b = b_data.principal_def_id(); |
| 813 | + if principal_def_id_a == principal_def_id_b { |
| 814 | + // We may upcast to auto traits that are either explicitly listed in |
| 815 | + // the object type's bounds, or implied by the principal trait ref's |
| 816 | + // supertraits. |
| 817 | + let a_auto_traits: FxIndexSet<DefId> = a_data |
| 818 | + .auto_traits() |
| 819 | + .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| { |
| 820 | + util::supertrait_def_ids(self.tcx(), principal_def_id) |
| 821 | + .filter(|def_id| self.tcx().trait_is_auto(*def_id)) |
| 822 | + })) |
| 823 | + .collect(); |
| 824 | + let auto_traits_compatible = b_data |
| 825 | + .auto_traits() |
| 826 | + // All of a's auto traits need to be in b's auto traits. |
| 827 | + .all(|b| a_auto_traits.contains(&b)); |
| 828 | + if auto_traits_compatible { |
819 | 829 | candidates.vec.push(BuiltinUnsizeCandidate);
|
820 |
| - } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() { |
821 |
| - // not casual unsizing, now check whether this is trait upcasting coercion. |
822 |
| - let principal_a = a_data.principal().unwrap(); |
823 |
| - let target_trait_did = principal_def_id_b.unwrap(); |
824 |
| - let source_trait_ref = principal_a.with_self_ty(self.tcx(), source); |
825 |
| - if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object( |
826 |
| - source, |
827 |
| - obligation.param_env, |
828 |
| - &obligation.cause, |
829 |
| - ) { |
830 |
| - if deref_trait_ref.def_id() == target_trait_did { |
831 |
| - return; |
832 |
| - } |
| 830 | + } |
| 831 | + } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() { |
| 832 | + // not casual unsizing, now check whether this is trait upcasting coercion. |
| 833 | + let principal_a = a_data.principal().unwrap(); |
| 834 | + let target_trait_did = principal_def_id_b.unwrap(); |
| 835 | + let source_trait_ref = principal_a.with_self_ty(self.tcx(), source); |
| 836 | + if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object( |
| 837 | + source, |
| 838 | + obligation.param_env, |
| 839 | + &obligation.cause, |
| 840 | + ) { |
| 841 | + if deref_trait_ref.def_id() == target_trait_did { |
| 842 | + return; |
833 | 843 | }
|
| 844 | + } |
834 | 845 |
|
835 |
| - for (idx, upcast_trait_ref) in |
836 |
| - util::supertraits(self.tcx(), source_trait_ref).enumerate() |
837 |
| - { |
838 |
| - self.infcx.probe(|_| { |
839 |
| - if upcast_trait_ref.def_id() == target_trait_did |
840 |
| - && let Ok(nested) = self.match_upcast_principal( |
841 |
| - obligation, |
842 |
| - upcast_trait_ref, |
843 |
| - a_data, |
844 |
| - b_data, |
845 |
| - a_region, |
846 |
| - b_region, |
847 |
| - ) |
848 |
| - { |
849 |
| - if nested.is_none() { |
850 |
| - candidates.ambiguous = true; |
851 |
| - } |
852 |
| - candidates.vec.push(TraitUpcastingUnsizeCandidate(idx)); |
| 846 | + for (idx, upcast_trait_ref) in |
| 847 | + util::supertraits(self.tcx(), source_trait_ref).enumerate() |
| 848 | + { |
| 849 | + self.infcx.probe(|_| { |
| 850 | + if upcast_trait_ref.def_id() == target_trait_did |
| 851 | + && let Ok(nested) = self.match_upcast_principal( |
| 852 | + obligation, |
| 853 | + upcast_trait_ref, |
| 854 | + a_data, |
| 855 | + b_data, |
| 856 | + a_region, |
| 857 | + b_region, |
| 858 | + ) |
| 859 | + { |
| 860 | + if nested.is_none() { |
| 861 | + candidates.ambiguous = true; |
853 | 862 | }
|
854 |
| - }) |
855 |
| - } |
| 863 | + candidates.vec.push(TraitUpcastingUnsizeCandidate(idx)); |
| 864 | + } |
| 865 | + }) |
856 | 866 | }
|
857 | 867 | }
|
858 | 868 | }
|
|
0 commit comments