Skip to content

Commit b4089bf

Browse files
authored
Rollup merge of #143640 - oli-obk:const-fn-traits, r=compiler-errors
Constify `Fn*` traits r? `@compiler-errors` `@fee1-dead` this should unlock a few things. A few `const_closures` tests have broken even more than before, but that feature is marked as incomplete anyway cc #67792
2 parents 95cbacd + b1d45f6 commit b4089bf

28 files changed

+146
-626
lines changed

compiler/rustc_hir_typeck/messages.ftl

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,6 @@ hir_typeck_cast_unknown_pointer = cannot cast {$to ->
8282
hir_typeck_const_continue_bad_label =
8383
`#[const_continue]` must break to a labeled block that participates in a `#[loop_match]`
8484
85-
hir_typeck_const_select_must_be_const = this argument must be a `const fn`
86-
.help = consult the documentation on `const_eval_select` for more information
87-
88-
hir_typeck_const_select_must_be_fn = this argument must be a function item
89-
.note = expected a function item, found {$ty}
90-
.help = consult the documentation on `const_eval_select` for more information
91-
9285
hir_typeck_continue_labeled_block =
9386
`continue` pointing to a labeled block
9487
.label = labeled blocks cannot be `continue`'d

compiler/rustc_hir_typeck/src/callee.rs

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -578,29 +578,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
578578
}
579579
}
580580

581-
if let Some(def_id) = def_id
582-
&& self.tcx.def_kind(def_id) == hir::def::DefKind::Fn
583-
&& self.tcx.is_intrinsic(def_id, sym::const_eval_select)
584-
{
585-
let fn_sig = self.resolve_vars_if_possible(fn_sig);
586-
for idx in 0..=1 {
587-
let arg_ty = fn_sig.inputs()[idx + 1];
588-
let span = arg_exprs.get(idx + 1).map_or(call_expr.span, |arg| arg.span);
589-
// Check that second and third argument of `const_eval_select` must be `FnDef`, and additionally that
590-
// the second argument must be `const fn`. The first argument must be a tuple, but this is already expressed
591-
// in the function signature (`F: FnOnce<ARG>`), so I did not bother to add another check here.
592-
//
593-
// This check is here because there is currently no way to express a trait bound for `FnDef` types only.
594-
if let ty::FnDef(def_id, _args) = *arg_ty.kind() {
595-
if idx == 0 && !self.tcx.is_const_fn(def_id) {
596-
self.dcx().emit_err(errors::ConstSelectMustBeConst { span });
597-
}
598-
} else {
599-
self.dcx().emit_err(errors::ConstSelectMustBeFn { span, ty: arg_ty });
600-
}
601-
}
602-
}
603-
604581
fn_sig.output()
605582
}
606583

compiler/rustc_hir_typeck/src/errors.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -605,24 +605,6 @@ impl Subdiagnostic for RemoveSemiForCoerce {
605605
}
606606
}
607607

608-
#[derive(Diagnostic)]
609-
#[diag(hir_typeck_const_select_must_be_const)]
610-
#[help]
611-
pub(crate) struct ConstSelectMustBeConst {
612-
#[primary_span]
613-
pub span: Span,
614-
}
615-
616-
#[derive(Diagnostic)]
617-
#[diag(hir_typeck_const_select_must_be_fn)]
618-
#[note]
619-
#[help]
620-
pub(crate) struct ConstSelectMustBeFn<'a> {
621-
#[primary_span]
622-
pub span: Span,
623-
pub ty: Ty<'a>,
624-
}
625-
626608
#[derive(Diagnostic)]
627609
#[diag(hir_typeck_union_pat_multiple_fields)]
628610
pub(crate) struct UnionPatMultipleFields {

compiler/rustc_hir_typeck/src/upvar.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -529,7 +529,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
529529
// process any deferred resolutions.
530530
let deferred_call_resolutions = self.remove_deferred_call_resolutions(closure_def_id);
531531
for deferred_call_resolution in deferred_call_resolutions {
532-
deferred_call_resolution.resolve(self);
532+
deferred_call_resolution.resolve(&mut FnCtxt::new(
533+
self,
534+
self.param_env,
535+
closure_def_id,
536+
));
533537
}
534538
}
535539

