@@ -3,6 +3,7 @@ use std::cmp::max;
3
3
use std:: ops:: Deref ;
4
4
5
5
use rustc_data_structures:: fx:: FxHashSet ;
6
+ use rustc_data_structures:: sso:: SsoHashSet ;
6
7
use rustc_errors:: Applicability ;
7
8
use rustc_hir as hir;
8
9
use rustc_hir:: HirId ;
@@ -33,6 +34,7 @@ use rustc_trait_selection::traits::query::method_autoderef::{
33
34
CandidateStep , MethodAutoderefBadTy , MethodAutoderefStepsResult ,
34
35
} ;
35
36
use rustc_trait_selection:: traits:: { self , ObligationCause , ObligationCtxt } ;
37
+ use rustc_type_ir:: elaborate:: supertrait_def_ids;
36
38
use smallvec:: { SmallVec , smallvec} ;
37
39
use tracing:: { debug, instrument} ;
38
40
@@ -1614,10 +1616,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1614
1616
debug ! ( "applicable_candidates: {:?}" , applicable_candidates) ;
1615
1617
1616
1618
if applicable_candidates. len ( ) > 1 {
1617
- if let Some ( pick) =
1618
- self . collapse_candidates_to_trait_pick ( self_ty, & applicable_candidates)
1619
- {
1620
- return Some ( Ok ( pick) ) ;
1619
+ if self . tcx . features ( ) . supertrait_item_shadowing ( ) {
1620
+ if let Some ( pick) =
1621
+ self . collapse_candidates_to_subtrait_pick ( self_ty, & applicable_candidates)
1622
+ {
1623
+ return Some ( Ok ( pick) ) ;
1624
+ }
1625
+ } else {
1626
+ if let Some ( pick) =
1627
+ self . collapse_candidates_to_trait_pick ( self_ty, & applicable_candidates)
1628
+ {
1629
+ return Some ( Ok ( pick) ) ;
1630
+ }
1621
1631
}
1622
1632
}
1623
1633
@@ -2084,6 +2094,52 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
2084
2094
} )
2085
2095
}
2086
2096
2097
+ /// Much like `collapse_candidates_to_trait_pick`, this method allows us to collapse
2098
+ /// multiple conflicting picks if there is one pick whose trait container is a subtrait
2099
+ /// of the trait containers of all of the other picks.
2100
+ ///
2101
+ /// This implements RFC #3624.
2102
+ fn collapse_candidates_to_subtrait_pick (
2103
+ & self ,
2104
+ self_ty : Ty < ' tcx > ,
2105
+ probes : & [ ( & Candidate < ' tcx > , ProbeResult ) ] ,
2106
+ ) -> Option < Pick < ' tcx > > {
2107
+ let mut child_pick = probes[ 0 ] . 0 ;
2108
+ let mut supertraits: SsoHashSet < _ > =
2109
+ supertrait_def_ids ( self . tcx , child_pick. item . trait_container ( self . tcx ) ?) . collect ( ) ;
2110
+
2111
+ // All other picks should be a supertrait of the `child_pick`.
2112
+ // If it's not, then we update the `child_pick` and the `supertraits`
2113
+ // list.
2114
+ for ( p, _) in & probes[ 1 ..] {
2115
+ let p_container = p. item . trait_container ( self . tcx ) ?;
2116
+ if !supertraits. contains ( & p_container) {
2117
+ // This pick is not a supertrait of the `child_pick`.
2118
+ // Check if it's a subtrait of the `child_pick`, which
2119
+ // is sufficient to imply that all of the previous picks
2120
+ // are also supertraits of this pick.
2121
+ supertraits = supertrait_def_ids ( self . tcx , p_container) . collect ( ) ;
2122
+ if supertraits. contains ( & child_pick. item . trait_container ( self . tcx ) . unwrap ( ) ) {
2123
+ child_pick = * p;
2124
+ } else {
2125
+ // `child_pick` is not a supertrait of this pick. Bail.
2126
+ return None ;
2127
+ }
2128
+ }
2129
+ }
2130
+
2131
+ Some ( Pick {
2132
+ item : child_pick. item ,
2133
+ kind : TraitPick ,
2134
+ import_ids : child_pick. import_ids . clone ( ) ,
2135
+ autoderefs : 0 ,
2136
+ autoref_or_ptr_adjustment : None ,
2137
+ self_ty,
2138
+ unstable_candidates : vec ! [ ] ,
2139
+ receiver_steps : None ,
2140
+ } )
2141
+ }
2142
+
2087
2143
/// Similarly to `probe_for_return_type`, this method attempts to find the best matching
2088
2144
/// candidate method where the method name may have been misspelled. Similarly to other
2089
2145
/// edit distance based suggestions, we provide at most one such suggestion.
0 commit comments