1
Fork 0

Auto merge of #114776 - fee1-dead-contrib:enable-effects-in-libcore, r=oli-obk

Enable effects for libcore

~~r? `@oli-obk~~`

forgot you are on vacation, oops
This commit is contained in:
bors 2023-09-22 07:00:52 +00:00
commit 8759de0a49
19 changed files with 174 additions and 134 deletions

View file

@ -525,8 +525,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
_ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0, _ => self.instantiate_value_path(segs, opt_ty, res, expr.span, expr.hir_id).0,
}; };
if let ty::FnDef(did, ..) = *ty.kind() { if let ty::FnDef(did, callee_args) = *ty.kind() {
let fn_sig = ty.fn_sig(tcx); let fn_sig = ty.fn_sig(tcx);
// HACK: whenever we get a FnDef in a non-const context, enforce effects to get the
// default `host = true` to avoid inference errors later.
if tcx.hir().body_const_context(self.body_id).is_none() {
self.enforce_context_effects(expr.hir_id, qpath.span(), did, callee_args);
}
if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic if tcx.fn_sig(did).skip_binder().abi() == RustIntrinsic
&& tcx.item_name(did) == sym::transmute && tcx.item_name(did) == sym::transmute
{ {

View file

@ -273,11 +273,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// //
// This check is here because there is currently no way to express a trait bound for `FnDef` types only. // This check is here because there is currently no way to express a trait bound for `FnDef` types only.
if is_const_eval_select && (1..=2).contains(&idx) { if is_const_eval_select && (1..=2).contains(&idx) {
if let ty::FnDef(def_id, _) = checked_ty.kind() { if let ty::FnDef(def_id, args) = *checked_ty.kind() {
if idx == 1 && !self.tcx.is_const_fn_raw(*def_id) { if idx == 1 {
self.tcx if !self.tcx.is_const_fn_raw(def_id) {
.sess self.tcx.sess.emit_err(errors::ConstSelectMustBeConst {
.emit_err(errors::ConstSelectMustBeConst { span: provided_arg.span }); span: provided_arg.span,
});
} else {
self.enforce_context_effects(
provided_arg.hir_id,
provided_arg.span,
def_id,
args,
)
}
} }
} else { } else {
self.tcx.sess.emit_err(errors::ConstSelectMustBeFn { self.tcx.sess.emit_err(errors::ConstSelectMustBeFn {

View file

@ -20,7 +20,8 @@ use rustc_hir::lang_items::{extract, GenericRequirement};
use rustc_hir::{LangItem, LanguageItems, Target}; use rustc_hir::{LangItem, LanguageItems, Target};
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::ExternCrate; use rustc_session::cstore::ExternCrate;
use rustc_span::{symbol::kw::Empty, Span}; use rustc_span::symbol::kw::Empty;
use rustc_span::{sym, Span};
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
@ -157,7 +158,14 @@ impl<'tcx> LanguageItemCollector<'tcx> {
self.tcx.hir().get_by_def_id(item_def_id) self.tcx.hir().get_by_def_id(item_def_id)
{ {
let (actual_num, generics_span) = match kind.generics() { let (actual_num, generics_span) = match kind.generics() {
Some(generics) => (generics.params.len(), generics.span), Some(generics) => (
generics
.params
.iter()
.filter(|p| !self.tcx.has_attr(p.def_id, sym::rustc_host))
.count(),
generics.span,
),
None => (0, *item_span), None => (0, *item_span),
}; };

View file

@ -195,6 +195,7 @@
// //
// Language features: // Language features:
// tidy-alphabetical-start // tidy-alphabetical-start
#![cfg_attr(not(bootstrap), feature(effects))]
#![feature(abi_unadjusted)] #![feature(abi_unadjusted)]
#![feature(adt_const_params)] #![feature(adt_const_params)]
#![feature(allow_internal_unsafe)] #![feature(allow_internal_unsafe)]

View file

@ -202,7 +202,7 @@
/// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle /// [nomicon]: ../../nomicon/phantom-data.html#an-exception-the-special-case-of-the-standard-library-and-its-unstable-may_dangle
#[lang = "drop"] #[lang = "drop"]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[const_trait] // FIXME(effects) #[const_trait]
pub trait Drop { pub trait Drop {
/// Executes the destructor for this type. /// Executes the destructor for this type.
/// ///

View file

@ -72,7 +72,7 @@ use crate::marker::Tuple;
)] )]
#[fundamental] // so that regex can rely that `&str: !FnMut` #[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"] #[must_use = "closures are lazy and do nothing unless called"]
#[const_trait] // FIXME(effects) #[const_trait]
pub trait Fn<Args: Tuple>: FnMut<Args> { pub trait Fn<Args: Tuple>: FnMut<Args> {
/// Performs the call operation. /// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")] #[unstable(feature = "fn_traits", issue = "29625")]
@ -159,7 +159,7 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
)] )]
#[fundamental] // so that regex can rely that `&str: !FnMut` #[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"] #[must_use = "closures are lazy and do nothing unless called"]
#[const_trait] // FIXME(effects) #[const_trait]
pub trait FnMut<Args: Tuple>: FnOnce<Args> { pub trait FnMut<Args: Tuple>: FnOnce<Args> {
/// Performs the call operation. /// Performs the call operation.
#[unstable(feature = "fn_traits", issue = "29625")] #[unstable(feature = "fn_traits", issue = "29625")]
@ -238,7 +238,7 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
)] )]
#[fundamental] // so that regex can rely that `&str: !FnMut` #[fundamental] // so that regex can rely that `&str: !FnMut`
#[must_use = "closures are lazy and do nothing unless called"] #[must_use = "closures are lazy and do nothing unless called"]
#[const_trait] // FIXME(effects) #[const_trait]
pub trait FnOnce<Args: Tuple> { pub trait FnOnce<Args: Tuple> {
/// The returned type after the call operator is used. /// The returned type after the call operator is used.
#[lang = "fn_once_output"] #[lang = "fn_once_output"]

View file

@ -793,6 +793,7 @@ fn clean_ty_generics<'tcx>(
} }
Some(clean_generic_param_def(param, cx)) Some(clean_generic_param_def(param, cx))
} }
ty::GenericParamDefKind::Const { is_host_effect: true, .. } => None,
ty::GenericParamDefKind::Const { .. } => Some(clean_generic_param_def(param, cx)), ty::GenericParamDefKind::Const { .. } => Some(clean_generic_param_def(param, cx)),
}) })
.collect::<ThinVec<GenericParamDef>>(); .collect::<ThinVec<GenericParamDef>>();

View file

@ -207,7 +207,8 @@ fn path_segment_certainty(
// Checking `res_generics_def_id(..)` before calling `generics_of` avoids an ICE. // Checking `res_generics_def_id(..)` before calling `generics_of` avoids an ICE.
if cx.tcx.res_generics_def_id(path_segment.res).is_some() { if cx.tcx.res_generics_def_id(path_segment.res).is_some() {
let generics = cx.tcx.generics_of(def_id); let generics = cx.tcx.generics_of(def_id);
let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && generics.params.is_empty() let count = generics.params.len() - generics.host_effect_index.is_some() as usize;
let lhs = if (parent_certainty.is_certain() || generics.parent_count == 0) && count == 0
{ {
Certainty::Certain(None) Certainty::Certain(None)
} else { } else {
@ -299,7 +300,7 @@ fn type_is_inferrable_from_arguments(cx: &LateContext<'_>, expr: &Expr<'_>) -> b
// Check that all type parameters appear in the functions input types. // Check that all type parameters appear in the functions input types.
(0..(generics.parent_count + generics.params.len()) as u32).all(|index| { (0..(generics.parent_count + generics.params.len()) as u32).all(|index| {
fn_sig Some(index as usize) == generics.host_effect_index || fn_sig
.inputs() .inputs()
.iter() .iter()
.any(|input_ty| contains_param(*input_ty.skip_binder(), index)) .any(|input_ty| contains_param(*input_ty.skip_binder(), index))

View file

@ -5,6 +5,8 @@
// To future blessers: make sure that `const_trait_impl` is // To future blessers: make sure that `const_trait_impl` is
// stabilized when changing `@!has` to `@has`, and please do // stabilized when changing `@!has` to `@has`, and please do
// not remove this test. // not remove this test.
//
// FIXME(effects) add `const_trait` to `Fn` so we use `~const`
#![feature(const_trait_impl)] #![feature(const_trait_impl)]
#![crate_name = "foo"] #![crate_name = "foo"]
@ -22,9 +24,9 @@ pub trait Tr<T> {
// @has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' // @has - '//section[@id="method.a"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn'
// @!has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const' // @!has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where"]' '~const'
// @has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn' // @has - '//section[@id="method.a"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn'
fn a<A: ~const Fn() + ~const Destruct>() fn a<A: /* ~const */ Fn() + ~const Destruct>()
where where
Option<A>: ~const Fn() + ~const Destruct, Option<A>: /* ~const */ Fn() + ~const Destruct,
{ {
} }
} }
@ -34,13 +36,13 @@ pub trait Tr<T> {
// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/a[@class="trait"]' 'Fn' // @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/a[@class="trait"]' 'Fn'
// @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where"]' '~const' // @!has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where"]' '~const'
// @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn' // @has - '//section[@id="impl-Tr%3CT%3E-for-T"]/h3[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn'
impl<T: ~const Fn() + ~const Destruct> const Tr<T> for T impl<T: /* ~const */ Fn() + ~const Destruct> const Tr<T> for T
where where
Option<T>: ~const Fn() + ~const Destruct, Option<T>: /* ~const */ Fn() + ~const Destruct,
{ {
fn a<A: ~const Fn() + ~const Destruct>() fn a<A: /* ~const */ Fn() + ~const Destruct>()
where where
Option<A>: ~const Fn() + ~const Destruct, Option<A>: /* ~const */ Fn() + ~const Destruct,
{ {
} }
} }
@ -49,9 +51,9 @@ where
// @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn' // @has - '//pre[@class="rust item-decl"]/code/a[@class="trait"]' 'Fn'
// @!has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' '~const' // @!has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' '~const'
// @has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' ': Fn' // @has - '//pre[@class="rust item-decl"]/code/span[@class="where fmt-newline"]' ': Fn'
pub const fn foo<F: ~const Fn() + ~const Destruct>() pub const fn foo<F: /* ~const */ Fn() + ~const Destruct>()
where where
Option<F>: ~const Fn() + ~const Destruct, Option<F>: /* ~const */ Fn() + ~const Destruct,
{ {
F::a() F::a()
} }
@ -61,9 +63,9 @@ impl<T> S<T> {
// @has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn' // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/a[@class="trait"]' 'Fn'
// @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const' // @!has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where"]' '~const'
// @has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn' // @has - '//section[@id="method.foo"]/h4[@class="code-header"]/span[@class="where fmt-newline"]' ': Fn'
pub const fn foo<B, C: ~const Fn() + ~const Destruct>() pub const fn foo<B, C: /* ~const */ Fn() + ~const Destruct>()
where where
B: ~const Fn() + ~const Destruct, B: /* ~const */ Fn() + ~const Destruct,
{ {
B::a() B::a()
} }

View file

@ -10,6 +10,66 @@ error[E0635]: unknown feature `const_cmp`
LL | #![feature(const_cmp)] LL | #![feature(const_cmp)]
| ^^^^^^^^^ | ^^^^^^^^^
error: aborting due to 2 previous errors error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:15:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:15:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:22:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:22:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:29:15
|
LL | T: ~const FnOnce<()>,
| ^^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:29:15
|
LL | T: ~const FnOnce<()>,
| ^^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:36:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:36:15
|
LL | T: ~const Fn<()> + ~const Destruct,
| ^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:50:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/fn_trait_refs.rs:50:15
|
LL | T: ~const FnMut<()> + ~const Destruct,
| ^^^^^^^^^
error: aborting due to 12 previous errors
For more information about this error, try `rustc --explain E0635`. For more information about this error, try `rustc --explain E0635`.

View file

@ -1,3 +1,5 @@
// known-bug: #110395
// FIXME check-pass
// This is a non-regression test for const-qualification of unstable items in libcore // This is a non-regression test for const-qualification of unstable items in libcore
// as explained in issue #67053. // as explained in issue #67053.
// const-qualification could miss some `const fn`s if they were unstable and the feature // const-qualification could miss some `const fn`s if they were unstable and the feature
@ -15,12 +17,12 @@ impl<T> Opt<T> {
#[rustc_const_unstable(feature = "foo", issue = "none")] #[rustc_const_unstable(feature = "foo", issue = "none")]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T { const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
//~^ ERROR destructor of //FIXME ~^ ERROR destructor of
//~| ERROR destructor of //FIXME ~| ERROR destructor of
match self { match self {
Opt::Some(t) => t, Opt::Some(t) => t,
Opt::None => f(), Opt::None => f(),
//~^ ERROR cannot call //FIXME ~^ ERROR cannot call
} }
} }
} }

View file

@ -1,34 +1,8 @@
error[E0015]: cannot call non-const closure in constant functions error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/unstable-const-fn-in-libcore.rs:22:26 --> $DIR/unstable-const-fn-in-libcore.rs:19:39
|
LL | Opt::None => f(),
| ^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T + ~const std::ops::FnOnce<()>>(self, f: F) -> T {
| +++++++++++++++++++++++++++++
error[E0493]: destructor of `F` cannot be evaluated at compile-time
--> $DIR/unstable-const-fn-in-libcore.rs:17:60
| |
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T { LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
| ^ the destructor for this type cannot be evaluated in constant functions | ^^^^^^^^^^^^^
...
LL | }
| - value is dropped here
error[E0493]: destructor of `Opt<T>` cannot be evaluated at compile-time error: aborting due to previous error
--> $DIR/unstable-const-fn-in-libcore.rs:17:54
|
LL | const fn unwrap_or_else<F: ~const FnOnce() -> T>(self, f: F) -> T {
| ^^^^ the destructor for this type cannot be evaluated in constant functions
...
LL | }
| - value is dropped here
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View file

@ -1,25 +1,8 @@
error[E0015]: cannot call non-const closure in constant functions error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/normalize-tait-in-const.rs:26:5 --> $DIR/normalize-tait-in-const.rs:25:42
|
LL | fun(filter_positive());
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct + ~const std::ops::Fn<(&Alias<'_>,)>>(fun: F) {
| ++++++++++++++++++++++++++++++++++++
error[E0493]: destructor of `F` cannot be evaluated at compile-time
--> $DIR/normalize-tait-in-const.rs:25:79
| |
LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) { LL | const fn with_positive<F: ~const for<'a> Fn(&'a Alias<'a>) + ~const Destruct>(fun: F) {
| ^^^ the destructor for this type cannot be evaluated in constant functions | ^^^^^^^^^^^^^^^^^
LL | fun(filter_positive());
LL | }
| - value is dropped here
error: aborting due to 2 previous errors error: aborting due to previous error
Some errors have detailed explanations: E0015, E0493.
For more information about an error, try `rustc --explain E0015`.

View file

@ -1,4 +1,5 @@
// check-pass // known-bug: #110395
// FIXME check-pass
#![feature(const_trait_impl, const_closures)] #![feature(const_trait_impl, const_closures)]
#![allow(incomplete_features)] #![allow(incomplete_features)]

View file

@ -0,0 +1,8 @@
error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-closure-parse-not-item.rs:7:32
|
LL | const fn test() -> impl ~const Fn() {
| ^^^^
error: aborting due to previous error

View file

@ -1,15 +1,8 @@
error[E0015]: cannot call non-const closure in constant functions error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-closure-trait-method-fail.rs:15:5 --> $DIR/const-closure-trait-method-fail.rs:14:39
| |
LL | x(()) LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
| ^^^^^ | ^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 {
| ++++++++++++++++++++++++++++++++
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View file

@ -1,15 +1,8 @@
error[E0015]: cannot call non-const closure in constant functions error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-closure-trait-method.rs:15:5 --> $DIR/const-closure-trait-method.rs:14:39
| |
LL | x(()) LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32>(x: T) -> i32 {
| ^^^^^ | ^^^^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn need_const_closure<T: ~const FnOnce(()) -> i32 + ~const std::ops::FnOnce<((),)>>(x: T) -> i32 {
| ++++++++++++++++++++++++++++++++
error: aborting due to previous error error: aborting due to previous error
For more information about this error, try `rustc --explain E0015`.

View file

@ -1,39 +1,26 @@
error[E0015]: cannot call non-const closure in constant functions error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-closures.rs:12:5 --> $DIR/const-closures.rs:8:19
| |
LL | f() * 7 LL | F: ~const FnOnce() -> u8,
| ^^^ | ^^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | F: ~const FnOnce() -> u8 + ~const std::ops::Fn<()>,
| +++++++++++++++++++++++++
error[E0015]: cannot call non-const closure in constant functions error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-closures.rs:24:5 --> $DIR/const-closures.rs:9:19
| |
LL | f() + f() LL | F: ~const FnMut() -> u8,
| ^^^ | ^^^^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn answer<F: ~const Fn() -> u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 {
| +++++++++++++++++++++++++
error[E0015]: cannot call non-const closure in constant functions error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-closures.rs:24:11 --> $DIR/const-closures.rs:10:19
| |
LL | f() + f() LL | F: ~const Fn() -> u8,
| ^^^ | ^^^^^^^^^^
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
help: consider further restricting this bound
|
LL | const fn answer<F: ~const Fn() -> u8 + ~const std::ops::Fn<()>>(f: &F) -> u8 {
| +++++++++++++++++++++++++
error: aborting due to 3 previous errors error: ~const can only be applied to `#[const_trait]` traits
--> $DIR/const-closures.rs:23:27
|
LL | const fn answer<F: ~const Fn() -> u8>(f: &F) -> u8 {
| ^^^^^^^^^^
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0015`.

View file

@ -0,0 +1,11 @@
// check-pass
#![feature(const_trait_impl, effects)]
const fn a() {}
fn foo<F: FnOnce()>(a: F) {}
fn main() {
let _ = a;
foo(a);
}