Add rustc_allow_const_fn_ptr
This commit is contained in:
parent
e938c2b9aa
commit
e617025e96
@ -121,6 +121,7 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability {
|
||||
feature,
|
||||
rustc_depr,
|
||||
promotable,
|
||||
allow_const_fn_ptr,
|
||||
const_stability
|
||||
});
|
||||
|
||||
|
@ -441,6 +441,7 @@ impl<'a, 'tcx> Index<'tcx> {
|
||||
rustc_depr: None,
|
||||
const_stability: None,
|
||||
promotable: false,
|
||||
allow_const_fn_ptr: false,
|
||||
});
|
||||
annotator.parent_stab = Some(stability);
|
||||
}
|
||||
|
@ -235,6 +235,8 @@ rustc_queries! {
|
||||
/// constructor function).
|
||||
query is_promotable_const_fn(_: DefId) -> bool {}
|
||||
|
||||
query const_fn_is_allowed_fn_ptr(_: DefId) -> bool {}
|
||||
|
||||
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
|
||||
query is_foreign_item(_: DefId) -> bool {}
|
||||
|
||||
|
@ -95,9 +95,16 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
|
||||
}
|
||||
}
|
||||
|
||||
fn const_fn_is_allowed_fn_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
|
||||
tcx.is_const_fn(def_id) &&
|
||||
tcx.lookup_stability(def_id)
|
||||
.map(|stab| stab.allow_const_fn_ptr).unwrap_or(false)
|
||||
}
|
||||
|
||||
*providers = Providers {
|
||||
is_const_fn_raw,
|
||||
is_promotable_const_fn,
|
||||
const_fn_is_allowed_fn_ptr,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
@ -60,13 +60,14 @@ pub fn is_min_const_fn(
|
||||
}
|
||||
|
||||
for local in &mir.local_decls {
|
||||
check_ty(tcx, local.ty, local.source_info.span)?;
|
||||
check_ty(tcx, local.ty, local.source_info.span, def_id)?;
|
||||
}
|
||||
// impl trait is gone in MIR, so check the return type manually
|
||||
check_ty(
|
||||
tcx,
|
||||
tcx.fn_sig(def_id).output().skip_binder(),
|
||||
mir.local_decls.iter().next().unwrap().source_info.span,
|
||||
def_id,
|
||||
)?;
|
||||
|
||||
for bb in mir.basic_blocks() {
|
||||
@ -82,6 +83,7 @@ fn check_ty(
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
ty: ty::Ty<'tcx>,
|
||||
span: Span,
|
||||
fn_def_id: DefId,
|
||||
) -> McfResult {
|
||||
for ty in ty.walk() {
|
||||
match ty.sty {
|
||||
@ -91,7 +93,9 @@ fn check_ty(
|
||||
)),
|
||||
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
|
||||
ty::FnPtr(..) => {
|
||||
return Err((span, "function pointers in const fn are unstable".into()))
|
||||
if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
|
||||
return Err((span, "function pointers in const fn are unstable".into()))
|
||||
}
|
||||
}
|
||||
ty::Dynamic(preds, _) => {
|
||||
for pred in preds.iter() {
|
||||
|
@ -114,6 +114,8 @@ pub struct Stability {
|
||||
pub const_stability: Option<Symbol>,
|
||||
/// whether the function has a `#[rustc_promotable]` attribute
|
||||
pub promotable: bool,
|
||||
/// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute
|
||||
pub allow_const_fn_ptr: bool,
|
||||
}
|
||||
|
||||
/// The available stability levels.
|
||||
@ -178,6 +180,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||
let mut rustc_depr: Option<RustcDeprecation> = None;
|
||||
let mut rustc_const_unstable: Option<Symbol> = None;
|
||||
let mut promotable = false;
|
||||
let mut allow_const_fn_ptr = false;
|
||||
let diagnostic = &sess.span_diagnostic;
|
||||
|
||||
'outer: for attr in attrs_iter {
|
||||
@ -187,6 +190,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||
"unstable",
|
||||
"stable",
|
||||
"rustc_promotable",
|
||||
"rustc_allow_const_fn_ptr",
|
||||
].iter().any(|&s| attr.path == s) {
|
||||
continue // not a stability level
|
||||
}
|
||||
@ -198,6 +202,9 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||
if attr.path == "rustc_promotable" {
|
||||
promotable = true;
|
||||
}
|
||||
if attr.path == "rustc_allow_const_fn_ptr" {
|
||||
allow_const_fn_ptr = true;
|
||||
}
|
||||
// attributes with data
|
||||
else if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
|
||||
let meta = meta.as_ref().unwrap();
|
||||
@ -354,6 +361,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||
rustc_depr: None,
|
||||
const_stability: None,
|
||||
promotable: false,
|
||||
allow_const_fn_ptr: false,
|
||||
})
|
||||
}
|
||||
(None, _, _) => {
|
||||
@ -418,6 +426,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||
rustc_depr: None,
|
||||
const_stability: None,
|
||||
promotable: false,
|
||||
allow_const_fn_ptr: false,
|
||||
})
|
||||
}
|
||||
(None, _) => {
|
||||
@ -458,13 +467,14 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
||||
}
|
||||
|
||||
// Merge the const-unstable info into the stability info
|
||||
if promotable {
|
||||
if promotable || allow_const_fn_ptr {
|
||||
if let Some(ref mut stab) = stab {
|
||||
stab.promotable = true;
|
||||
stab.promotable = promotable;
|
||||
stab.allow_const_fn_ptr = allow_const_fn_ptr;
|
||||
} else {
|
||||
span_err!(diagnostic, item_sp, E0717,
|
||||
"rustc_promotable attribute must be paired with \
|
||||
either stable or unstable attribute");
|
||||
"rustc_promotable and rustc_allow_const_fn_ptr attributes \
|
||||
must be paired with either stable or unstable attribute");
|
||||
}
|
||||
}
|
||||
|
||||
|
10
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs
Normal file
10
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.rs
Normal file
@ -0,0 +1,10 @@
|
||||
#![feature(rustc_attrs, staged_api)]
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
const fn error(_: fn()) {} //~ ERROR function pointers in const fn are unstable
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_allow_const_fn_ptr]
|
||||
const fn compiles(_: fn()) {}
|
||||
|
||||
fn main() {}
|
11
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
Normal file
11
src/test/ui/consts/min_const_fn/allow_const_fn_ptr.stderr
Normal file
@ -0,0 +1,11 @@
|
||||
error[E0723]: function pointers in const fn are unstable (see issue #57563)
|
||||
--> $DIR/allow_const_fn_ptr.rs:4:16
|
||||
|
|
||||
LL | const fn error(_: fn()) {}
|
||||
| ^
|
||||
|
|
||||
= help: add #![feature(const_fn)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0723`.
|
@ -0,0 +1,11 @@
|
||||
#![feature(staged_api)]
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
const fn error(_: fn()) {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_allow_const_fn_ptr]
|
||||
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
|
||||
const fn compiles(_: fn()) {}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,12 @@
|
||||
error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
|
||||
--> $DIR/allow_const_fn_ptr_feature_gate.rs:7:3
|
||||
|
|
||||
LL | #[rustc_allow_const_fn_ptr]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
|
||||
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -0,0 +1,18 @@
|
||||
// run-pass
|
||||
|
||||
#![feature(rustc_attrs, staged_api)]
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_allow_const_fn_ptr]
|
||||
const fn takes_fn_ptr(_: fn()) {}
|
||||
|
||||
const FN: fn() = || ();
|
||||
|
||||
const fn gives_fn_ptr() {
|
||||
takes_fn_ptr(FN)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
gives_fn_ptr();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user