Skip to content

Commit f8aa73d

Browse files
committed
Coerce const FnDefs to implement const Fn traits
1 parent d3f981b commit f8aa73d

File tree

7 files changed

+55
-13
lines changed

7 files changed

+55
-13
lines changed

compiler/rustc_const_eval/src/transform/promote_consts.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -655,8 +655,7 @@ impl<'tcx> Validator<'_, 'tcx> {
655655

656656
let is_const_fn = match *fn_ty.kind() {
657657
ty::FnDef(def_id, _) => {
658-
self.tcx.is_const_fn_raw(def_id)
659-
|| is_lang_panic_fn(self.tcx, def_id)
658+
self.tcx.is_const_fn_raw(def_id) || is_lang_panic_fn(self.tcx, def_id)
660659
}
661660
_ => false,
662661
};

compiler/rustc_middle/src/traits/select.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,9 @@ pub enum SelectionCandidate<'tcx> {
120120

121121
/// Implementation of a `Fn`-family trait by one of the anonymous
122122
/// types generated for a fn pointer type (e.g., `fn(int) -> int`)
123-
FnPointerCandidate,
123+
FnPointerCandidate {
124+
is_const: bool,
125+
},
124126

125127
/// Builtin implementation of `DiscriminantKind`.
126128
DiscriminantKindCandidate,

compiler/rustc_middle/src/ty/context.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -2750,7 +2750,10 @@ impl<'tcx> TyCtxt<'tcx> {
27502750
Some(stability) if stability.level.is_unstable() => {
27512751
// has a `rustc_const_unstable` attribute, check whether the user enabled the
27522752
// corresponding feature gate.
2753-
self.features().declared_lib_features.iter().any(|&(sym, _)| sym == stability.feature)
2753+
self.features()
2754+
.declared_lib_features
2755+
.iter()
2756+
.any(|&(sym, _)| sym == stability.feature)
27542757
}
27552758
// functions without const stability are either stable user written
27562759
// const fn or the user is using feature gates and we thus don't

compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
475475
..
476476
} = self_ty.fn_sig(self.tcx()).skip_binder()
477477
{
478-
candidates.vec.push(FnPointerCandidate);
478+
candidates.vec.push(FnPointerCandidate { is_const: false });
479479
}
480480
}
481481
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
@@ -488,7 +488,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
488488
} = self_ty.fn_sig(self.tcx()).skip_binder()
489489
{
490490
if self.tcx().codegen_fn_attrs(def_id).target_features.is_empty() {
491-
candidates.vec.push(FnPointerCandidate);
491+
candidates
492+
.vec
493+
.push(FnPointerCandidate { is_const: self.tcx().is_const_fn(def_id) });
492494
}
493495
}
494496
}

compiler/rustc_trait_selection/src/traits/select/confirmation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
9292
Ok(ImplSource::Generator(vtable_generator))
9393
}
9494

95-
FnPointerCandidate => {
95+
FnPointerCandidate { .. } => {
9696
let data = self.confirm_fn_pointer_candidate(obligation)?;
9797
Ok(ImplSource::FnPointer(data))
9898
}

compiler/rustc_trait_selection/src/traits/select/mod.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -1100,6 +1100,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
11001100
// generator, this will raise error in other places
11011101
// or ignore error with const_async_blocks feature
11021102
GeneratorCandidate => {}
1103+
// FnDef where the function is const
1104+
FnPointerCandidate { is_const: true } => {}
11031105
ConstDropCandidate => {}
11041106
_ => {
11051107
// reject all other types of candidates
@@ -1513,6 +1515,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15131515
}
15141516
}
15151517

1518+
// Drop otherwise equivalent non-const fn pointer candidates
1519+
(FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => true,
1520+
15161521
// Global bounds from the where clause should be ignored
15171522
// here (see issue #50825). Otherwise, we have a where
15181523
// clause so don't go around looking for impls.
@@ -1523,7 +1528,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15231528
ImplCandidate(..)
15241529
| ClosureCandidate
15251530
| GeneratorCandidate
1526-
| FnPointerCandidate
1531+
| FnPointerCandidate { .. }
15271532
| BuiltinObjectCandidate
15281533
| BuiltinUnsizeCandidate
15291534
| TraitUpcastingUnsizeCandidate(_)
@@ -1541,7 +1546,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15411546
ImplCandidate(_)
15421547
| ClosureCandidate
15431548
| GeneratorCandidate
1544-
| FnPointerCandidate
1549+
| FnPointerCandidate { .. }
15451550
| BuiltinObjectCandidate
15461551
| BuiltinUnsizeCandidate
15471552
| TraitUpcastingUnsizeCandidate(_)
@@ -1571,7 +1576,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15711576
ImplCandidate(..)
15721577
| ClosureCandidate
15731578
| GeneratorCandidate
1574-
| FnPointerCandidate
1579+
| FnPointerCandidate { .. }
15751580
| BuiltinObjectCandidate
15761581
| BuiltinUnsizeCandidate
15771582
| TraitUpcastingUnsizeCandidate(_)
@@ -1583,7 +1588,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
15831588
ImplCandidate(..)
15841589
| ClosureCandidate
15851590
| GeneratorCandidate
1586-
| FnPointerCandidate
1591+
| FnPointerCandidate { .. }
15871592
| BuiltinObjectCandidate
15881593
| BuiltinUnsizeCandidate
15891594
| TraitUpcastingUnsizeCandidate(_)
@@ -1664,7 +1669,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16641669
ImplCandidate(_)
16651670
| ClosureCandidate
16661671
| GeneratorCandidate
1667-
| FnPointerCandidate
1672+
| FnPointerCandidate { .. }
16681673
| BuiltinObjectCandidate
16691674
| BuiltinUnsizeCandidate
16701675
| TraitUpcastingUnsizeCandidate(_)
@@ -1673,7 +1678,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
16731678
ImplCandidate(_)
16741679
| ClosureCandidate
16751680
| GeneratorCandidate
1676-
| FnPointerCandidate
1681+
| FnPointerCandidate { .. }
16771682
| BuiltinObjectCandidate
16781683
| BuiltinUnsizeCandidate
16791684
| TraitUpcastingUnsizeCandidate(_)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// run-pass
2+
3+
#![feature(const_trait_impl)]
4+
#![feature(const_fn_trait_bound)]
5+
6+
const fn answer_p1<F>(f: &F) -> u8
7+
where
8+
F: ~const FnOnce() -> u8,
9+
F: ~const FnMut() -> u8,
10+
F: ~const Fn() -> u8,
11+
{
12+
f() * 7
13+
}
14+
15+
const fn three() -> u8 {
16+
3
17+
}
18+
19+
const fn answer_p2() -> u8 {
20+
answer_p1(&three)
21+
}
22+
23+
const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
24+
f() + f()
25+
}
26+
27+
const ANSWER: u8 = answer(&answer_p2);
28+
29+
fn main() {
30+
assert_eq!(ANSWER, 42)
31+
}

0 commit comments

Comments
 (0)