@@ -471,6 +471,69 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
471
471
}
472
472
}
473
473
474
+ if let Some ( def_id) = def_id
475
+ && self . tcx . def_kind ( def_id) == hir:: def:: DefKind :: Fn
476
+ && self . tcx . is_intrinsic ( def_id)
477
+ && self . tcx . item_name ( def_id) == sym:: const_eval_select
478
+ {
479
+ let fn_sig = self . resolve_vars_if_possible ( fn_sig) ;
480
+ for idx in 0 ..=1 {
481
+ let arg_ty = fn_sig. inputs ( ) [ idx + 1 ] ;
482
+ // Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
483
+ // the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
484
+ // in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
485
+ //
486
+ // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
487
+ if let ty:: FnDef ( def_id, _args) = * arg_ty. kind ( ) {
488
+ let fn_once_def_id =
489
+ self . tcx . require_lang_item ( hir:: LangItem :: FnOnce , Some ( call_expr. span ) ) ;
490
+ let fn_once_output_def_id = self
491
+ . tcx
492
+ . require_lang_item ( hir:: LangItem :: FnOnceOutput , Some ( call_expr. span ) ) ;
493
+ if self . tcx . generics_of ( fn_once_def_id) . host_effect_index . is_none ( ) {
494
+ if idx == 0 && !self . tcx . is_const_fn_raw ( def_id) {
495
+ self . tcx
496
+ . sess
497
+ . emit_err ( errors:: ConstSelectMustBeConst { span : call_expr. span } ) ;
498
+ }
499
+ } else {
500
+ let const_param: ty:: GenericArg < ' tcx > =
501
+ ( [ self . tcx . consts . false_ , self . tcx . consts . true_ ] ) [ idx] . into ( ) ;
502
+ self . register_predicate ( traits:: Obligation :: new (
503
+ self . tcx ,
504
+ self . misc ( call_expr. span ) ,
505
+ self . param_env ,
506
+ ty:: TraitRef :: new (
507
+ self . tcx ,
508
+ fn_once_def_id,
509
+ [ arg_ty. into ( ) , fn_sig. inputs ( ) [ 0 ] . into ( ) , const_param] ,
510
+ ) ,
511
+ ) ) ;
512
+
513
+ self . register_predicate ( traits:: Obligation :: new (
514
+ self . tcx ,
515
+ self . misc ( call_expr. span ) ,
516
+ self . param_env ,
517
+ ty:: ProjectionPredicate {
518
+ projection_ty : ty:: AliasTy :: new (
519
+ self . tcx ,
520
+ fn_once_output_def_id,
521
+ [ arg_ty. into ( ) , fn_sig. inputs ( ) [ 0 ] . into ( ) , const_param] ,
522
+ ) ,
523
+ term : fn_sig. output ( ) . into ( ) ,
524
+ } ,
525
+ ) ) ;
526
+
527
+ self . select_obligations_where_possible ( |_| { } ) ;
528
+ }
529
+ } else {
530
+ self . tcx
531
+ . sess
532
+ . emit_err ( errors:: ConstSelectMustBeFn { span : call_expr. span , ty : arg_ty } ) ;
533
+ }
534
+ }
535
+ }
536
+
474
537
fn_sig. output ( )
475
538
}
476
539
0 commit comments