|
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::{Obligation, PolyTraitObligation, SelectionError};
|
13 | 14 | use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
|
@@ -765,43 +766,52 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
765 | 766 | //
|
766 | 767 | // We always perform upcasting coercions when we can because of reason
|
767 | 768 | // #2 (region bounds).
|
768 |
| - let auto_traits_compatible = b_data |
769 |
| - .auto_traits() |
770 |
| - // All of a's auto traits need to be in b's auto traits. |
771 |
| - .all(|b| a_data.auto_traits().any(|a| a == b)); |
772 |
| - if auto_traits_compatible { |
773 |
| - let principal_def_id_a = a_data.principal_def_id(); |
774 |
| - let principal_def_id_b = b_data.principal_def_id(); |
775 |
| - if principal_def_id_a == principal_def_id_b { |
776 |
| - // no cyclic |
| 769 | + let principal_def_id_a = a_data.principal_def_id(); |
| 770 | + let principal_def_id_b = b_data.principal_def_id(); |
| 771 | + if principal_def_id_a == principal_def_id_b { |
| 772 | + // We may upcast to auto traits that are either explicitly listed in |
| 773 | + // the object type's bounds, or implied by the principal trait ref's |
| 774 | + // supertraits. |
| 775 | + let a_auto_traits: FxIndexSet<DefId> = a_data |
| 776 | + .auto_traits() |
| 777 | + .chain(principal_def_id_a.into_iter().flat_map(|principal_def_id| { |
| 778 | + util::supertrait_def_ids(self.tcx(), principal_def_id) |
| 779 | + .filter(|def_id| self.tcx().trait_is_auto(*def_id)) |
| 780 | + })) |
| 781 | + .collect(); |
| 782 | + let auto_traits_compatible = b_data |
| 783 | + .auto_traits() |
| 784 | + // All of a's auto traits need to be in b's auto traits. |
| 785 | + .all(|b| a_auto_traits.contains(&b)); |
| 786 | + if auto_traits_compatible { |
777 | 787 | candidates.vec.push(BuiltinUnsizeCandidate);
|
778 |
| - } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() { |
779 |
| - // not casual unsizing, now check whether this is trait upcasting coercion. |
780 |
| - let principal_a = a_data.principal().unwrap(); |
781 |
| - let target_trait_did = principal_def_id_b.unwrap(); |
782 |
| - let source_trait_ref = principal_a.with_self_ty(self.tcx(), source); |
783 |
| - |
784 |
| - for (idx, upcast_trait_ref) in |
785 |
| - util::supertraits(self.tcx(), source_trait_ref).enumerate() |
786 |
| - { |
787 |
| - self.infcx.probe(|_| { |
788 |
| - if upcast_trait_ref.def_id() == target_trait_did |
789 |
| - && let Ok(nested) = self.match_upcast_principal( |
790 |
| - obligation, |
791 |
| - upcast_trait_ref, |
792 |
| - a_data, |
793 |
| - b_data, |
794 |
| - a_region, |
795 |
| - b_region, |
796 |
| - ) |
797 |
| - { |
798 |
| - if nested.is_none() { |
799 |
| - candidates.ambiguous = true; |
800 |
| - } |
801 |
| - candidates.vec.push(TraitUpcastingUnsizeCandidate(idx)); |
| 788 | + } |
| 789 | + } else if principal_def_id_a.is_some() && principal_def_id_b.is_some() { |
| 790 | + // not casual unsizing, now check whether this is trait upcasting coercion. |
| 791 | + let principal_a = a_data.principal().unwrap(); |
| 792 | + let target_trait_did = principal_def_id_b.unwrap(); |
| 793 | + let source_trait_ref = principal_a.with_self_ty(self.tcx(), source); |
| 794 | + |
| 795 | + for (idx, upcast_trait_ref) in |
| 796 | + util::supertraits(self.tcx(), source_trait_ref).enumerate() |
| 797 | + { |
| 798 | + self.infcx.probe(|_| { |
| 799 | + if upcast_trait_ref.def_id() == target_trait_did |
| 800 | + && let Ok(nested) = self.match_upcast_principal( |
| 801 | + obligation, |
| 802 | + upcast_trait_ref, |
| 803 | + a_data, |
| 804 | + b_data, |
| 805 | + a_region, |
| 806 | + b_region, |
| 807 | + ) |
| 808 | + { |
| 809 | + if nested.is_none() { |
| 810 | + candidates.ambiguous = true; |
802 | 811 | }
|
803 |
| - }) |
804 |
| - } |
| 812 | + candidates.vec.push(TraitUpcastingUnsizeCandidate(idx)); |
| 813 | + } |
| 814 | + }) |
805 | 815 | }
|
806 | 816 | }
|
807 | 817 | }
|
|
0 commit comments