33
44use rustc_type_ir:: fast_reject:: DeepRejectCtxt ;
55use rustc_type_ir:: inherent:: * ;
6- use rustc_type_ir:: { self as ty, Interner , elaborate} ;
6+ use rustc_type_ir:: lang_items:: TraitSolverLangItem ;
7+ use rustc_type_ir:: { self as ty, Interner , Upcast , 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
@@ -204,7 +204,7 @@ where
204204 _ecx : & mut EvalCtxt < ' _ , D > ,
205205 _goal : Goal < I , Self > ,
206206 ) -> Result < Candidate < I > , NoSolution > {
207- todo ! ( "Copy/Clone is not yet const" )
207+ Err ( NoSolution )
208208 }
209209
210210 fn consider_builtin_pointer_like_candidate (
@@ -222,11 +222,110 @@ where
222222 }
223223
224224 fn consider_builtin_fn_trait_candidates (
225- _ecx : & mut EvalCtxt < ' _ , D > ,
226- _goal : Goal < I , Self > ,
225+ ecx : & mut EvalCtxt < ' _ , D > ,
226+ goal : Goal < I , Self > ,
227227 _kind : rustc_type_ir:: ClosureKind ,
228228 ) -> Result < Candidate < I > , NoSolution > {
229- todo ! ( "Fn* are not yet const" )
229+ let cx = ecx. cx ( ) ;
230+
231+ let self_ty = goal. predicate . self_ty ( ) ;
232+ let ( tupled_inputs_and_output, def_id, args) = match self_ty. kind ( ) {
233+ // keep this in sync with assemble_fn_pointer_candidates until the old solver is removed.
234+ ty:: FnDef ( def_id, args) => {
235+ let sig = cx. fn_sig ( def_id) ;
236+ if sig. skip_binder ( ) . is_fn_trait_compatible ( )
237+ && !cx. has_target_features ( def_id)
238+ && cx. fn_is_const ( def_id)
239+ {
240+ (
241+ sig. instantiate ( cx, args) . map_bound ( |sig| {
242+ ( Ty :: new_tup ( cx, sig. inputs ( ) . as_slice ( ) ) , sig. output ( ) )
243+ } ) ,
244+ def_id,
245+ args,
246+ )
247+ } else {
248+ return Err ( NoSolution ) ;
249+ }
250+ }
251+ // `FnPtr`s are not const for now.
252+ ty:: FnPtr ( ..) => {
253+ return Err ( NoSolution ) ;
254+ }
255+ // `Closure`s are not const for now.
256+ ty:: Closure ( ..) => {
257+ return Err ( NoSolution ) ;
258+ }
259+ // `CoroutineClosure`s are not const for now.
260+ ty:: CoroutineClosure ( ..) => {
261+ return Err ( NoSolution ) ;
262+ }
263+
264+ ty:: Bool
265+ | ty:: Char
266+ | ty:: Int ( _)
267+ | ty:: Uint ( _)
268+ | ty:: Float ( _)
269+ | ty:: Adt ( _, _)
270+ | ty:: Foreign ( _)
271+ | ty:: Str
272+ | ty:: Array ( _, _)
273+ | ty:: Slice ( _)
274+ | ty:: RawPtr ( _, _)
275+ | ty:: Ref ( _, _, _)
276+ | ty:: Dynamic ( _, _, _)
277+ | ty:: Coroutine ( _, _)
278+ | ty:: CoroutineWitness ( ..)
279+ | ty:: Never
280+ | ty:: Tuple ( _)
281+ | ty:: Pat ( _, _)
282+ | ty:: Alias ( _, _)
283+ | ty:: Param ( _)
284+ | ty:: Placeholder ( ..)
285+ | ty:: Infer ( ty:: IntVar ( _) | ty:: FloatVar ( _) )
286+ | ty:: Error ( _) => return Err ( NoSolution ) ,
287+
288+ ty:: Bound ( ..)
289+ | ty:: Infer ( ty:: TyVar ( _) | ty:: FreshTy ( _) | ty:: FreshIntTy ( _) | ty:: FreshFloatTy ( _) ) => {
290+ panic ! ( "unexpected type `{self_ty:?}`" )
291+ }
292+ } ;
293+
294+ let output_is_sized_pred = tupled_inputs_and_output. map_bound ( |( _, output) | {
295+ ty:: TraitRef :: new ( cx, cx. require_lang_item ( TraitSolverLangItem :: Sized ) , [ output] )
296+ } ) ;
297+ let requirements = cx
298+ . const_conditions ( def_id)
299+ . iter_instantiated ( cx, args)
300+ . map ( |trait_ref| {
301+ (
302+ GoalSource :: ImplWhereBound ,
303+ goal. with ( cx, trait_ref. to_host_effect_clause ( cx, goal. predicate . host ) ) ,
304+ )
305+ } )
306+ // A built-in `Fn` impl only holds if the output is sized.
307+ // (FIXME: technically we only need to check this if the type is a fn ptr...)
308+ . chain ( [ ( GoalSource :: ImplWhereBound , goal. with ( cx, output_is_sized_pred) ) ] ) ;
309+
310+ let pred = tupled_inputs_and_output
311+ . map_bound ( |( inputs, _) | {
312+ ty:: ClauseKind :: HostEffect ( ty:: HostEffectPredicate {
313+ trait_ref : ty:: TraitRef :: new ( cx, goal. predicate . def_id ( ) , [
314+ goal. predicate . self_ty ( ) ,
315+ inputs,
316+ ] ) ,
317+ host : goal. predicate . host ,
318+ } )
319+ } )
320+ . upcast ( cx) ;
321+
322+ Self :: probe_and_consider_implied_clause (
323+ ecx,
324+ CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ,
325+ goal,
326+ pred,
327+ requirements,
328+ )
230329 }
231330
232331 fn consider_builtin_async_fn_trait_candidates (
@@ -311,7 +410,7 @@ where
311410 _ecx : & mut EvalCtxt < ' _ , D > ,
312411 _goal : Goal < I , Self > ,
313412 ) -> Result < Candidate < I > , NoSolution > {
314- unreachable ! ( "Destruct is not const" )
413+ Err ( NoSolution )
315414 }
316415
317416 fn consider_builtin_transmute_candidate (
0 commit comments