compiler/rustc_trait_selection/src/traits/effects.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use rustc_hir::{self as hir, LangItem};
22
use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes};
33
use rustc_infer::traits::{
4-
ImplDerivedHostCause, ImplSource, Obligation, ObligationCauseCode, PredicateObligation,
4+
ImplDerivedHostCause, ImplSource, Obligation, ObligationCause, ObligationCauseCode,
5+
PredicateObligation,
56
};
67
use rustc_middle::span_bug;
78
use rustc_middle::traits::query::NoSolution;
@@ -303,6 +304,9 @@ fn evaluate_host_effect_from_builtin_impls<'tcx>(
303304
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
304305
match selcx.tcx().as_lang_item(obligation.predicate.def_id()) {
305306
Some(LangItem::Destruct) => evaluate_host_effect_for_destruct_goal(selcx, obligation),
307+
Some(LangItem::Fn | LangItem::FnMut | LangItem::FnOnce) => {
308+
evaluate_host_effect_for_fn_goal(selcx, obligation)
309+
}
306310
_ => Err(EvaluationFailure::NoSolution),
307311
}
308312
}
@@ -398,6 +402,51 @@ fn evaluate_host_effect_for_destruct_goal<'tcx>(
398402
.collect())
399403
}
400404

405+
// NOTE: Keep this in sync with `extract_fn_def_from_const_callable` in the new solver.
406+
fn evaluate_host_effect_for_fn_goal<'tcx>(
407+
selcx: &mut SelectionContext<'_, 'tcx>,
408+
obligation: &HostEffectObligation<'tcx>,
409+
) -> Result<ThinVec<PredicateObligation<'tcx>>, EvaluationFailure> {
410+
let tcx = selcx.tcx();
411+
let self_ty = obligation.predicate.self_ty();
412+
413+
let (def, args) = match *self_ty.kind() {
414+
ty::FnDef(def, args) => (def, args),
415+
416+
// We may support function pointers at some point in the future
417+
ty::FnPtr(..) => return Err(EvaluationFailure::NoSolution),
418+
419+
// Closures could implement `[const] Fn`,
420+
// but they don't really need to right now.
421+
ty::Closure(..) | ty::CoroutineClosure(_, _) => {
422+
return Err(EvaluationFailure::NoSolution);
423+
}
424+
425+
// Everything else needs explicit impls or cannot have an impl
426+
_ => return Err(EvaluationFailure::NoSolution),
427+
};
428+
429+
match tcx.constness(def) {
430+
hir::Constness::Const => Ok(tcx
431+
.const_conditions(def)
432+
.instantiate(tcx, args)
433+
.into_iter()
434+
.map(|(c, span)| {
435+
let code = ObligationCauseCode::WhereClause(def, span);
436+
let cause =
437+
ObligationCause::new(obligation.cause.span, obligation.cause.body_id, code);
438+
Obligation::new(
439+
tcx,
440+
cause,
441+
obligation.param_env,
442+
c.to_host_effect_clause(tcx, obligation.predicate.constness),
443+
)
444+
})
445+
.collect()),
446+
hir::Constness::NotConst => Err(EvaluationFailure::NoSolution),
447+
}
448+
}
449+
401450
fn evaluate_host_effect_from_selection_candidate<'tcx>(
402451
selcx: &mut SelectionContext<'_, 'tcx>,
403452
obligation: &HostEffectObligation<'tcx>,

library/core/src/intrinsics/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2279,7 +2279,7 @@ pub const fn const_eval_select<ARG: Tuple, F, G, RET>(
22792279
) -> RET
22802280
where
22812281
G: FnOnce<ARG, Output = RET>,
2282-
F: FnOnce<ARG, Output = RET>;
2282+
F: const FnOnce<ARG, Output = RET>;
22832283

