3
3
4
4
use rustc_type_ir:: fast_reject:: DeepRejectCtxt ;
5
5
use 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} ;
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
@@ -204,7 +204,7 @@ where
204
204
_ecx : & mut EvalCtxt < ' _ , D > ,
205
205
_goal : Goal < I , Self > ,
206
206
) -> Result < Candidate < I > , NoSolution > {
207
- todo ! ( "Copy/Clone is not yet const" )
207
+ Err ( NoSolution )
208
208
}
209
209
210
210
fn consider_builtin_pointer_like_candidate (
@@ -222,11 +222,110 @@ where
222
222
}
223
223
224
224
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 > ,
227
227
_kind : rustc_type_ir:: ClosureKind ,
228
228
) -> 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
+ )
230
329
}
231
330
232
331
fn consider_builtin_async_fn_trait_candidates (
@@ -311,7 +410,7 @@ where
311
410
_ecx : & mut EvalCtxt < ' _ , D > ,
312
411
_goal : Goal < I , Self > ,
313
412
) -> Result < Candidate < I > , NoSolution > {
314
- unreachable ! ( "Destruct is not const" )
413
+ Err ( NoSolution )
315
414
}
316
415
317
416
fn consider_builtin_transmute_candidate (
0 commit comments