@@ -6,7 +6,7 @@ use super::assembly::{self, Candidate, CandidateSource};
66use super :: infcx_ext:: InferCtxtExt ;
77use super :: { EvalCtxt , Goal , QueryResult } ;
88use rustc_hir:: def_id:: DefId ;
9- use rustc_infer:: infer:: LateBoundRegionConversionTime ;
9+ use rustc_infer:: infer:: InferCtxt ;
1010use rustc_infer:: traits:: query:: NoSolution ;
1111use rustc_middle:: ty:: fast_reject:: { DeepRejectCtxt , TreatParams } ;
1212use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
@@ -58,13 +58,6 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
5858 } )
5959 }
6060
61- fn consider_builtin_sized_candidate (
62- _ecx : & mut EvalCtxt < ' _ , ' tcx > ,
63- _goal : Goal < ' tcx , Self > ,
64- ) -> QueryResult < ' tcx > {
65- unimplemented ! ( ) ;
66- }
67-
6861 fn consider_assumption (
6962 ecx : & mut EvalCtxt < ' _ , ' tcx > ,
7063 goal : Goal < ' tcx , Self > ,
@@ -84,9 +77,61 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
8477 Err ( NoSolution )
8578 }
8679 }
80+
81+ fn consider_auto_trait_candidate (
82+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
83+ goal : Goal < ' tcx , Self > ,
84+ ) -> QueryResult < ' tcx > {
85+ ecx. infcx . probe ( |_| {
86+ let constituent_tys =
87+ instantiate_constituent_tys_for_auto_trait ( ecx. infcx , goal. predicate . self_ty ( ) ) ?;
88+ ecx. evaluate_goal_for_constituent_tys_and_make_canonical_response ( goal, constituent_tys)
89+ } )
90+ }
91+
92+ fn consider_trait_alias_candidate (
93+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
94+ goal : Goal < ' tcx , Self > ,
95+ ) -> QueryResult < ' tcx > {
96+ let tcx = ecx. tcx ( ) ;
97+
98+ ecx. infcx . probe ( |_| {
99+ let nested_obligations = tcx
100+ . predicates_of ( goal. predicate . def_id ( ) )
101+ . instantiate ( tcx, goal. predicate . trait_ref . substs ) ;
102+ ecx. evaluate_all_and_make_canonical_response (
103+ nested_obligations. predicates . into_iter ( ) . map ( |p| goal. with ( tcx, p) ) . collect ( ) ,
104+ )
105+ } )
106+ }
107+
108+ fn consider_builtin_sized_candidate (
109+ _ecx : & mut EvalCtxt < ' _ , ' tcx > ,
110+ _goal : Goal < ' tcx , Self > ,
111+ ) -> QueryResult < ' tcx > {
112+ unimplemented ! ( ) ;
113+ }
87114}
88115
89116impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
117+ fn evaluate_goal_for_constituent_tys_and_make_canonical_response (
118+ & mut self ,
119+ goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
120+ constituent_tys : Vec < Ty < ' tcx > > ,
121+ ) -> QueryResult < ' tcx > {
122+ self . evaluate_all_and_make_canonical_response (
123+ constituent_tys
124+ . into_iter ( )
125+ . map ( |ty| {
126+ goal. with (
127+ self . tcx ( ) ,
128+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( self . tcx ( ) , ty) ) ,
129+ )
130+ } )
131+ . collect ( ) ,
132+ )
133+ }
134+
90135 pub ( super ) fn compute_trait_goal (
91136 & mut self ,
92137 goal : Goal < ' tcx , TraitPredicate < ' tcx > > ,
@@ -162,3 +207,74 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
162207 candidate
163208 }
164209}
210+
211+ // Calculates the constituent types of a type for `auto trait` purposes.
212+ //
213+ // For types with an "existential" binder, i.e. generator witnesses, we also
214+ // instantiate the binder with placeholders eagerly.
215+ fn instantiate_constituent_tys_for_auto_trait < ' tcx > (
216+ infcx : & InferCtxt < ' tcx > ,
217+ ty : Ty < ' tcx > ,
218+ ) -> Result < Vec < Ty < ' tcx > > , NoSolution > {
219+ let tcx = infcx. tcx ;
220+ match * ty. kind ( ) {
221+ ty:: Uint ( _)
222+ | ty:: Int ( _)
223+ | ty:: Bool
224+ | ty:: Float ( _)
225+ | ty:: FnDef ( ..)
226+ | ty:: FnPtr ( _)
227+ | ty:: Str
228+ | ty:: Error ( _)
229+ | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
230+ | ty:: Never
231+ | ty:: Char => Ok ( vec ! [ ] ) ,
232+
233+ ty:: Placeholder ( ..)
234+ | ty:: Dynamic ( ..)
235+ | ty:: Param ( ..)
236+ | ty:: Foreign ( ..)
237+ | ty:: Alias ( ty:: Projection , ..)
238+ | ty:: Bound ( ..)
239+ | ty:: Infer ( ty:: TyVar ( _) ) => {
240+ // FIXME: Do we need to mark anything as ambiguous here? Yeah?
241+ Err ( NoSolution )
242+ }
243+
244+ ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
245+
246+ ty:: RawPtr ( ty:: TypeAndMut { ty : element_ty, .. } ) | ty:: Ref ( _, element_ty, _) => {
247+ Ok ( vec ! [ element_ty] )
248+ }
249+
250+ ty:: Array ( element_ty, _) | ty:: Slice ( element_ty) => Ok ( vec ! [ element_ty] ) ,
251+
252+ ty:: Tuple ( ref tys) => {
253+ // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
254+ Ok ( tys. iter ( ) . collect ( ) )
255+ }
256+
257+ ty:: Closure ( _, ref substs) => Ok ( vec ! [ substs. as_closure( ) . tupled_upvars_ty( ) ] ) ,
258+
259+ ty:: Generator ( _, ref substs, _) => {
260+ let generator_substs = substs. as_generator ( ) ;
261+ Ok ( vec ! [ generator_substs. tupled_upvars_ty( ) , generator_substs. witness( ) ] )
262+ }
263+
264+ ty:: GeneratorWitness ( types) => {
265+ Ok ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
266+ }
267+
268+ // For `PhantomData<T>`, we pass `T`.
269+ ty:: Adt ( def, substs) if def. is_phantom_data ( ) => Ok ( vec ! [ substs. type_at( 0 ) ] ) ,
270+
271+ ty:: Adt ( def, substs) => Ok ( def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) ) ,
272+
273+ ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => {
274+ // We can resolve the `impl Trait` to its concrete type,
275+ // which enforces a DAG between the functions requiring
276+ // the auto trait bounds in question.
277+ Ok ( vec ! [ tcx. bound_type_of( def_id) . subst( tcx, substs) ] )
278+ }
279+ }
280+ }
0 commit comments