3
3
4
4
use rustc_type_ir:: fast_reject:: DeepRejectCtxt ;
5
5
use rustc_type_ir:: inherent:: * ;
6
+ use rustc_type_ir:: lang_items:: TraitSolverLangItem ;
6
7
use rustc_type_ir:: { self as ty, Interner , elaborate} ;
7
8
use tracing:: instrument;
8
9
9
10
use super :: assembly:: Candidate ;
10
11
use crate :: delegate:: SolverDelegate ;
11
- use crate :: solve:: assembly:: { self } ;
12
12
use crate :: solve:: {
13
13
BuiltinImplSource , CandidateSource , Certainty , EvalCtxt , Goal , GoalSource , NoSolution ,
14
- QueryResult ,
14
+ QueryResult , assembly ,
15
15
} ;
16
16
17
17
impl < D , I > assembly:: GoalKind < D > for ty:: HostEffectPredicate < I >
@@ -142,7 +142,7 @@ where
142
142
ty:: ImplPolarity :: Positive => { }
143
143
} ;
144
144
145
- if !cx. is_const_impl ( impl_def_id) {
145
+ if !cx. impl_is_const ( impl_def_id) {
146
146
return Err ( NoSolution ) ;
147
147
}
148
148
@@ -207,7 +207,7 @@ where
207
207
_ecx : & mut EvalCtxt < ' _ , D > ,
208
208
_goal : Goal < I , Self > ,
209
209
) -> Result < Candidate < I > , NoSolution > {
210
- todo ! ( "Copy/Clone is not yet const" )
210
+ Err ( NoSolution )
211
211
}
212
212
213
213
fn consider_builtin_pointer_like_candidate (
@@ -225,11 +225,104 @@ where
225
225
}
226
226
227
227
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 > ,
230
230
_kind : rustc_type_ir:: ClosureKind ,
231
231
) -> 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
+ )
233
326
}
234
327
235
328
fn consider_builtin_async_fn_trait_candidates (
@@ -314,7 +407,7 @@ where
314
407
_ecx : & mut EvalCtxt < ' _ , D > ,
315
408
_goal : Goal < I , Self > ,
316
409
) -> Result < Candidate < I > , NoSolution > {
317
- unreachable ! ( "Destruct is not const" )
410
+ Err ( NoSolution )
318
411
}
319
412
320
413
fn consider_builtin_transmute_candidate (
0 commit comments