From 97816a2451b0c8ab8e7472cbe024623a7c067e66 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Wed, 27 Oct 2021 17:48:29 -0400 Subject: [PATCH 1/3] Lint unstable functions that are const stable --- compiler/rustc_lint/src/internal.rs | 44 +++++++++++++++++++ compiler/rustc_lint/src/lib.rs | 3 ++ src/test/ui/lint/incompatible_stability.rs | 16 +++++++ .../ui/lint/incompatible_stability.stderr | 16 +++++++ 4 files changed, 79 insertions(+) create mode 100644 src/test/ui/lint/incompatible_stability.rs create mode 100644 src/test/ui/lint/incompatible_stability.stderr diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index e9dcc120200d0..3c8b02da3668f 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -358,3 +358,47 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword { } } } + +declare_tool_lint! { + pub rustc::INCOMPATIBLE_STABILITY, + Deny, + "check that an unstable item is not const-stable" +} + +declare_lint_pass!(IncompatibleStability => [INCOMPATIBLE_STABILITY]); + +impl LateLintPass<'_> for IncompatibleStability { + fn check_fn( + &mut self, + cx: &LateContext<'_>, + kind: rustc_hir::intravisit::FnKind<'_>, + _: &FnDecl<'_>, + _: &Body<'_>, + span: rustc_span::Span, + hir_id: HirId, + ) { + use rustc_attr::{ConstStability, Stability, StabilityLevel}; + + // Perform a cheap check up-front to avoid unnecessary querying. + if kind.constness() == rustc_hir::Constness::NotConst { + return; + } + + if !matches!( + cx.tcx.lookup_stability(hir_id.owner), + Some(Stability { level: StabilityLevel::Unstable { .. }, .. }) + ) { + return; + } + if !matches!( + cx.tcx.lookup_const_stability(hir_id.owner), + Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) + ) { + return; + } + + cx.struct_span_lint(INCOMPATIBLE_STABILITY, span, |lint| { + lint.build("functions cannot be const-stable if they are unstable").emit(); + }); + } +} diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index f83eaabdfefcd..618abd6c05bf0 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -492,6 +492,8 @@ fn register_internals(store: &mut LintStore) { store.register_late_pass(|| Box::new(ExistingDocKeyword)); store.register_lints(&TyTyKind::get_lints()); store.register_late_pass(|| Box::new(TyTyKind)); + store.register_lints(&IncompatibleStability::get_lints()); + store.register_late_pass(|| Box::new(IncompatibleStability)); store.register_group( false, "rustc::internal", @@ -504,6 +506,7 @@ fn register_internals(store: &mut LintStore) { LintId::of(TY_PASS_BY_REFERENCE), LintId::of(USAGE_OF_QUALIFIED_TY), LintId::of(EXISTING_DOC_KEYWORD), + LintId::of(INCOMPATIBLE_STABILITY), ], ); } diff --git a/src/test/ui/lint/incompatible_stability.rs b/src/test/ui/lint/incompatible_stability.rs new file mode 100644 index 0000000000000..6c0b53ee3d693 --- /dev/null +++ b/src/test/ui/lint/incompatible_stability.rs @@ -0,0 +1,16 @@ +// compile-flags: -Zunstable-options +#![stable(feature = "stable", since = "1.0.0")] +#![feature(staged_api, rustc_attrs)] + +#[unstable(feature = "unstable", issue = "none")] +#[rustc_const_stable(feature = "stable", since = "1.0.0")] +const fn foo() {} //~ ERROR functions cannot be const-stable if they are unstable + +mod bar { + #![unstable(feature = "unstable", issue = "none")] + + #[rustc_const_stable(feature = "stable", since = "1.0.0")] + const fn foo() {} //~ ERROR functions cannot be const-stable if they are unstable +} + +fn main() {} diff --git a/src/test/ui/lint/incompatible_stability.stderr b/src/test/ui/lint/incompatible_stability.stderr new file mode 100644 index 0000000000000..91a13ed5623c3 --- /dev/null +++ b/src/test/ui/lint/incompatible_stability.stderr @@ -0,0 +1,16 @@ +error: functions cannot be const-stable if they are unstable + --> $DIR/incompatible_stability.rs:7:1 + | +LL | const fn foo() {} + | ^^^^^^^^^^^^^^^^^ + | + = note: `#[deny(rustc::incompatible_stability)]` on by default + +error: functions cannot be const-stable if they are unstable + --> $DIR/incompatible_stability.rs:13:5 + | +LL | const fn foo() {} + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From 354502ace96b13e08a4757e0a1c7c6bab323f7e5 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Wed, 27 Oct 2021 18:51:11 -0400 Subject: [PATCH 2/3] Lint unstable extern fns that are const stable --- compiler/rustc_lint/src/internal.rs | 25 +++++++++++++++++++ src/test/ui/lint/incompatible_stability.rs | 10 +++++++- .../ui/lint/incompatible_stability.stderr | 8 +++++- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 3c8b02da3668f..bc92ead17c88f 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -401,4 +401,29 @@ impl LateLintPass<'_> for IncompatibleStability { lint.build("functions cannot be const-stable if they are unstable").emit(); }); } + + fn check_foreign_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::ForeignItem<'_>) { + use rustc_attr::{ConstStability, Stability, StabilityLevel}; + + if !matches!(item.kind, rustc_hir::ForeignItemKind::Fn(..)) { + return; + } + + if !matches!( + cx.tcx.lookup_stability(item.def_id), + Some(Stability { level: StabilityLevel::Unstable { .. }, .. }) + ) { + return; + } + if !matches!( + cx.tcx.lookup_const_stability(item.def_id), + Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) + ) { + return; + } + + cx.struct_span_lint(INCOMPATIBLE_STABILITY, item.span, |lint| { + lint.build("functions cannot be const-stable if they are unstable").emit(); + }); + } } diff --git a/src/test/ui/lint/incompatible_stability.rs b/src/test/ui/lint/incompatible_stability.rs index 6c0b53ee3d693..20587daaccf14 100644 --- a/src/test/ui/lint/incompatible_stability.rs +++ b/src/test/ui/lint/incompatible_stability.rs @@ -1,6 +1,6 @@ // compile-flags: -Zunstable-options #![stable(feature = "stable", since = "1.0.0")] -#![feature(staged_api, rustc_attrs)] +#![feature(staged_api, rustc_attrs, intrinsics)] #[unstable(feature = "unstable", issue = "none")] #[rustc_const_stable(feature = "stable", since = "1.0.0")] @@ -13,4 +13,12 @@ mod bar { const fn foo() {} //~ ERROR functions cannot be const-stable if they are unstable } +mod intrinsics { + #![unstable(feature = "unstable", issue = "none")] + extern "rust-intrinsic" { + #[rustc_const_stable(feature = "stable", since = "1.0.0")] + pub fn transmute(_: T) -> U; //~ ERROR functions cannot be const-stable if they are unstable + } +} + fn main() {} diff --git a/src/test/ui/lint/incompatible_stability.stderr b/src/test/ui/lint/incompatible_stability.stderr index 91a13ed5623c3..cea0e7e43ccb0 100644 --- a/src/test/ui/lint/incompatible_stability.stderr +++ b/src/test/ui/lint/incompatible_stability.stderr @@ -12,5 +12,11 @@ error: functions cannot be const-stable if they are unstable LL | const fn foo() {} | ^^^^^^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: functions cannot be const-stable if they are unstable + --> $DIR/incompatible_stability.rs:20:9 + | +LL | pub fn transmute(_: T) -> U; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors From a11d1c567c300ce13cdae37bf514b0cba7e5ade5 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Thu, 28 Oct 2021 00:01:46 -0400 Subject: [PATCH 3/3] Fix incompatible stability lint --- library/core/src/intrinsics.rs | 2 ++ library/core/src/num/saturating.rs | 2 +- library/core/src/num/uint_macros.rs | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs index 1aeb83931e5aa..19116b2313111 100644 --- a/library/core/src/intrinsics.rs +++ b/library/core/src/intrinsics.rs @@ -53,6 +53,8 @@ issue = "none" )] #![allow(missing_docs)] +// intrinsics are never stable but may need to be const-stable for other items +#![cfg_attr(not(bootstrap), allow(rustc::incompatible_stability))] use crate::marker::DiscriminantKind; use crate::mem; diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs index ba81f3f9fd6a0..d9b14c82e96ba 100644 --- a/library/core/src/num/saturating.rs +++ b/library/core/src/num/saturating.rs @@ -628,7 +628,7 @@ macro_rules! saturating_int_impl { /// ``` #[inline] #[unstable(feature = "saturating_int_impl", issue = "87920")] - #[rustc_const_stable(feature = "const_reverse_bits", since = "1.37.0")] + #[rustc_const_unstable(feature = "saturating_int_impl", issue = "87920")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn reverse_bits(self) -> Self { diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 507ff516a8f28..66b12848bab2b 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -2208,7 +2208,7 @@ macro_rules! uint_impl { /// ``` #[unstable(feature = "wrapping_next_power_of_two", issue = "32463", reason = "needs decision on wrapping behaviour")] - #[rustc_const_stable(feature = "const_int_pow", since = "1.50.0")] + #[rustc_const_unstable(feature = "wrapping_next_power_of_two", issue = "32463")] #[must_use = "this returns the result of the operation, \ without modifying the original"] pub const fn wrapping_next_power_of_two(self) -> Self {