Skip to content

Commit

Permalink
fn must be const if marked with stability attribut
Browse files Browse the repository at this point in the history
remove trailing newline

fix: test with attribute but missing const

Update compiler/rustc_passes/src/stability.rs

Co-authored-by: Léo Lanteri Thauvin <leseulartichaut@gmail.com>

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 <leseulartichaut@gmail.com>
  • Loading branch information
Lamb and LeSeulArtichaut committed Jul 4, 2021
1 parent 96859db commit f3f2def
Show file tree
Hide file tree
Showing 6 changed files with 200 additions and 7 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0542.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Erroneous code example:
fn _stable_fn() {}
#[rustc_const_stable(feature = "_stable_const_fn")] // invalid
fn _stable_const_fn() {}
const fn _stable_const_fn() {}
#[stable(feature = "_deprecated_fn", since = "0.1.0")]
#[rustc_deprecated(
Expand All @@ -29,7 +29,7 @@ To fix this issue, you need to provide the `since` field. Example:
fn _stable_fn() {}
#[rustc_const_stable(feature = "_stable_const_fn", since = "1.0.0")] // ok!
fn _stable_const_fn() {}
const fn _stable_const_fn() {}
#[stable(feature = "_deprecated_fn", since = "0.1.0")]
#[rustc_deprecated(
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0545.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Erroneous code example:
fn _unstable_fn() {}
#[rustc_const_unstable(feature = "_unstable_const_fn", issue = "0")] // invalid
fn _unstable_const_fn() {}
const fn _unstable_const_fn() {}
```

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

See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0547.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Erroneous code example:
fn _unstable_fn() {}
#[rustc_const_unstable(feature = "_unstable_const_fn")] // invalid
fn _unstable_const_fn() {}
const fn _unstable_const_fn() {}
```

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

See the [How Rust is Made and “Nightly Rust”][how-rust-made-nightly] appendix
Expand Down
51 changes: 50 additions & 1 deletion compiler/rustc_passes/src/stability.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use rustc_session::parse::feature_err;
use rustc_session::Session;
use rustc_span::symbol::{sym, Symbol};
use rustc_span::{Span, DUMMY_SP};
use rustc_target::spec::abi::Abi;

