Skip to content

Commit e617025

Browse files
committed
Add rustc_allow_const_fn_ptr
1 parent e938c2b commit e617025

11 files changed

+93
-6
lines changed

Diff for: src/librustc/ich/impls_syntax.rs

+1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ impl_stable_hash_for!(struct ::syntax::attr::Stability {
121121
feature,
122122
rustc_depr,
123123
promotable,
124+
allow_const_fn_ptr,
124125
const_stability
125126
});
126127

Diff for: src/librustc/middle/stability.rs

+1
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,7 @@ impl<'a, 'tcx> Index<'tcx> {
441441
rustc_depr: None,
442442
const_stability: None,
443443
promotable: false,
444+
allow_const_fn_ptr: false,
444445
});
445446
annotator.parent_stab = Some(stability);
446447
}

Diff for: src/librustc/query/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ rustc_queries! {
235235
/// constructor function).
236236
query is_promotable_const_fn(_: DefId) -> bool {}
237237

238+
query const_fn_is_allowed_fn_ptr(_: DefId) -> bool {}
239+
238240
/// True if this is a foreign item (i.e., linked via `extern { ... }`).
239241
query is_foreign_item(_: DefId) -> bool {}
240242

Diff for: src/librustc/ty/constness.rs

+7
Original file line numberDiff line numberDiff line change
@@ -95,9 +95,16 @@ pub fn provide<'tcx>(providers: &mut Providers<'tcx>) {
9595
}
9696
}
9797

98+
fn const_fn_is_allowed_fn_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> bool {
99+
tcx.is_const_fn(def_id) &&
100+
tcx.lookup_stability(def_id)
101+
.map(|stab| stab.allow_const_fn_ptr).unwrap_or(false)
102+
}
103+
98104
*providers = Providers {
99105
is_const_fn_raw,
100106
is_promotable_const_fn,
107+
const_fn_is_allowed_fn_ptr,
101108
..*providers
102109
};
103110
}

Diff for: src/librustc_mir/transform/qualify_min_const_fn.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,14 @@ pub fn is_min_const_fn(
6060
}
6161

6262
for local in &mir.local_decls {
63-
check_ty(tcx, local.ty, local.source_info.span)?;
63+
check_ty(tcx, local.ty, local.source_info.span, def_id)?;
6464
}
6565
// impl trait is gone in MIR, so check the return type manually
6666
check_ty(
6767
tcx,
6868
tcx.fn_sig(def_id).output().skip_binder(),
6969
mir.local_decls.iter().next().unwrap().source_info.span,
70+
def_id,
7071
)?;
7172

7273
for bb in mir.basic_blocks() {
@@ -82,6 +83,7 @@ fn check_ty(
8283
tcx: TyCtxt<'a, 'tcx, 'tcx>,
8384
ty: ty::Ty<'tcx>,
8485
span: Span,
86+
fn_def_id: DefId,
8587
) -> McfResult {
8688
for ty in ty.walk() {
8789
match ty.sty {
@@ -91,7 +93,9 @@ fn check_ty(
9193
)),
9294
ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
9395
ty::FnPtr(..) => {
94-
return Err((span, "function pointers in const fn are unstable".into()))
96+
if !tcx.const_fn_is_allowed_fn_ptr(fn_def_id) {
97+
return Err((span, "function pointers in const fn are unstable".into()))
98+
}
9599
}
96100
ty::Dynamic(preds, _) => {
97101
for pred in preds.iter() {

Diff for: src/libsyntax/attr/builtin.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ pub struct Stability {
114114
pub const_stability: Option<Symbol>,
115115
/// whether the function has a `#[rustc_promotable]` attribute
116116
pub promotable: bool,
117+
/// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute
118+
pub allow_const_fn_ptr: bool,
117119
}
118120

119121
/// The available stability levels.
@@ -178,6 +180,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
178180
let mut rustc_depr: Option<RustcDeprecation> = None;
179181
let mut rustc_const_unstable: Option<Symbol> = None;
180182
let mut promotable = false;
183+
let mut allow_const_fn_ptr = false;
181184
let diagnostic = &sess.span_diagnostic;
182185

183186
'outer: for attr in attrs_iter {
@@ -187,6 +190,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
187190
"unstable",
188191
"stable",
189192
"rustc_promotable",
193+
"rustc_allow_const_fn_ptr",
190194
].iter().any(|&s| attr.path == s) {
191195
continue // not a stability level
192196
}
@@ -198,6 +202,9 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
198202
if attr.path == "rustc_promotable" {
199203
promotable = true;
200204
}
205+
if attr.path == "rustc_allow_const_fn_ptr" {
206+
allow_const_fn_ptr = true;
207+
}
201208
// attributes with data
202209
else if let Some(MetaItem { node: MetaItemKind::List(ref metas), .. }) = meta {
203210
let meta = meta.as_ref().unwrap();
@@ -354,6 +361,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
354361
rustc_depr: None,
355362
const_stability: None,
356363
promotable: false,
364+
allow_const_fn_ptr: false,
357365
})
358366
}
359367
(None, _, _) => {
@@ -418,6 +426,7 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
418426
rustc_depr: None,
419427
const_stability: None,
420428
promotable: false,
429+
allow_const_fn_ptr: false,
421430
})
422431
}
423432
(None, _) => {
@@ -458,13 +467,14 @@ fn find_stability_generic<'a, I>(sess: &ParseSess,
458467
}
459468

