Skip to content

Commit d85718a

Browse files
Rollup merge of #86838 - lambinoo:I-69630-rust_const_unstable_check_const, r=oli-obk
Checking that function is const if marked with rustc_const_unstable Fixes #69630 This one is still missing tests to check the behavior but I checked by hand and it seemed to work. I would not mind some direction for writing those unit tests!
2 parents ff4bf73 + 07f903e commit d85718a

File tree

7 files changed

+220
-7
lines changed

7 files changed

+220
-7
lines changed

compiler/rustc_error_codes/src/error_codes/E0542.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Erroneous code example:
1010
fn _stable_fn() {}
1111
1212
#[rustc_const_stable(feature = "_stable_const_fn")] // invalid
13-
fn _stable_const_fn() {}
13+
const fn _stable_const_fn() {}
1414
1515
#[stable(feature = "_deprecated_fn", since = "0.1.0")]
1616
#[rustc_deprecated(
@@ -29,7 +29,7 @@ To fix this issue, you need to provide the `since` field. Example:
2929
fn _stable_fn() {}
3030
3131
#[rustc_const_stable(feature = "_stable_const_fn", since = "1.0.0")] // ok!
32-
fn _stable_const_fn() {}
32+
const fn _stable_const_fn() {}
3333
3434
#[stable(feature = "_deprecated_fn", since = "0.1.0")]
3535
#[rustc_deprecated(

compiler/rustc_error_codes/src/error_codes/E0545.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Erroneous code example:
1010
fn _unstable_fn() {}
1111
1212
#[rustc_const_unstable(feature = "_unstable_const_fn", issue = "0")] // invalid
13-
fn _unstable_const_fn() {}
13+
const fn _unstable_const_fn() {}
1414
```
1515

1616
To fix this issue, you need to provide a correct value in the `issue` field.
@@ -24,7 +24,7 @@ Example:
2424
fn _unstable_fn() {}
2525
2626
#[rustc_const_unstable(feature = "_unstable_const_fn", issue = "1")] // ok!
27-
fn _unstable_const_fn() {}
27+
const fn _unstable_const_fn() {}
2828
```
2929

3030
See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix

compiler/rustc_error_codes/src/error_codes/E0547.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Erroneous code example:
1010
fn _unstable_fn() {}
1111
1212
#[rustc_const_unstable(feature = "_unstable_const_fn")] // invalid
13-
fn _unstable_const_fn() {}
13+
const fn _unstable_const_fn() {}
1414
```
1515

1616
To fix this issue, you need to provide the `issue` field. Example:
@@ -26,7 +26,7 @@ fn _unstable_fn() {}
2626
feature = "_unstable_const_fn",
2727
issue = "none"
2828
)] // ok!
29-
fn _unstable_const_fn() {}
29+
const fn _unstable_const_fn() {}
3030
```
3131

3232
See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix

compiler/rustc_passes/src/stability.rs

+60-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use rustc_session::parse::feature_err;
2020
use rustc_session::Session;
2121
use rustc_span::symbol::{sym, Symbol};
2222
use rustc_span::{Span, DUMMY_SP};
23+
use rustc_target::spec::abi::Abi;
2324

