33
44use rustc_type_ir:: fast_reject:: DeepRejectCtxt ;
55use rustc_type_ir:: inherent:: * ;
6+ use rustc_type_ir:: lang_items:: TraitSolverLangItem ;
67use rustc_type_ir:: { self as ty, Interner , elaborate} ;
78use tracing:: instrument;
89
910use super :: assembly:: Candidate ;
1011use crate :: delegate:: SolverDelegate ;
11- use crate :: solve:: assembly:: { self } ;
1212use crate :: solve:: {
1313 BuiltinImplSource , CandidateSource , Certainty , EvalCtxt , Goal , GoalSource , NoSolution ,
14- QueryResult ,
14+ QueryResult , assembly ,
1515} ;
1616
1717impl < D , I > assembly:: GoalKind < D > for ty:: HostEffectPredicate < I >
@@ -142,7 +142,7 @@ where
142142 ty:: ImplPolarity :: Positive => { }
143143 } ;
144144
145- if !cx. is_const_impl ( impl_def_id) {
145+ if !cx. impl_is_const ( impl_def_id) {
146146 return Err ( NoSolution ) ;
147147 }
148148
@@ -207,7 +207,7 @@ where
207207 _ecx : & mut EvalCtxt < ' _ , D > ,
208208 _goal : Goal < I , Self > ,
209209 ) -> Result < Candidate < I > , NoSolution > {
210- todo ! ( "Copy/Clone is not yet const" )
210+ Err ( NoSolution )
211211 }
212212
213213 fn consider_builtin_pointer_like_candidate (
@@ -225,11 +225,104 @@ where
225225 }
226226
227227 fn consider_builtin_fn_trait_candidates (
228- _ecx : & mut EvalCtxt < ' _ , D > ,
229- _goal : Goal < I , Self > ,
228+ ecx : & mut EvalCtxt < ' _ , D > ,
229+ goal : Goal < I , Self > ,
230230 _kind : rustc_type_ir:: ClosureKind ,
231231 ) -> Result < Candidate < I > , NoSolution > {
232- todo ! ( "Fn* are not yet const" )
232+ let cx = ecx. cx ( ) ;
233+
234+ let self_ty = goal. predicate . self_ty ( ) ;
235+ let ( tupled_inputs_and_output, def_id, args) = match self_ty. kind ( ) {
236+ // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
237+ ty:: FnDef ( def_id, args) => {
238+ let sig = cx. fn_sig ( def_id) ;
239+ if sig. skip_binder ( ) . is_fn_trait_compatible ( )
240+ && !cx. has_target_features ( def_id)
241+ && cx. fn_is_const ( def_id)
242+ {
243+ (
244+ sig. instantiate ( cx, args) . map_bound ( |sig| {
245+ ( Ty :: new_tup ( cx, sig. inputs ( ) . as_slice ( ) ) , sig. output ( ) )
246+ } ) ,
247+ def_id,
248+ args,
249+ )
250+ } else {
251+ return Err ( NoSolution ) ;
252+ }
253+ }
254+ // `FnPtr`s are not const for now.
255+ ty:: FnPtr ( ..) => {
256+ return Err ( NoSolution ) ;
257+ }
258+ // `Closure`s are not const for now.
259+ ty:: Closure ( ..) => {
260+ return Err ( NoSolution ) ;
261+ }
262+ // `CoroutineClosure`s are not const for now.
263+ ty:: CoroutineClosure ( ..) => {
264+ return Err ( NoSolution ) ;
265+ }
266+
267+ ty:: Bool
268+ | ty:: Char
269+ | ty:: Int ( _)
270+ | ty:: Uint ( _)
271+ | ty:: Float ( _)
272+ | ty:: Adt ( _, _)
273+ | ty:: Foreign ( _)
274+ | ty:: Str
275+ | ty:: Array ( _, _)
276+ | ty:: Slice ( _)
277+ | ty:: RawPtr ( _, _)
278+ | ty:: Ref ( _, _, _)
279+ | ty:: Dynamic ( _, _, _)
280+ | ty:: Coroutine ( _, _)
281+ | ty:: CoroutineWitness ( ..)
282+ | ty:: Never
283+ | ty:: Tuple ( _)
284+ | ty:: Pat ( _, _)
285+ | ty:: Alias ( _, _)
286+ | ty:: Param ( _)
287+ | ty:: Placeholder ( ..)
288+ | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
289+ | ty:: Error ( _) => return Err ( NoSolution ) ,
290+
291+ ty:: Bound ( ..)
292+ | ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => {
293+ panic ! ( "unexpected type `{self_ty:?}`" )
294+ }
295+ } ;
296+
297+ let output_is_sized_pred = tupled_inputs_and_output. map_bound ( |( _, output) | {
298+ ty:: TraitRef :: new ( cx, cx. require_lang_item ( TraitSolverLangItem :: Sized ) , [ output] )
299+ } ) ;
300+ let requirements = cx
301+ . const_conditions ( def_id)
302+ . iter_instantiated ( cx, args)
303+ . map ( |trait_ref| {
304+ (
305+ GoalSource :: ImplWhereBound ,
306+ goal. with ( cx, trait_ref. to_host_effect_clause ( cx, goal. predicate . constness ) ) ,
307+ )
308+ } )
309+ // A built-in `Fn` impl only holds if the output is sized.
310+ // (FIXME: technically we only need to check this if the type is a fn ptr...)
311+ . chain ( [ ( GoalSource :: ImplWhereBound , goal. with ( cx, output_is_sized_pred) ) ] ) ;
312+
313+ let pred = tupled_inputs_and_output
314+ . map_bound ( |( inputs, _) | {
315+ ty:: TraitRef :: new ( cx, goal. predicate . def_id ( ) , [ goal. predicate . self_ty ( ) , inputs] )
316+ } )
317+ . to_host_effect_clause ( cx, goal. predicate . constness ) ;
318+
319+ Self :: probe_and_consider_implied_clause (
320+ ecx,
321+ CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ,
322+ goal,
323+ pred,
324+ requirements,
325+ )
233326 }
234327
235328 fn consider_builtin_async_fn_trait_candidates (
@@ -314,7 +407,7 @@ where
314407 _ecx : & mut EvalCtxt < ' _ , D > ,
315408 _goal : Goal < I , Self > ,
316409 ) -> Result < Candidate < I > , NoSolution > {
317- unreachable ! ( "Destruct is not const" )
410+ Err ( NoSolution )
318411 }
319412
320413 fn consider_builtin_transmute_candidate (
0 commit comments