@@ -5,8 +5,9 @@ use std::iter;
55use super :: assembly:: { self , AssemblyCtxt } ;
66use super :: { CanonicalGoal , EvalCtxt , Goal , QueryResult } ;
77use rustc_hir:: def_id:: DefId ;
8- use rustc_infer:: infer:: InferOk ;
8+ use rustc_infer:: infer:: { InferOk , LateBoundRegionConversionTime } ;
99use rustc_infer:: traits:: query:: NoSolution ;
10+ use rustc_infer:: traits:: util:: supertraits;
1011use rustc_infer:: traits:: ObligationCause ;
1112use rustc_middle:: ty:: fast_reject:: { DeepRejectCtxt , TreatParams } ;
1213use rustc_middle:: ty:: TraitPredicate ;
@@ -36,6 +37,8 @@ pub(super) enum CandidateSource {
3637 /// We know that `<Whatever as Trait>::Assoc: OtherTrait` holds by looking at
3738 /// the bounds on `Trait::Assoc`.
3839 AliasBound ( usize ) ,
40+ /// Implementation of `Trait` or its supertraits for a `dyn Trait + Send + Sync`.
41+ ObjectBound ( usize ) ,
3942 /// A builtin implementation for some specific traits, used in cases
4043 /// where we cannot rely an ordinary library implementations.
4144 ///
@@ -68,7 +71,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
6871
6972 fn consider_impl_candidate (
7073 acx : & mut AssemblyCtxt < ' _ , ' tcx , Self > ,
71- goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
74+ goal : Goal < ' tcx , Self > ,
7275 impl_def_id : DefId ,
7376 ) {
7477 let tcx = acx. cx . tcx ;
@@ -108,6 +111,87 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
108111 acx. try_insert_candidate ( CandidateSource :: Impl ( impl_def_id) , certainty) ;
109112 } )
110113 }
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+ } )
111195}
112196
113197impl < ' tcx > EvalCtxt < ' tcx > {
@@ -169,6 +253,7 @@ impl<'tcx> EvalCtxt<'tcx> {
169253 ( CandidateSource :: Impl ( _) , _)
170254 | ( CandidateSource :: ParamEnv ( _) , _)
171255 | ( CandidateSource :: AliasBound ( _) , _)
256+ | ( CandidateSource :: ObjectBound ( _) , _)
172257 | ( CandidateSource :: Builtin , _)
173258 | ( CandidateSource :: AutoImpl , _) => unimplemented ! ( ) ,
174259 }
0 commit comments