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,
|
feature,
|
||||||
rustc_depr,
|
rustc_depr,
|
||||||
promotable,
|
promotable,
|
||||||
|
allow_const_fn_ptr,
|
||||||
const_stability
|
const_stability
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -441,6 +441,7 @@ impl<'a, 'tcx> Index<'tcx> {
|
|||||||
rustc_depr: None,
|
rustc_depr: None,
|
||||||
const_stability: None,
|
const_stability: None,
|
||||||
promotable: false,
|
promotable: false,
|
||||||
|
allow_const_fn_ptr: false,
|
||||||
});
|
});
|
||||||
annotator.parent_stab = Some(stability);
|
annotator.parent_stab = Some(stability);
|
||||||
}
|
}
|
||||||
|
@ -235,6 +235,8 @@ rustc_queries! {
|
|||||||
/// constructor function).
|
/// constructor function).
|
||||||
query is_promotable_const_fn(_: DefId) -> bool {}
|
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 { ... }`).
|
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
|
||||||
query is_foreign_item(_: DefId) -> bool {}
|
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 {
|
*providers = Providers {
|
||||||
is_const_fn_raw,
|
is_const_fn_raw,
|
||||||
is_promotable_const_fn,
|
is_promotable_const_fn,
|
||||||
|
const_fn_is_allowed_fn_ptr,
|
||||||
..*providers
|
..*providers
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -60,13 +60,14 @@ pub fn is_min_const_fn(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for local in &mir.local_decls {
|
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
|
// impl trait is gone in MIR, so check the return type manually
|
||||||
check_ty(
|
check_ty(
|
||||||
tcx,
|
tcx,
|
||||||
tcx.fn_sig(def_id).output().skip_binder(),
|
tcx.fn_sig(def_id).output().skip_binder(),
|
||||||
mir.local_decls.iter().next().unwrap().source_info.span,
|
mir.local_decls.iter().next().unwrap().source_info.span,
|
||||||
|
def_id,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
for bb in mir.basic_blocks() {
|
for bb in mir.basic_blocks() {
|
||||||
@ -82,6 +83,7 @@ fn check_ty(
|
|||||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
ty: ty::Ty<'tcx>,
|
ty: ty::Ty<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
|
fn_def_id: DefId,
|
||||||
) -> McfResult {
|
) -> McfResult {
|
||||||
for ty in ty.walk() {
|
for ty in ty.walk() {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
@ -91,7 +93,9 @@ fn check_ty(
|
|||||||
)),
|
)),
|
||||||
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
|
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
|
||||||
ty::FnPtr(..) => {
|
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, _) => {
|
ty::Dynamic(preds, _) => {
|
||||||
for pred in preds.iter() {
|
for pred in preds.iter() {
|
||||||
|
@ -114,6 +114,8 @@ pub struct Stability {
|
|||||||
pub const_stability: Option<Symbol>,
|
pub const_stability: Option<Symbol>,
|
||||||
/// whether the function has a `#[rustc_promotable]` attribute
|
/// whether the function has a `#[rustc_promotable]` attribute
|
||||||
pub promotable: bool,
|
pub promotable: bool,
|
||||||
|
/// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute
|
||||||
|
pub allow_const_fn_ptr: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The available stability levels.
|
/// 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_depr: Option<RustcDeprecation> = None;
|
||||||
let mut rustc_const_unstable: Option<Symbol> = None;
|
let mut rustc_const_unstable: Option<Symbol> = None;
|
||||||
let mut promotable = false;
|
let mut promotable = false;
|
||||||
|
let mut allow_const_fn_ptr = false;
|
||||||
let diagnostic = &sess.span_diagnostic;
|
let diagnostic = &sess.span_diagnostic;
|
||||||
|
|
||||||
'outer: for attr in attrs_iter {
|
'outer: for attr in attrs_iter {
|
||||||
@ -187,6 +190,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||||||
"unstable",
|
"unstable",
|
||||||
"stable",
|
"stable",
|
||||||
"rustc_promotable",
|
"rustc_promotable",
|
||||||
|
"rustc_allow_const_fn_ptr",
|
||||||
].iter().any(|&s| attr.path == s) {
|
].iter().any(|&s| attr.path == s) {
|
||||||
continue // not a stability level
|
continue // not a stability level
|
||||||
}
|
}
|
||||||
@ -198,6 +202,9 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||||||
if attr.path == "rustc_promotable" {
|
if attr.path == "rustc_promotable" {
|
||||||
promotable = true;
|
promotable = true;
|
||||||
}
|
}
|
||||||
|
if attr.path == "rustc_allow_const_fn_ptr" {
|
||||||
|
allow_const_fn_ptr = true;
|
||||||
|
}
|
||||||
// attributes with data
|
// attributes with data
|
||||||
else if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
|
else if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
|
||||||
let meta = meta.as_ref().unwrap();
|
let meta = meta.as_ref().unwrap();
|
||||||
@ -354,6 +361,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||||||
rustc_depr: None,
|
rustc_depr: None,
|
||||||
const_stability: None,
|
const_stability: None,
|
||||||
promotable: false,
|
promotable: false,
|
||||||
|
allow_const_fn_ptr: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(None, _, _) => {
|
(None, _, _) => {
|
||||||
@ -418,6 +426,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||||||
rustc_depr: None,
|
rustc_depr: None,
|
||||||
const_stability: None,
|
const_stability: None,
|
||||||
promotable: false,
|
promotable: false,
|
||||||
|
allow_const_fn_ptr: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(None, _) => {
|
(None, _) => {
|
||||||
@ -458,13 +467,14 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Merge the const-unstable info into the stability info
|
// Merge the const-unstable info into the stability info
|
||||||
if promotable {
|
if promotable || allow_const_fn_ptr {
|
||||||
if let Some(ref mut stab) = stab {
|
if let Some(ref mut stab) = stab {
|
||||||
stab.promotable = true;
|
stab.promotable = promotable;
|
||||||
|
stab.allow_const_fn_ptr = allow_const_fn_ptr;
|
||||||
} else {
|
} else {
|
||||||
span_err!(diagnostic, item_sp, E0717,
|
span_err!(diagnostic, item_sp, E0717,
|
||||||
"rustc_promotable attribute must be paired with \
|
"rustc_promotable and rustc_allow_const_fn_ptr attributes \
|
||||||
either stable or unstable attribute");
|
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