@@ -4,6 +4,7 @@ use std::iter;
4
4
use std:: ops:: Deref ;
5
5
6
6
use rustc_data_structures:: fx:: FxHashSet ;
7
+ use rustc_data_structures:: sso:: SsoHashSet ;
7
8
use rustc_errors:: Applicability ;
8
9
use rustc_hir as hir;
9
10
use rustc_hir:: HirId ;
@@ -35,6 +36,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
35
36
CandidateStep , MethodAutoderefBadTy , MethodAutoderefStepsResult ,
36
37
} ;
37
38
use rustc_trait_selection:: traits:: { self , ObligationCause , ObligationCtxt } ;
39
+ use rustc_type_ir:: elaborate:: supertrait_def_ids;
38
40
use smallvec:: { SmallVec , smallvec} ;
39
41
use tracing:: { debug, instrument} ;
40
42
@@ -1315,10 +1317,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1315
1317
debug ! ( "applicable_candidates: {:?}" , applicable_candidates) ;
1316
1318
1317
1319
if applicable_candidates. len ( ) > 1 {
1318
- if let Some ( pick) =
1319
- self . collapse_candidates_to_trait_pick ( self_ty, & applicable_candidates)
1320
- {
1321
- return Some ( Ok ( pick) ) ;
1320
+ if self . tcx . features ( ) . supertrait_item_shadowing {
1321
+ if let Some ( pick) =
1322
+ self . collapse_candidates_to_subtrait_pick ( self_ty, & applicable_candidates)
1323
+ {
1324
+ return Some ( Ok ( pick) ) ;
1325
+ }
1326
+ } else {
1327
+ if let Some ( pick) =
1328
+ self . collapse_candidates_to_trait_pick ( self_ty, & applicable_candidates)
1329
+ {
1330
+ return Some ( Ok ( pick) ) ;
1331
+ }
1322
1332
}
1323
1333
}
1324
1334
@@ -1751,6 +1761,51 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1751
1761
} )
1752
1762
}
1753
1763
1764
+ /// Much like `collapse_candidates_to_trait_pick`, this method allows us to collapse
1765
+ /// multiple conflicting picks if there is one pick whose trait container is a subtrait
1766
+ /// of the trait containers of all of the other picks.
1767
+ ///
1768
+ /// This implements RFC #3624.
1769
+ fn collapse_candidates_to_subtrait_pick (
1770
+ & self ,
1771
+ self_ty : Ty < ' tcx > ,
1772
+ probes : & [ ( & Candidate < ' tcx > , ProbeResult ) ] ,
1773
+ ) -> Option < Pick < ' tcx > > {
1774
+ let mut child_pick = probes[ 0 ] . 0 ;
1775
+ let mut supertraits: SsoHashSet < _ > =
1776
+ supertrait_def_ids ( self . tcx , child_pick. item . trait_container ( self . tcx ) ?) . collect ( ) ;
1777
+
1778
+ // All other picks should be a supertrait of the `child_pick`.
1779
+ // If it's not, then we update the `child_pick` and the `supertraits`
1780
+ // list.
1781
+ for ( p, _) in & probes[ 1 ..] {
1782
+ let p_container = p. item . trait_container ( self . tcx ) ?;
1783
+ if !supertraits. contains ( & p_container) {
1784
+ // This pick is not a supertrait of the `child_pick`.
1785
+ // Check if it's a subtrait of the `child_pick`, which
1786
+ // is sufficient to imply that all of the previous picks
1787
+ // are also supertraits of this pick.
1788
+ supertraits = supertrait_def_ids ( self . tcx , p_container) . collect ( ) ;
1789
+ if supertraits. contains ( & child_pick. item . trait_container ( self . tcx ) . unwrap ( ) ) {
1790
+ child_pick = * p;
1791
+ } else {
1792
+ // `child_pick` is not a supertrait of this pick. Bail.
1793
+ return None ;
1794
+ }
1795
+ }
1796
+ }
1797
+
1798
+ Some ( Pick {
1799
+ item : child_pick. item ,
1800
+ kind : TraitPick ,
1801
+ import_ids : child_pick. import_ids . clone ( ) ,
1802
+ autoderefs : 0 ,
1803
+ autoref_or_ptr_adjustment : None ,
1804
+ self_ty,
1805
+ unstable_candidates : vec ! [ ] ,
1806
+ } )
1807
+ }
1808
+
1754
1809
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
1755
1810
/// candidate method where the method name may have been misspelled. Similarly to other
1756
1811
/// edit distance based suggestions, we provide at most one such suggestion.
0 commit comments