@@ -5,7 +5,7 @@ use std::iter;
55use super :: assembly:: { self , AssemblyCtxt } ;
66use super :: { CanonicalGoal , Certainty , EvalCtxt , Goal , QueryResult } ;
77use rustc_hir:: def_id:: DefId ;
8- use rustc_infer:: infer:: { InferOk , LateBoundRegionConversionTime } ;
8+ use rustc_infer:: infer:: { InferCtxt , InferOk , LateBoundRegionConversionTime } ;
99use rustc_infer:: traits:: query:: NoSolution ;
1010use rustc_infer:: traits:: util:: supertraits;
1111use rustc_infer:: traits:: ObligationCause ;
@@ -191,6 +191,29 @@ impl<'tcx> assembly::GoalKind<'tcx> for TraitPredicate<'tcx> {
191191 ) ;
192192 }
193193 }
194+
195+ fn consider_auto_trait_candidate (
196+ acx : & mut AssemblyCtxt < ' _ , ' tcx , Self > ,
197+ goal : Goal < ' tcx , Self > ,
198+ ) {
199+ // FIXME: We need to give auto trait candidates less precedence than impl candidates?
200+ acx. infcx . probe ( |_| {
201+ let Ok ( constituent_tys) =
202+ instantiate_constituent_tys_for_auto_trait ( acx. infcx , goal. predicate . self_ty ( ) ) else { return } ;
203+ let nested_goals = constituent_tys
204+ . into_iter ( )
205+ . map ( |ty| {
206+ Goal :: new (
207+ acx. cx . tcx ,
208+ goal. param_env ,
209+ ty:: Binder :: dummy ( goal. predicate . with_self_ty ( acx. cx . tcx , ty) ) ,
210+ )
211+ } )
212+ . collect ( ) ;
213+ let Ok ( certainty) = acx. cx . evaluate_all ( acx. infcx , nested_goals) else { return } ;
214+ acx. try_insert_candidate ( CandidateSource :: AutoImpl , certainty) ;
215+ } )
216+ }
194217}
195218
196219fn match_poly_trait_ref_against_goal < ' tcx > (
@@ -223,6 +246,77 @@ fn match_poly_trait_ref_against_goal<'tcx>(
223246 } )
224247}
225248
249+ // Calculates the constituent types of a type for `auto trait` purposes.
250+ //
251+ // For types with an "existential" binder, i.e. generator witnesses, we also
252+ // instantiate the binder with placeholders eagerly.
253+ fn instantiate_constituent_tys_for_auto_trait < ' tcx > (
254+ infcx : & InferCtxt < ' tcx > ,
255+ ty : Ty < ' tcx > ,
256+ ) -> Result < Vec < Ty < ' tcx > > , ( ) > {
257+ let tcx = infcx. tcx ;
258+ match * ty. kind ( ) {
259+ ty:: Uint ( _)
260+ | ty:: Int ( _)
261+ | ty:: Bool
262+ | ty:: Float ( _)
263+ | ty:: FnDef ( ..)
264+ | ty:: FnPtr ( _)
265+ | ty:: Str
266+ | ty:: Error ( _)
267+ | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
268+ | ty:: Never
269+ | ty:: Char => Ok ( vec ! [ ] ) ,
270+
271+ ty:: Placeholder ( ..)
272+ | ty:: Dynamic ( ..)
273+ | ty:: Param ( ..)
274+ | ty:: Foreign ( ..)
275+ | ty:: Alias ( ty:: Projection , ..)
276+ | ty:: Bound ( ..)
277+ | ty:: Infer ( ty:: TyVar ( _) ) => {
278+ // FIXME: Do we need to mark anything as ambiguous here? Yeah?
279+ Err ( ( ) )
280+ }
281+
282+ ty:: Infer ( ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => bug ! ( ) ,
283+
284+ ty:: RawPtr ( ty:: TypeAndMut { ty : element_ty, .. } ) | ty:: Ref ( _, element_ty, _) => {
285+ Ok ( vec ! [ element_ty] )
286+ }
287+
288+ ty:: Array ( element_ty, _) | ty:: Slice ( element_ty) => Ok ( vec ! [ element_ty] ) ,
289+
290+ ty:: Tuple ( ref tys) => {
291+ // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
292+ Ok ( tys. iter ( ) . collect ( ) )
293+ }
294+
295+ ty:: Closure ( _, ref substs) => Ok ( vec ! [ substs. as_closure( ) . tupled_upvars_ty( ) ] ) ,
296+
297+ ty:: Generator ( _, ref substs, _) => {
298+ let generator_substs = substs. as_generator ( ) ;
299+ Ok ( vec ! [ generator_substs. tupled_upvars_ty( ) , generator_substs. witness( ) ] )
300+ }
301+
302+ ty:: GeneratorWitness ( types) => {
303+ Ok ( infcx. replace_bound_vars_with_placeholders ( types) . to_vec ( ) )
304+ }
305+
306+ // For `PhantomData<T>`, we pass `T`.
307+ ty:: Adt ( def, substs) if def. is_phantom_data ( ) => Ok ( vec ! [ substs. type_at( 0 ) ] ) ,
308+
309+ ty:: Adt ( def, substs) => Ok ( def. all_fields ( ) . map ( |f| f. ty ( tcx, substs) ) . collect ( ) ) ,
310+
311+ ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => {
312+ // We can resolve the `impl Trait` to its concrete type,
313+ // which enforces a DAG between the functions requiring
314+ // the auto trait bounds in question.
315+ Ok ( vec ! [ tcx. bound_type_of( def_id) . subst( tcx, substs) ] )
316+ }
317+ }
318+ }
319+
226320impl < ' tcx > EvalCtxt < ' tcx > {
227321 pub ( super ) fn compute_trait_goal (
228322 & mut self ,
0 commit comments