2425
use std::cmp::Ordering;
2526
use std::iter;
@@ -95,10 +96,12 @@ struct Annotator<'a, 'tcx> {
9596
impl<'a, 'tcx> Annotator<'a, 'tcx> {
9697
// Determine the stability for a node based on its attributes and inherited
9798
// stability. The stability is recorded in the index and used as the parent.
99+
// If the node is a function, `fn_sig` is its signature
98100
fn annotate<F>(
99101
&mut self,
100102
hir_id: HirId,
101103
item_sp: Span,
104+
fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
102105
kind: AnnotationKind,
103106
inherit_deprecation: InheritDeprecation,
104107
inherit_const_stability: InheritConstStability,
@@ -163,13 +166,30 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
163166
}
164167

165168
let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);
169+
let mut const_span = None;
166170

167-
let const_stab = const_stab.map(|(const_stab, _)| {
171+
let const_stab = const_stab.map(|(const_stab, const_span_node)| {
168172
let const_stab = self.tcx.intern_const_stability(const_stab);
169173
self.index.const_stab_map.insert(hir_id, const_stab);
174+
const_span = Some(const_span_node);
170175
const_stab
171176
});
172177

178+
// If the current node is a function, has const stability attributes and if it doesn not have an intrinsic ABI,
179+
// check if the function/method is const or the parent impl block is const
180+
if let (Some(const_span), Some(fn_sig)) = (const_span, fn_sig) {
181+
if fn_sig.header.abi != Abi::RustIntrinsic
182+
&& fn_sig.header.abi != Abi::PlatformIntrinsic
183+
&& !fn_sig.header.is_const()
184+
{
185+
if !self.in_trait_impl
186+
|| (self.in_trait_impl && !self.tcx.is_const_fn_raw(hir_id.owner.to_def_id()))
187+
{
188+
missing_const_err(&self.tcx.sess, fn_sig.span, const_span);
189+
}
190+
}
191+
}
192+
173193
// `impl const Trait for Type` items forward their const stability to their
174194
// immediate children.
175195
if const_stab.is_none() {
@@ -367,6 +387,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
367387
let orig_in_trait_impl = self.in_trait_impl;
368388
let mut kind = AnnotationKind::Required;
369389
let mut const_stab_inherit = InheritConstStability::No;
390+
let mut fn_sig = None;
391+
370392
match i.kind {
371393
// Inherent impls and foreign modules serve only as containers for other items,
372394
// they don't have their own stability. They still can be annotated as unstable
@@ -387,6 +409,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
387409
self.annotate(
388410
ctor_hir_id,
389411
i.span,
412+
None,
390413
AnnotationKind::Required,
391414
InheritDeprecation::Yes,
392415
InheritConstStability::No,
@@ -395,12 +418,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
395418
)
396419
}
397420
}
421+
hir::ItemKind::Fn(ref item_fn_sig, _, _) => {
422+
fn_sig = Some(item_fn_sig);
423+
}
398424
_ => {}
399425
}
400426

401427
self.annotate(
402428
i.hir_id(),
403429
i.span,
430+
fn_sig,
404431
kind,
405432
InheritDeprecation::Yes,
406433
const_stab_inherit,
@@ -411,9 +438,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
411438
}
412439

413440
fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
441+
let fn_sig = match ti.kind {
442+
hir::TraitItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
443+
_ => None,
444+
};
445+
414446
self.annotate(
415447
ti.hir_id(),
416448
ti.span,
449+
fn_sig,
417450
AnnotationKind::Required,
418451
InheritDeprecation::Yes,
419452
InheritConstStability::No,
@@ -427,9 +460,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
427460
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
428461
let kind =
429462
if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };
463+
464+
let fn_sig = match ii.kind {
465+
hir::ImplItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
466+
_ => None,
467+
};
468+
430469
self.annotate(
431470
ii.hir_id(),
432471
ii.span,
472+
fn_sig,
433473
kind,
434474
InheritDeprecation::Yes,
435475
InheritConstStability::No,
@@ -444,6 +484,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
444484
self.annotate(
445485
var.id,
446486
var.span,
487+
None,
447488
AnnotationKind::Required,
448489
InheritDeprecation::Yes,
449490
InheritConstStability::No,
@@ -453,6 +494,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
453494
v.annotate(
454495
ctor_hir_id,
455496
var.span,
497+
None,
456498
AnnotationKind::Required,
457499
InheritDeprecation::Yes,
458500
InheritConstStability::No,
@@ -470,6 +512,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
470512
self.annotate(
471513
s.hir_id,
472514
s.span,
515+
None,
473516
AnnotationKind::Required,
474517
InheritDeprecation::Yes,
475518
InheritConstStability::No,
@@ -484,6 +527,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
484527
self.annotate(
485528
i.hir_id(),
486529
i.span,
530+
None,
487531
AnnotationKind::Required,
488532
InheritDeprecation::Yes,
489533
InheritConstStability::No,
@@ -498,6 +542,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
498542
self.annotate(
499543
md.hir_id(),
500544
md.span,
545+
None,
501546
AnnotationKind::Required,
502547
InheritDeprecation::Yes,
503548
InheritConstStability::No,
@@ -517,6 +562,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
517562
self.annotate(
518563
p.hir_id,
519564
p.span,
565+
None,
520566
kind,
521567
InheritDeprecation::No,
522568
InheritConstStability::No,
@@ -687,6 +733,7 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
687733
annotator.annotate(
688734
hir::CRATE_HIR_ID,
689735
krate.item.inner,
736+
None,
690737
AnnotationKind::Required,
691738
InheritDeprecation::Yes,
692739
InheritConstStability::No,
@@ -969,3 +1016,15 @@ fn duplicate_feature_err(sess: &Session, span: Span, feature: Symbol) {
9691016
struct_span_err!(sess, span, E0636, "the feature `{}` has already been declared", feature)
9701017
.emit();
9711018
}
1019+
1020+
fn missing_const_err(session: &Session, fn_sig_span: Span, const_span: Span) {
1021+
const ERROR_MSG: &'static str = "attributes `#[rustc_const_unstable]` \
1022+
and `#[rustc_const_stable]` require \
1023+
the function or method to be `const`";
1024+
1025+
session
1026+
.struct_span_err(fn_sig_span, ERROR_MSG)
1027+
.span_help(fn_sig_span, "make the function or method const")
1028+
.span_label(const_span, "attribute specified here")
1029+
.emit();
1030+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#![crate_type = "lib"]
2+
#![feature(staged_api)]
3+
#![stable(feature = "foo", since = "1.0.0")]
4+
5+
#[stable(feature = "foo", since = "1.0.0")]
6+
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
7+
pub fn foo() {}
8+
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
9+
10+
#[stable(feature = "bar", since = "1.0.0")]
11+
#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
12+
pub fn bar() {}
13+
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
14+
15+
#[stable(feature = "potato", since = "1.0.0")]
16+
pub struct Potato;
17+
18+
impl Potato {
19+
#[stable(feature = "salad", since = "1.0.0")]
20+
#[rustc_const_unstable(feature = "const_salad", issue = "none")]
21+
pub fn salad(&self) -> &'static str { "mmmmmm" }
22+
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
23+
24+
#[stable(feature = "roasted", since = "1.0.0")]
25+
#[rustc_const_unstable(feature = "const_roasted", issue = "none")]
26+
pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
27+
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
28+
}
29+
30+
#[stable(feature = "bar", since = "1.0.0")]
31+
#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
32+
pub extern "C" fn bar_c() {}
33+
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
34+
35+
#[stable(feature = "foo", since = "1.0.0")]
36+
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
37+
pub extern "C" fn foo_c() {}
38+
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
39+
40+
41+
#[stable(feature = "foobar", since = "1.0.0")]
42+
#[rustc_const_unstable(feature = "foobar_const", issue = "none")]
43+
pub const fn foobar() {}
44+
45+
#[stable(feature = "barfoo", since = "1.0.0")]
46+
#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
47+
pub const fn barfoo() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
2+
--> $DIR/rustc-const-stability-require-const.rs:7:1
3+
|
4+
LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
5+
| -------------------------------------------------------------- attribute specified here
6+
LL | pub fn foo() {}
7+
| ^^^^^^^^^^^^
8+
|
9+
help: make the function or method const
10+
--> $DIR/rustc-const-stability-require-const.rs:7:1
11+
|
12+
LL | pub fn foo() {}
13+
| ^^^^^^^^^^^^
14+
15+
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
16+
--> $DIR/rustc-const-stability-require-const.rs:12:1
17+
|
18+
LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
19+
| ------------------------------------------------------------- attribute specified here
20+
LL | pub fn bar() {}
21+
| ^^^^^^^^^^^^
22+
|
23+
help: make the function or method const
24+
--> $DIR/rustc-const-stability-require-const.rs:12:1
25+
|
26+
LL | pub fn bar() {}
27+
| ^^^^^^^^^^^^
28+
29+
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
30+
--> $DIR/rustc-const-stability-require-const.rs:21:5
31+
|
32+
LL | #[rustc_const_unstable(feature = "const_salad", issue = "none")]
33+
| ---------------------------------------------------------------- attribute specified here
34+
LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36+
|
37+
help: make the function or method const
38+
--> $DIR/rustc-const-stability-require-const.rs:21:5
39+
|
40+
LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
41+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
42+
43+
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
44+
--> $DIR/rustc-const-stability-require-const.rs:26:5
45+
|
46+
LL | #[rustc_const_unstable(feature = "const_roasted", issue = "none")]
47+
| ------------------------------------------------------------------ attribute specified here
48+
LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
50+
|
51+
help: make the function or method const
52+
--> $DIR/rustc-const-stability-require-const.rs:26:5
53+
|
54+
LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
55+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
56+
57+
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
58+
--> $DIR/rustc-const-stability-require-const.rs:32:1
59+
|
60+
LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
61+
| ------------------------------------------------------------- attribute specified here
62+
LL | pub extern "C" fn bar_c() {}
63+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
64+
|
65+
help: make the function or method const
66+
--> $DIR/rustc-const-stability-require-const.rs:32:1
67+
|
68+
LL | pub extern "C" fn bar_c() {}
69+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
70+
71+
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be `const`
72+
--> $DIR/rustc-const-stability-require-const.rs:37:1
73+
|
74+
LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
75+
| -------------------------------------------------------------- attribute specified here
76+
LL | pub extern "C" fn foo_c() {}
77+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
78+
|
79+
help: make the function or method const
80+
--> $DIR/rustc-const-stability-require-const.rs:37:1
81+
|
82+
LL | pub extern "C" fn foo_c() {}
83+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
84+
85+
error: aborting due to 6 previous errors
86+

0 commit comments

Comments
 (0)