22842284
/// A macro to make it easier to invoke const_eval_select. Use as follows:
22852285
/// ```rust,ignore (just a macro example)

library/core/src/ops/function.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ use crate::marker::Tuple;
7272
)]
7373
#[fundamental] // so that regex can rely that `&str: !FnMut`
7474
#[must_use = "closures are lazy and do nothing unless called"]
75-
// FIXME(const_trait_impl) #[const_trait]
75+
#[const_trait]
76+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
7677
pub trait Fn<Args: Tuple>: FnMut<Args> {
7778
/// Performs the call operation.
7879
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -159,7 +160,8 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
159160
)]
160161
#[fundamental] // so that regex can rely that `&str: !FnMut`
161162
#[must_use = "closures are lazy and do nothing unless called"]
162-
// FIXME(const_trait_impl) #[const_trait]
163+
#[const_trait]
164+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
163165
pub trait FnMut<Args: Tuple>: FnOnce<Args> {
164166
/// Performs the call operation.
165167
#[unstable(feature = "fn_traits", issue = "29625")]
@@ -238,7 +240,8 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
238240
)]
239241
#[fundamental] // so that regex can rely that `&str: !FnMut`
240242
#[must_use = "closures are lazy and do nothing unless called"]
241-
// FIXME(const_trait_impl) #[const_trait]
243+
#[const_trait]
244+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
242245
pub trait FnOnce<Args: Tuple> {
243246
/// The returned type after the call operator is used.
244247
#[lang = "fn_once_output"]
@@ -254,29 +257,32 @@ mod impls {
254257
use crate::marker::Tuple;
255258

256259
#[stable(feature = "rust1", since = "1.0.0")]
257-
impl<A: Tuple, F: ?Sized> Fn<A> for &F
260+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
261+
impl<A: Tuple, F: ?Sized> const Fn<A> for &F
258262
where
259-
F: Fn<A>,
263+
F: ~const Fn<A>,
260264
{
261265
extern "rust-call" fn call(&self, args: A) -> F::Output {
262266
(**self).call(args)
263267
}
264268
}
265269

266270
#[stable(feature = "rust1", since = "1.0.0")]
267-
impl<A: Tuple, F: ?Sized> FnMut<A> for &F
271+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
272+
impl<A: Tuple, F: ?Sized> const FnMut<A> for &F
268273
where
269-
F: Fn<A>,
274+
F: ~const Fn<A>,
270275
{
271276
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
272277
(**self).call(args)
273278
}
274279
}
275280

276281
#[stable(feature = "rust1", since = "1.0.0")]
277-
impl<A: Tuple, F: ?Sized> FnOnce<A> for &F
282+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
283+
impl<A: Tuple, F: ?Sized> const FnOnce<A> for &F
278284
where
279-
F: Fn<A>,
285+
F: ~const Fn<A>,
280286
{
281287
type Output = F::Output;
282288

@@ -286,19 +292,21 @@ mod impls {
286292
}
287293

288294
#[stable(feature = "rust1", since = "1.0.0")]
289-
impl<A: Tuple, F: ?Sized> FnMut<A> for &mut F
295+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
296+
impl<A: Tuple, F: ?Sized> const FnMut<A> for &mut F
290297
where
291-
F: FnMut<A>,
298+
F: ~const FnMut<A>,
292299
{
293300
extern "rust-call" fn call_mut(&mut self, args: A) -> F::Output {
294301
(*self).call_mut(args)
295302
}
296303
}
297304

298305
#[stable(feature = "rust1", since = "1.0.0")]
299-
impl<A: Tuple, F: ?Sized> FnOnce<A> for &mut F
306+
#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")]
307+
impl<A: Tuple, F: ?Sized> const FnOnce<A> for &mut F
300308
where
301-
F: FnMut<A>,
309+
F: ~const FnMut<A>,
302310
{
303311
type Output = F::Output;
304312
extern "rust-call" fn call_once(self, args: A) -> F::Output {

0 commit comments

Comments
 (0)