460469
// Merge the const-unstable info into the stability info
461-
if promotable {
470+
if promotable || allow_const_fn_ptr {
462471
if let Some(ref mut stab) = stab {
463-
stab.promotable = true;
472+
stab.promotable = promotable;
473+
stab.allow_const_fn_ptr = allow_const_fn_ptr;
464474
} else {
465475
span_err!(diagnostic, item_sp, E0717,
466-
"rustc_promotable attribute must be paired with \
467-
either stable or unstable attribute");
476+
"rustc_promotable and rustc_allow_const_fn_ptr attributes \
477+
must be paired with either stable or unstable attribute");
468478
}
469479
}
470480

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![feature(rustc_attrs, staged_api)]
2+
3+
#[stable(feature = "rust1", since = "1.0.0")]
4+
const fn error(_: fn()) {} //~ ERROR function pointers in const fn are unstable
5+
6+
#[stable(feature = "rust1", since = "1.0.0")]
7+
#[rustc_allow_const_fn_ptr]
8+
const fn compiles(_: fn()) {}
9+
10+
fn main() {}
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
error[E0723]: function pointers in const fn are unstable (see issue #57563)
2+
--> $DIR/allow_const_fn_ptr.rs:4:16
3+
|
4+
LL | const fn error(_: fn()) {}
5+
| ^
6+
|
7+
= help: add #![feature(const_fn)] to the crate attributes to enable
8+
9+
error: aborting due to previous error
10+
11+
For more information about this error, try `rustc --explain E0723`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(staged_api)]
2+
3+
#[stable(feature = "rust1", since = "1.0.0")]
4+
const fn error(_: fn()) {}
5+
6+
#[stable(feature = "rust1", since = "1.0.0")]
7+
#[rustc_allow_const_fn_ptr]
8+
//~^ ERROR unless otherwise specified, attributes with the prefix `rustc_` are reserved
9+
const fn compiles(_: fn()) {}
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0658]: unless otherwise specified, attributes with the prefix `rustc_` are reserved for internal compiler diagnostics
2+
--> $DIR/allow_const_fn_ptr_feature_gate.rs:7:3
3+
|
4+
LL | #[rustc_allow_const_fn_ptr]
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: for more information, see https://github.com/rust-lang/rust/issues/29642
8+
= help: add #![feature(rustc_attrs)] to the crate attributes to enable
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// run-pass
2+
3+
#![feature(rustc_attrs, staged_api)]
4+
#![stable(feature = "rust1", since = "1.0.0")]
5+
6+
#[stable(feature = "rust1", since = "1.0.0")]
7+
#[rustc_allow_const_fn_ptr]
8+
const fn takes_fn_ptr(_: fn()) {}
9+
10+
const FN: fn() = || ();
11+
12+
const fn gives_fn_ptr() {
13+
takes_fn_ptr(FN)
14+
}
15+
16+
fn main() {
17+
gives_fn_ptr();
18+
}

0 commit comments

Comments
 (0)