Skip to content

Commit 07f903e

Browse files
author
Lamb
committed
fn must be const if marked with stability attribut
remove trailing newline fix: test with attribute but missing const Update compiler/rustc_passes/src/stability.rs Co-authored-by: Léo Lanteri Thauvin <[email protected]> Add test for extern functions fix: using span_help instead of span_suggestion add test for some ABIs + fmt fix Update compiler/rustc_passes/src/stability.rs Co-authored-by: Léo Lanteri Thauvin <[email protected]> Refractor and add test for `impl const` Add test to make sure no output + cleanup condition ----------------------------- remove stdcall test, failing CI test C abi is already tested in this, so it is not that useful to test another one. The tested code is blind to which specific ABI for now, as long as it's not an intrinsic one
1 parent 96859db commit 07f903e

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)