@@ -5,8 +5,9 @@ use std::iter;
5
5
use super :: assembly:: { self , AssemblyCtxt } ;
6
6
use super :: { CanonicalGoal , EvalCtxt , Goal , QueryResult } ;
7
7
use rustc_hir:: def_id:: DefId ;
8
- use rustc_infer:: infer:: InferOk ;
8
+ use rustc_infer:: infer:: { InferOk , LateBoundRegionConversionTime } ;
9
9
use rustc_infer:: traits:: query:: NoSolution ;
10
+ use rustc_infer:: traits:: util:: supertraits;
10
11
use rustc_infer:: traits:: ObligationCause ;
11
12
use rustc_middle:: ty:: fast_reject:: { DeepRejectCtxt , TreatParams } ;
12
13
use rustc_middle:: ty:: TraitPredicate ;
@@ -36,6 +37,8 @@ pub(super) enum CandidateSource {
36
37
/// We know that `<Whatever as Trait>::Assoc: OtherTrait` holds by looking at
37
38
/// the bounds on `Trait::Assoc`.
38
39
AliasBound ( usize ) ,
40
+ /// Implementation of `Trait` or its supertraits for a `dyn Trait + Send + Sync`.
41
+ ObjectBound ( usize ) ,
39
42
/// A builtin implementation for some specific traits, used in cases
40
43
/// where we cannot rely an ordinary library implementations.
41
44
///
@@ -68,7 +71,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
68
71
69
72
fn consider_impl_candidate (
70
73
acx : & mut AssemblyCtxt < ' _ , ' tcx , Self > ,
71
- goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
74
+ goal : Goal < ' tcx , Self > ,
72
75
impl_def_id : DefId ,
73
76
) {
74
77
let tcx = acx. cx . tcx ;
@@ -108,6 +111,87 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
108
111
acx. try_insert_candidate ( CandidateSource :: Impl ( impl_def_id) , certainty) ;
109
112
} )
110
113
}
114
+
115
+ fn consider_alias_bound_candidates (
116
+ acx : & mut AssemblyCtxt < ' _ , ' tcx , Self > ,
117
+ goal : Goal < ' tcx , Self > ,
118
+ alias_ty : ty:: AliasTy < ' tcx > ,
119
+ ) {
120
+ for ( idx, ( predicate, _) ) in acx
121
+ . cx
122
+ . tcx
123
+ . bound_explicit_item_bounds ( alias_ty. def_id )
124
+ . subst_iter_copied ( acx. cx . tcx , alias_ty. substs )
125
+ . enumerate ( )
126
+ {
127
+ let Some ( poly_trait_pred) = predicate. to_opt_poly_trait_pred ( ) else { continue } ;
128
+ if poly_trait_pred. skip_binder ( ) . def_id ( ) != goal. predicate . def_id ( ) {
129
+ continue ;
130
+ } ;
131
+ // FIXME: constness? polarity?
132
+ let poly_trait_ref = poly_trait_pred. map_bound ( |trait_pred| trait_pred. trait_ref ) ;
133
+ // FIXME: Faster to do a filter first with a rejection context?
134
+ match_poly_trait_ref_against_goal (
135
+ acx,
136
+ goal,
137
+ poly_trait_ref,
138
+ CandidateSource :: AliasBound ( idx) ,
139
+ ) ;
140
+ }
141
+ }
142
+
143
+ fn consider_object_bound_candidates (
144
+ acx : & mut AssemblyCtxt < ' _ , ' tcx , Self > ,
145
+ goal : Goal < ' tcx , Self > ,
146
+ object_bounds : & ' tcx ty:: List < ty:: PolyExistentialPredicate < ' tcx > > ,
147
+ ) {
148
+ if let Some ( principal_trait_ref) = object_bounds. principal ( ) {
149
+ let principal_trait_ref =
150
+ principal_trait_ref. with_self_ty ( acx. cx . tcx , goal. predicate . self_ty ( ) ) ;
151
+
152
+ for ( idx, poly_trait_ref) in supertraits ( acx. cx . tcx , principal_trait_ref) . enumerate ( ) {
153
+ if poly_trait_ref. skip_binder ( ) . def_id != goal. predicate . def_id ( ) {
154
+ continue ;
155
+ } ;
156
+ match_poly_trait_ref_against_goal (
157
+ acx,
158
+ goal,
159
+ poly_trait_ref,
160
+ CandidateSource :: ObjectBound ( idx) ,
161
+ ) ;
162
+ }
163
+ }
164
+ }
165
+ }
166
+
167
+ fn match_poly_trait_ref_against_goal < ' tcx > (
168
+ acx : & mut AssemblyCtxt < ' _ , ' tcx , TraitPredicate < ' tcx > > ,
169
+ goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
170
+ trait_ref : ty:: PolyTraitRef < ' tcx > ,
171
+ candidate : impl FnOnce ( ) -> CandidateSource ,
172
+ ) {
173
+ acx. infcx . probe ( |_| {
174
+ let trait_ref = acx. infcx . replace_bound_vars_with_fresh_vars (
175
+ DUMMY_SP ,
176
+ LateBoundRegionConversionTime :: HigherRankedType ,
177
+ trait_ref,
178
+ ) ;
179
+
180
+ let Ok ( InferOk { obligations, .. } ) = acx
181
+ . infcx
182
+ . at ( & ObligationCause :: dummy ( ) , goal. param_env )
183
+ . define_opaque_types ( false )
184
+ . sup ( goal. predicate . trait_ref , trait_ref)
185
+ . map_err ( |e| debug ! ( "failed to equate trait refs: {e:?}" ) )
186
+ else {
187
+ return
188
+ } ;
189
+
190
+ let nested_goals = obligations. into_iter ( ) . map ( |o| o. into ( ) ) . collect ( ) ;
191
+
192
+ let Ok ( certainty) = acx. cx . evaluate_all ( acx. infcx , nested_goals) else { return } ;
193
+ acx. try_insert_candidate ( candidate ( ) , certainty) ;
194
+ } )
111
195
}
112
196
113
197
impl < ' tcx > EvalCtxt < ' tcx > {
@@ -169,6 +253,7 @@ impl<'tcx> EvalCtxt<'tcx> {
169
253
( CandidateSource :: Impl ( _) , _)
170
254
| ( CandidateSource :: ParamEnv ( _) , _)
171
255
| ( CandidateSource :: AliasBound ( _) , _)
256
+ | ( CandidateSource :: ObjectBound ( _) , _)
172
257
| ( CandidateSource :: Builtin , _)
173
258
| ( CandidateSource :: AutoImpl , _) => unimplemented ! ( ) ,
174
259
}
0 commit comments