use std::cmp::Ordering;
use std::iter;
Expand Down Expand Up @@ -95,10 +96,12 @@ struct Annotator<'a, 'tcx> {
impl<'a, 'tcx> Annotator<'a, 'tcx> {
// Determine the stability for a node based on its attributes and inherited
// stability. The stability is recorded in the index and used as the parent.
// If the node is a function, `fn_sig` is its signature
fn annotate<F>(
&mut self,
hir_id: HirId,
item_sp: Span,
fn_sig: Option<&'tcx hir::FnSig<'tcx>>,
kind: AnnotationKind,
inherit_deprecation: InheritDeprecation,
inherit_const_stability: InheritConstStability,
Expand Down Expand Up @@ -164,8 +167,27 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {

let (stab, const_stab) = attr::find_stability(&self.tcx.sess, attrs, item_sp);

let const_stab = const_stab.map(|(const_stab, _)| {
let const_stab = const_stab.map(|(const_stab, const_span)| {
let const_stab = self.tcx.intern_const_stability(const_stab);
if let Some(fn_sig) = fn_sig {
if !(fn_sig.header.constness == hir::Constness::Const
&& fn_sig.header.abi != Abi::RustIntrinsic
&& fn_sig.header.abi != Abi::PlatformIntrinsic)
{
self.tcx
.sess
.struct_span_err(
fn_sig.span,
"attributes `#[rustc_const_unstable]` \
and `#[rustc_const_stable]` require \
the function or method to be marked `const`",
)
.span_help(fn_sig.span, "make the function or method const")
.span_label(const_span, "attribute specified here")
.emit();
}
}

self.index.const_stab_map.insert(hir_id, const_stab);
const_stab
});
Expand Down Expand Up @@ -367,6 +389,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
let orig_in_trait_impl = self.in_trait_impl;
let mut kind = AnnotationKind::Required;
let mut const_stab_inherit = InheritConstStability::No;
let mut fn_sig = None;

match i.kind {
// Inherent impls and foreign modules serve only as containers for other items,
// they don't have their own stability. They still can be annotated as unstable
Expand All @@ -387,6 +411,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
self.annotate(
ctor_hir_id,
i.span,
None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
Expand All @@ -395,12 +420,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
)
}
}
hir::ItemKind::Fn(ref item_fn_sig, _, _) => {
fn_sig = Some(item_fn_sig);
}
_ => {}
}

self.annotate(
i.hir_id(),
i.span,
fn_sig,
kind,
InheritDeprecation::Yes,
const_stab_inherit,
Expand All @@ -411,9 +440,15 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
}

fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem<'tcx>) {
let fn_sig = match ti.kind {
hir::TraitItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
_ => None,
};

self.annotate(
ti.hir_id(),
ti.span,
fn_sig,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
Expand All @@ -427,9 +462,16 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem<'tcx>) {
let kind =
if self.in_trait_impl { AnnotationKind::Prohibited } else { AnnotationKind::Required };

let fn_sig = match ii.kind {
hir::ImplItemKind::Fn(ref fn_sig, _) => Some(fn_sig),
_ => None,
};

self.annotate(
ii.hir_id(),
ii.span,
fn_sig,
kind,
InheritDeprecation::Yes,
InheritConstStability::No,
Expand All @@ -444,6 +486,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
self.annotate(
var.id,
var.span,
None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
Expand All @@ -453,6 +496,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
v.annotate(
ctor_hir_id,
var.span,
None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
Expand All @@ -470,6 +514,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
self.annotate(
s.hir_id,
s.span,
None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
Expand All @@ -484,6 +529,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
self.annotate(
i.hir_id(),
i.span,
None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
Expand All @@ -498,6 +544,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
self.annotate(
md.hir_id(),
md.span,
None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
Expand All @@ -517,6 +564,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
self.annotate(
p.hir_id,
p.span,
None,
kind,
InheritDeprecation::No,
InheritConstStability::No,
Expand Down Expand Up @@ -687,6 +735,7 @@ fn stability_index(tcx: TyCtxt<'tcx>, (): ()) -> Index<'tcx> {
annotator.annotate(
hir::CRATE_HIR_ID,
krate.item.inner,
None,
AnnotationKind::Required,
InheritDeprecation::Yes,
InheritConstStability::No,
Expand Down
44 changes: 44 additions & 0 deletions src/test/ui/consts/rustc-const-stability-require-const.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#![crate_type = "lib"]
#![feature(staged_api)]
#![stable(feature = "foo", since = "1.0.0")]

#[stable(feature = "foo", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
pub fn foo() {}
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`

#[stable(feature = "bar", since = "1.0.0")]
#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
pub fn bar() {}
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`

#[stable(feature = "potato", since = "1.0.0")]
pub struct Potato;

impl Potato {
#[stable(feature = "salad", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_salad", issue = "none")]
pub fn salad(&self) -> &'static str { "mmmmmm" }
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`

#[stable(feature = "roasted", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_roasted", issue = "none")]
pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`
}

#[stable(feature = "bar", since = "1.0.0")]
#[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
pub extern "C" fn bar_c() {}
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`

#[stable(feature = "foo", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
pub extern "C" fn foo_c() {}
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`


#[stable(feature = "foo", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_foo", issue = "none")]
pub extern "stdcall" fn foo_stdcall() {}
//~^ ERROR attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`
100 changes: 100 additions & 0 deletions src/test/ui/consts/rustc-const-stability-require-const.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`
--> $DIR/rustc-const-stability-require-const.rs:7:1
|
LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
| -------------------------------------------------------------- attribute specified here
LL | pub fn foo() {}
| ^^^^^^^^^^^^
|
help: make the function or method const
--> $DIR/rustc-const-stability-require-const.rs:7:1
|
LL | pub fn foo() {}
| ^^^^^^^^^^^^

error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`
--> $DIR/rustc-const-stability-require-const.rs:12:1
|
LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
| ------------------------------------------------------------- attribute specified here
LL | pub fn bar() {}
| ^^^^^^^^^^^^
|
help: make the function or method const
--> $DIR/rustc-const-stability-require-const.rs:12:1
|
LL | pub fn bar() {}
| ^^^^^^^^^^^^

error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`
--> $DIR/rustc-const-stability-require-const.rs:21:5
|
LL | #[rustc_const_unstable(feature = "const_salad", issue = "none")]
| ---------------------------------------------------------------- attribute specified here
LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: make the function or method const
--> $DIR/rustc-const-stability-require-const.rs:21:5
|
LL | pub fn salad(&self) -> &'static str { "mmmmmm" }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`
--> $DIR/rustc-const-stability-require-const.rs:26:5
|
LL | #[rustc_const_unstable(feature = "const_roasted", issue = "none")]
| ------------------------------------------------------------------ attribute specified here
LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: make the function or method const
--> $DIR/rustc-const-stability-require-const.rs:26:5
|
LL | pub fn roasted(&self) -> &'static str { "mmmmmmmmmm" }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`
--> $DIR/rustc-const-stability-require-const.rs:32:1
|
LL | #[rustc_const_stable(feature = "const_bar", since = "1.0.0")]
| ------------------------------------------------------------- attribute specified here
LL | pub extern "C" fn bar_c() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: make the function or method const
--> $DIR/rustc-const-stability-require-const.rs:32:1
|
LL | pub extern "C" fn bar_c() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`
--> $DIR/rustc-const-stability-require-const.rs:37:1
|
LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
| -------------------------------------------------------------- attribute specified here
LL | pub extern "C" fn foo_c() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: make the function or method const
--> $DIR/rustc-const-stability-require-const.rs:37:1
|
LL | pub extern "C" fn foo_c() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error: attributes `#[rustc_const_unstable]` and `#[rustc_const_stable]` require the function or method to be marked `const`
--> $DIR/rustc-const-stability-require-const.rs:43:1
|
LL | #[rustc_const_unstable(feature = "const_foo", issue = "none")]
| -------------------------------------------------------------- attribute specified here
LL | pub extern "stdcall" fn foo_stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: make the function or method const
--> $DIR/rustc-const-stability-require-const.rs:43:1
|
LL | pub extern "stdcall" fn foo_stdcall() {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 7 previous errors

0 comments on commit f3f2def

Please sign in to comment.