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
9- use super :: assembly:: Candidate ;
10+ use super :: assembly:: { Candidate , structural_traits } ;
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,48 @@ 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 ( inputs_and_output, def_id, args) =
236+ structural_traits:: extract_fn_def_from_const_callable ( cx, self_ty) ?;
237+
238+ // A built-in `Fn` impl only holds if the output is sized.
239+ // (FIXME: technically we only need to check this if the type is a fn ptr...)
240+ let output_is_sized_pred = inputs_and_output. map_bound ( |( _, output) | {
241+ ty:: TraitRef :: new ( cx, cx. require_lang_item ( TraitSolverLangItem :: Sized ) , [ output] )
242+ } ) ;
243+ let requirements = cx
244+ . const_conditions ( def_id)
245+ . iter_instantiated ( cx, args)
246+ . map ( |trait_ref| {
247+ (
248+ GoalSource :: ImplWhereBound ,
249+ goal. with ( cx, trait_ref. to_host_effect_clause ( cx, goal. predicate . constness ) ) ,
250+ )
251+ } )
252+ . chain ( [ ( GoalSource :: ImplWhereBound , goal. with ( cx, output_is_sized_pred) ) ] ) ;
253+
254+ let pred = inputs_and_output
255+ . map_bound ( |( inputs, _) | {
256+ ty:: TraitRef :: new ( cx, goal. predicate . def_id ( ) , [
257+ goal. predicate . self_ty ( ) ,
258+ Ty :: new_tup ( cx, inputs. as_slice ( ) ) ,
259+ ] )
260+ } )
261+ . to_host_effect_clause ( cx, goal. predicate . constness ) ;
262+
263+ Self :: probe_and_consider_implied_clause (
264+ ecx,
265+ CandidateSource :: BuiltinImpl ( BuiltinImplSource :: Misc ) ,
266+ goal,
267+ pred,
268+ requirements,
269+ )
233270 }
234271
235272 fn consider_builtin_async_fn_trait_candidates (
@@ -314,7 +351,7 @@ where
314351 _ecx : & mut EvalCtxt < ' _ , D > ,
315352 _goal : Goal < I , Self > ,
316353 ) -> Result < Candidate < I > , NoSolution > {
317- unreachable ! ( "Destruct is not const" )
354+ Err ( NoSolution )
318355 }
319356
320357 fn consider_builtin_transmute_candidate (
0 commit comments