Coerce const FnDefs to implement const Fn traits
This commit is contained in:
parent
d3f981b144
commit
f8aa73d3dd
7 changed files with 55 additions and 13 deletions
|
@ -655,8 +655,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||||
|
|
||||||
let is_const_fn = match *fn_ty.kind() {
|
let is_const_fn = match *fn_ty.kind() {
|
||||||
ty::FnDef(def_id, _) => {
|
ty::FnDef(def_id, _) => {
|
||||||
self.tcx.is_const_fn_raw(def_id)
|
self.tcx.is_const_fn_raw(def_id) || is_lang_panic_fn(self.tcx, def_id)
|
||||||
|| is_lang_panic_fn(self.tcx, def_id)
|
|
||||||
}
|
}
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
|
|
@ -120,7 +120,9 @@ pub enum SelectionCandidate<'tcx> {
|
||||||
|
|
||||||
/// Implementation of a `Fn`-family trait by one of the anonymous
|
/// Implementation of a `Fn`-family trait by one of the anonymous
|
||||||
/// types generated for a fn pointer type (e.g., `fn(int) -> int`)
|
/// types generated for a fn pointer type (e.g., `fn(int) -> int`)
|
||||||
FnPointerCandidate,
|
FnPointerCandidate {
|
||||||
|
is_const: bool,
|
||||||
|
},
|
||||||
|
|
||||||
/// Builtin implementation of `DiscriminantKind`.
|
/// Builtin implementation of `DiscriminantKind`.
|
||||||
DiscriminantKindCandidate,
|
DiscriminantKindCandidate,
|
||||||
|
|
|
@ -2750,7 +2750,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
Some(stability) if stability.level.is_unstable() => {
|
Some(stability) if stability.level.is_unstable() => {
|
||||||
// has a `rustc_const_unstable` attribute, check whether the user enabled the
|
// has a `rustc_const_unstable` attribute, check whether the user enabled the
|
||||||
// corresponding feature gate.
|
// corresponding feature gate.
|
||||||
self.features().declared_lib_features.iter().any(|&(sym, _)| sym == stability.feature)
|
self.features()
|
||||||
|
.declared_lib_features
|
||||||
|
.iter()
|
||||||
|
.any(|&(sym, _)| sym == stability.feature)
|
||||||
}
|
}
|
||||||
// functions without const stability are either stable user written
|
// functions without const stability are either stable user written
|
||||||
// const fn or the user is using feature gates and we thus don't
|
// const fn or the user is using feature gates and we thus don't
|
||||||
|
|
|
@ -475,7 +475,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
..
|
..
|
||||||
} = self_ty.fn_sig(self.tcx()).skip_binder()
|
} = self_ty.fn_sig(self.tcx()).skip_binder()
|
||||||
{
|
{
|
||||||
candidates.vec.push(FnPointerCandidate);
|
candidates.vec.push(FnPointerCandidate { is_const: false });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
|
// Provide an impl for suitable functions, rejecting `#[target_feature]` functions (RFC 2396).
|
||||||
|
@ -488,7 +488,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
} = self_ty.fn_sig(self.tcx()).skip_binder()
|
} = self_ty.fn_sig(self.tcx()).skip_binder()
|
||||||
{
|
{
|
||||||
if self.tcx().codegen_fn_attrs(def_id).target_features.is_empty() {
|
if self.tcx().codegen_fn_attrs(def_id).target_features.is_empty() {
|
||||||
candidates.vec.push(FnPointerCandidate);
|
candidates
|
||||||
|
.vec
|
||||||
|
.push(FnPointerCandidate { is_const: self.tcx().is_const_fn(def_id) });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -92,7 +92,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
Ok(ImplSource::Generator(vtable_generator))
|
Ok(ImplSource::Generator(vtable_generator))
|
||||||
}
|
}
|
||||||
|
|
||||||
FnPointerCandidate => {
|
FnPointerCandidate { .. } => {
|
||||||
let data = self.confirm_fn_pointer_candidate(obligation)?;
|
let data = self.confirm_fn_pointer_candidate(obligation)?;
|
||||||
Ok(ImplSource::FnPointer(data))
|
Ok(ImplSource::FnPointer(data))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1100,6 +1100,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
// generator, this will raise error in other places
|
// generator, this will raise error in other places
|
||||||
// or ignore error with const_async_blocks feature
|
// or ignore error with const_async_blocks feature
|
||||||
GeneratorCandidate => {}
|
GeneratorCandidate => {}
|
||||||
|
// FnDef where the function is const
|
||||||
|
FnPointerCandidate { is_const: true } => {}
|
||||||
ConstDropCandidate => {}
|
ConstDropCandidate => {}
|
||||||
_ => {
|
_ => {
|
||||||
// reject all other types of candidates
|
// reject all other types of candidates
|
||||||
|
@ -1513,6 +1515,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Drop otherwise equivalent non-const fn pointer candidates
|
||||||
|
(FnPointerCandidate { .. }, FnPointerCandidate { is_const: false }) => true,
|
||||||
|
|
||||||
// Global bounds from the where clause should be ignored
|
// Global bounds from the where clause should be ignored
|
||||||
// here (see issue #50825). Otherwise, we have a where
|
// here (see issue #50825). Otherwise, we have a where
|
||||||
// clause so don't go around looking for impls.
|
// clause so don't go around looking for impls.
|
||||||
|
@ -1523,7 +1528,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
ImplCandidate(..)
|
ImplCandidate(..)
|
||||||
| ClosureCandidate
|
| ClosureCandidate
|
||||||
| GeneratorCandidate
|
| GeneratorCandidate
|
||||||
| FnPointerCandidate
|
| FnPointerCandidate { .. }
|
||||||
| BuiltinObjectCandidate
|
| BuiltinObjectCandidate
|
||||||
| BuiltinUnsizeCandidate
|
| BuiltinUnsizeCandidate
|
||||||
| TraitUpcastingUnsizeCandidate(_)
|
| TraitUpcastingUnsizeCandidate(_)
|
||||||
|
@ -1541,7 +1546,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
ImplCandidate(_)
|
ImplCandidate(_)
|
||||||
| ClosureCandidate
|
| ClosureCandidate
|
||||||
| GeneratorCandidate
|
| GeneratorCandidate
|
||||||
| FnPointerCandidate
|
| FnPointerCandidate { .. }
|
||||||
| BuiltinObjectCandidate
|
| BuiltinObjectCandidate
|
||||||
| BuiltinUnsizeCandidate
|
| BuiltinUnsizeCandidate
|
||||||
| TraitUpcastingUnsizeCandidate(_)
|
| TraitUpcastingUnsizeCandidate(_)
|
||||||
|
@ -1571,7 +1576,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
ImplCandidate(..)
|
ImplCandidate(..)
|
||||||
| ClosureCandidate
|
| ClosureCandidate
|
||||||
| GeneratorCandidate
|
| GeneratorCandidate
|
||||||
| FnPointerCandidate
|
| FnPointerCandidate { .. }
|
||||||
| BuiltinObjectCandidate
|
| BuiltinObjectCandidate
|
||||||
| BuiltinUnsizeCandidate
|
| BuiltinUnsizeCandidate
|
||||||
| TraitUpcastingUnsizeCandidate(_)
|
| TraitUpcastingUnsizeCandidate(_)
|
||||||
|
@ -1583,7 +1588,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
ImplCandidate(..)
|
ImplCandidate(..)
|
||||||
| ClosureCandidate
|
| ClosureCandidate
|
||||||
| GeneratorCandidate
|
| GeneratorCandidate
|
||||||
| FnPointerCandidate
|
| FnPointerCandidate { .. }
|
||||||
| BuiltinObjectCandidate
|
| BuiltinObjectCandidate
|
||||||
| BuiltinUnsizeCandidate
|
| BuiltinUnsizeCandidate
|
||||||
| TraitUpcastingUnsizeCandidate(_)
|
| TraitUpcastingUnsizeCandidate(_)
|
||||||
|
@ -1664,7 +1669,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
ImplCandidate(_)
|
ImplCandidate(_)
|
||||||
| ClosureCandidate
|
| ClosureCandidate
|
||||||
| GeneratorCandidate
|
| GeneratorCandidate
|
||||||
| FnPointerCandidate
|
| FnPointerCandidate { .. }
|
||||||
| BuiltinObjectCandidate
|
| BuiltinObjectCandidate
|
||||||
| BuiltinUnsizeCandidate
|
| BuiltinUnsizeCandidate
|
||||||
| TraitUpcastingUnsizeCandidate(_)
|
| TraitUpcastingUnsizeCandidate(_)
|
||||||
|
@ -1673,7 +1678,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
ImplCandidate(_)
|
ImplCandidate(_)
|
||||||
| ClosureCandidate
|
| ClosureCandidate
|
||||||
| GeneratorCandidate
|
| GeneratorCandidate
|
||||||
| FnPointerCandidate
|
| FnPointerCandidate { .. }
|
||||||
| BuiltinObjectCandidate
|
| BuiltinObjectCandidate
|
||||||
| BuiltinUnsizeCandidate
|
| BuiltinUnsizeCandidate
|
||||||
| TraitUpcastingUnsizeCandidate(_)
|
| TraitUpcastingUnsizeCandidate(_)
|
||||||
|
|
31
src/test/ui/rfc-2632-const-trait-impl/const-closures.rs
Normal file
31
src/test/ui/rfc-2632-const-trait-impl/const-closures.rs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
// run-pass
|
||||||
|
|
||||||
|
#![feature(const_trait_impl)]
|
||||||
|
#![feature(const_fn_trait_bound)]
|
||||||
|
|
||||||
|
const fn answer_p1<F>(f: &F) -> u8
|
||||||
|
where
|
||||||
|
F: ~const FnOnce() -> u8,
|
||||||
|
F: ~const FnMut() -> u8,
|
||||||
|
F: ~const Fn() -> u8,
|
||||||
|
{
|
||||||
|
f() * 7
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn three() -> u8 {
|
||||||
|
3
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn answer_p2() -> u8 {
|
||||||
|
answer_p1(&three)
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
|
||||||
|
f() + f()
|
||||||
|
}
|
||||||
|
|
||||||
|
const ANSWER: u8 = answer(&answer_p2);
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
assert_eq!(ANSWER, 42)
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue