11//! Code shared by trait and projection goals for candidate assembly.
22
33use super :: infcx_ext:: InferCtxtExt ;
4- use super :: { CanonicalResponse , Certainty , EvalCtxt , Goal } ;
4+ use super :: { CanonicalResponse , EvalCtxt , Goal , QueryResult } ;
55use rustc_hir:: def_id:: DefId ;
66use rustc_infer:: traits:: query:: NoSolution ;
7+ use rustc_infer:: traits:: util:: elaborate_predicates;
78use rustc_middle:: ty:: TypeFoldable ;
89use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
910use std:: fmt:: Debug ;
@@ -89,19 +90,35 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
8990 ecx : & mut EvalCtxt < ' _ , ' tcx > ,
9091 goal : Goal < ' tcx , Self > ,
9192 impl_def_id : DefId ,
92- ) -> Result < Certainty , NoSolution > ;
93+ ) -> QueryResult < ' tcx > ;
94+
95+ fn consider_assumption (
96+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
97+ goal : Goal < ' tcx , Self > ,
98+ assumption : ty:: Predicate < ' tcx > ,
99+ ) -> QueryResult < ' tcx > ;
100+
101+ fn consider_auto_trait_candidate (
102+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
103+ goal : Goal < ' tcx , Self > ,
104+ ) -> QueryResult < ' tcx > ;
105+
106+ fn consider_trait_alias_candidate (
107+ ecx : & mut EvalCtxt < ' _ , ' tcx > ,
108+ goal : Goal < ' tcx , Self > ,
109+ ) -> QueryResult < ' tcx > ;
93110
94111 fn consider_builtin_sized_candidate (
95112 ecx : & mut EvalCtxt < ' _ , ' tcx > ,
96113 goal : Goal < ' tcx , Self > ,
97- ) -> Result < Certainty , NoSolution > ;
114+ ) -> QueryResult < ' tcx > ;
98115
99- fn consider_assumption (
116+ fn consider_builtin_copy_clone_candidate (
100117 ecx : & mut EvalCtxt < ' _ , ' tcx > ,
101118 goal : Goal < ' tcx , Self > ,
102- assumption : ty:: Predicate < ' tcx > ,
103- ) -> Result < Certainty , NoSolution > ;
119+ ) -> QueryResult < ' tcx > ;
104120}
121+
105122impl < ' tcx > EvalCtxt < ' _ , ' tcx > {
106123 pub ( super ) fn assemble_and_evaluate_candidates < G : GoalKind < ' tcx > > (
107124 & mut self ,
@@ -119,6 +136,8 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
119136
120137 self . assemble_alias_bound_candidates ( goal, & mut candidates) ;
121138
139+ self . assemble_object_bound_candidates ( goal, & mut candidates) ;
140+
122141 candidates
123142 }
124143
@@ -180,9 +199,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
180199 tcx. for_each_relevant_impl (
181200 goal. predicate . trait_def_id ( tcx) ,
182201 goal. predicate . self_ty ( ) ,
183- |impl_def_id| match G :: consider_impl_candidate ( self , goal, impl_def_id)
184- . and_then ( |certainty| self . make_canonical_response ( certainty) )
185- {
202+ |impl_def_id| match G :: consider_impl_candidate ( self , goal, impl_def_id) {
186203 Ok ( result) => candidates
187204 . push ( Candidate { source : CandidateSource :: Impl ( impl_def_id) , result } ) ,
188205 Err ( NoSolution ) => ( ) ,
@@ -197,13 +214,21 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
197214 ) {
198215 let lang_items = self . tcx ( ) . lang_items ( ) ;
199216 let trait_def_id = goal. predicate . trait_def_id ( self . tcx ( ) ) ;
200- let result = if lang_items. sized_trait ( ) == Some ( trait_def_id) {
217+ let result = if self . tcx ( ) . trait_is_auto ( trait_def_id) {
218+ G :: consider_auto_trait_candidate ( self , goal)
219+ } else if self . tcx ( ) . trait_is_alias ( trait_def_id) {
220+ G :: consider_trait_alias_candidate ( self , goal)
221+ } else if lang_items. sized_trait ( ) == Some ( trait_def_id) {
201222 G :: consider_builtin_sized_candidate ( self , goal)
223+ } else if lang_items. copy_trait ( ) == Some ( trait_def_id)
224+ || lang_items. clone_trait ( ) == Some ( trait_def_id)
225+ {
226+ G :: consider_builtin_copy_clone_candidate ( self , goal)
202227 } else {
203228 Err ( NoSolution )
204229 } ;
205230
206- match result. and_then ( |certainty| self . make_canonical_response ( certainty ) ) {
231+ match result {
207232 Ok ( result) => {
208233 candidates. push ( Candidate { source : CandidateSource :: BuiltinImpl , result } )
209234 }
@@ -217,9 +242,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
217242 candidates : & mut Vec < Candidate < ' tcx > > ,
218243 ) {
219244 for ( i, assumption) in goal. param_env . caller_bounds ( ) . iter ( ) . enumerate ( ) {
220- match G :: consider_assumption ( self , goal, assumption)
221- . and_then ( |certainty| self . make_canonical_response ( certainty) )
222- {
245+ match G :: consider_assumption ( self , goal, assumption) {
223246 Ok ( result) => {
224247 candidates. push ( Candidate { source : CandidateSource :: ParamEnv ( i) , result } )
225248 }
@@ -268,14 +291,60 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
268291 . subst_iter_copied ( self . tcx ( ) , alias_ty. substs )
269292 . enumerate ( )
270293 {
271- match G :: consider_assumption ( self , goal, assumption)
272- . and_then ( |certainty| self . make_canonical_response ( certainty) )
273- {
294+ match G :: consider_assumption ( self , goal, assumption) {
274295 Ok ( result) => {
275296 candidates. push ( Candidate { source : CandidateSource :: AliasBound ( i) , result } )
276297 }
277298 Err ( NoSolution ) => ( ) ,
278299 }
279300 }
280301 }
302+
303+ fn assemble_object_bound_candidates < G : GoalKind < ' tcx > > (
304+ & mut self ,
305+ goal : Goal < ' tcx , G > ,
306+ candidates : & mut Vec < Candidate < ' tcx > > ,
307+ ) {
308+ let self_ty = goal. predicate . self_ty ( ) ;
309+ let bounds = match * self_ty. kind ( ) {
310+ ty:: Bool
311+ | ty:: Char
312+ | ty:: Int ( _)
313+ | ty:: Uint ( _)
314+ | ty:: Float ( _)
315+ | ty:: Adt ( _, _)
316+ | ty:: Foreign ( _)
317+ | ty:: Str
318+ | ty:: Array ( _, _)
319+ | ty:: Slice ( _)
320+ | ty:: RawPtr ( _)
321+ | ty:: Ref ( _, _, _)
322+ | ty:: FnDef ( _, _)
323+ | ty:: FnPtr ( _)
324+ | ty:: Alias ( ..)
325+ | ty:: Closure ( ..)
326+ | ty:: Generator ( ..)
327+ | ty:: GeneratorWitness ( _)
328+ | ty:: Never
329+ | ty:: Tuple ( _)
330+ | ty:: Param ( _)
331+ | ty:: Placeholder ( ..)
332+ | ty:: Infer ( _)
333+ | ty:: Error ( _) => return ,
334+ ty:: Bound ( ..) => bug ! ( "unexpected bound type: {goal:?}" ) ,
335+ ty:: Dynamic ( bounds, ..) => bounds,
336+ } ;
337+
338+ let tcx = self . tcx ( ) ;
339+ for assumption in
340+ elaborate_predicates ( tcx, bounds. iter ( ) . map ( |bound| bound. with_self_ty ( tcx, self_ty) ) )
341+ {
342+ match G :: consider_assumption ( self , goal, assumption. predicate ) {
343+ Ok ( result) => {
344+ candidates. push ( Candidate { source : CandidateSource :: BuiltinImpl , result } )
345+ }
346+ Err ( NoSolution ) => ( ) ,
347+ }
348+ }
349+ }
281350}
0 commit comments