From c4f2d21f1a9e41c025cc8cfca5f5f06053aba70e Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sat, 29 Jan 2022 11:54:16 +0000 Subject: [PATCH 1/4] Mark the panic_no_unwind lang item as nounwind --- compiler/rustc_typeck/src/collect.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index cf519a9ab3274..7c8a47d5d6524 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2778,6 +2778,13 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } } + // The panic_no_unwind function called by TerminatorKind::Abort will never + // unwind. If the panic handler that it invokes unwind then it will simply + // call the panic handler again. + if Some(id) == tcx.lang_items().panic_no_unwind() { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND; + } + let supported_target_features = tcx.supported_target_features(LOCAL_CRATE); let mut inline_span = None; From f738669b636eae466fef00f62af5d393169c676d Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Sun, 30 Jan 2022 21:33:51 +0100 Subject: [PATCH 2/4] Clarify safety of PanicInfo::can_unwind --- library/core/src/panic/panic_info.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 405224f8fb0b0..be8598fae09d7 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -136,6 +136,10 @@ impl<'a> PanicInfo<'a> { /// This is true for most kinds of panics with the exception of panics /// caused by trying to unwind out of a `Drop` implementation or a function /// whose ABI does not support unwinding. + /// + /// It is safe for a panic handler to unwind even when this function returns + /// true, however this will simply cause the panic handler to be called + /// again. #[must_use] #[unstable(feature = "panic_can_unwind", issue = "92988")] pub fn can_unwind(&self) -> bool { From 41f84c258ad5fc12775e25aafe4d67e3304a5bda Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Wed, 17 Nov 2021 21:06:17 -0500 Subject: [PATCH 3/4] Require const stability on all stable const items This was supposed to be the case previously, but a missed method call meant that trait impls were not checked. --- compiler/rustc_passes/src/stability.rs | 36 +++++++++---------- .../missing-const-stability.rs | 24 +++++++++---- .../missing-const-stability.stderr | 12 +++++-- 3 files changed, 45 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 3521b6fc1696c..136059677c5ae 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -577,17 +577,21 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { } fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) { - let stab_map = self.tcx.stability(); - let stab = stab_map.local_stability(def_id); - if stab.map_or(false, |stab| stab.level.is_stable()) { - let const_stab = stab_map.local_const_stability(def_id); - if const_stab.is_none() { - self.tcx.sess.span_err( - span, - "`#[stable]` const functions must also be either \ - `#[rustc_const_stable]` or `#[rustc_const_unstable]`", - ); - } + if !self.tcx.features().staged_api { + return; + } + + let is_const = self.tcx.is_const_fn(def_id.to_def_id()); + let is_stable = self + .tcx + .lookup_stability(def_id) + .map_or(false, |stability| stability.level.is_stable()); + let missing_const_stability_attribute = self.tcx.lookup_const_stability(def_id).is_none(); + let is_reachable = self.access_levels.is_reachable(def_id); + + if is_const && is_stable && missing_const_stability_attribute && is_reachable { + let descr = self.tcx.def_kind(def_id).descr(def_id.to_def_id()); + self.tcx.sess.span_err(span, &format!("{descr} has missing const stability attribute")); } } } @@ -612,13 +616,8 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { self.check_missing_stability(i.def_id, i.span); } - // Ensure `const fn` that are `stable` have one of `rustc_const_unstable` or - // `rustc_const_stable`. - if self.tcx.features().staged_api - && matches!(&i.kind, hir::ItemKind::Fn(sig, ..) if sig.header.is_const()) - { - self.check_missing_const_stability(i.def_id, i.span); - } + // Ensure stable `const fn` have a const stability attribute. + self.check_missing_const_stability(i.def_id, i.span); intravisit::walk_item(self, i) } @@ -632,6 +631,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> { let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id()); if self.tcx.impl_trait_ref(impl_def_id).is_none() { self.check_missing_stability(ii.def_id, ii.span); + self.check_missing_const_stability(ii.def_id, ii.span); } intravisit::walk_impl_item(self, ii); } diff --git a/src/test/ui/stability-attribute/missing-const-stability.rs b/src/test/ui/stability-attribute/missing-const-stability.rs index 7d499c611a43c..39af6e9e3b935 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.rs +++ b/src/test/ui/stability-attribute/missing-const-stability.rs @@ -1,12 +1,24 @@ #![feature(staged_api)] +#![stable(feature = "stable", since = "1.0.0")] -#![stable(feature = "rust1", since = "1.0.0")] +#[stable(feature = "stable", since = "1.0.0")] +pub const fn foo() {} //~ ERROR function has missing const stability attribute -#[stable(feature = "foo", since = "1.0.0")] -pub const fn foo() {} -//~^ ERROR rustc_const_stable +#[unstable(feature = "unstable", issue = "none")] +pub const fn bar() {} // ok for now -#[unstable(feature = "bar", issue = "none")] -pub const fn bar() {} // ok +#[stable(feature = "stable", since = "1.0.0")] +pub struct Foo; +impl Foo { + #[stable(feature = "stable", since = "1.0.0")] + pub const fn foo() {} //~ ERROR associated function has missing const stability attribute + + #[unstable(feature = "unstable", issue = "none")] + pub const fn bar() {} // ok for now +} + +// FIXME When #![feature(const_trait_impl)] is stabilized, add tests for const +// trait impls. Right now, a "trait methods cannot be stable const fn" error is +// emitted, but that's not in the scope of this test. fn main() {} diff --git a/src/test/ui/stability-attribute/missing-const-stability.stderr b/src/test/ui/stability-attribute/missing-const-stability.stderr index 450a5303fd86f..ee98e7b0e3fb1 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.stderr +++ b/src/test/ui/stability-attribute/missing-const-stability.stderr @@ -1,8 +1,14 @@ -error: `#[stable]` const functions must also be either `#[rustc_const_stable]` or `#[rustc_const_unstable]` - --> $DIR/missing-const-stability.rs:6:1 +error: function has missing const stability attribute + --> $DIR/missing-const-stability.rs:5:1 | LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: associated function has missing const stability attribute + --> $DIR/missing-const-stability.rs:14:5 + | +LL | pub const fn foo() {} + | ^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors From 1911eb8b6180f513a666372baf6e56f78b82dcd8 Mon Sep 17 00:00:00 2001 From: Jacob Pratt Date: Wed, 17 Nov 2021 21:08:16 -0500 Subject: [PATCH 4/4] Add missing const stability attributes --- library/core/src/array/mod.rs | 1 + library/core/src/cell.rs | 1 + library/core/src/num/int_macros.rs | 1 + library/core/src/num/nonzero.rs | 1 + library/core/src/num/uint_macros.rs | 1 + .../stability-attribute/missing-const-stability.rs | 12 +++++++----- .../missing-const-stability.stderr | 4 ++-- 7 files changed, 14 insertions(+), 7 deletions(-) diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs index 121aa634deb33..ee79021ed536e 100644 --- a/library/core/src/array/mod.rs +++ b/library/core/src/array/mod.rs @@ -512,6 +512,7 @@ impl [T; N] { /// Returns a slice containing the entire array. Equivalent to `&s[..]`. #[stable(feature = "array_as_slice", since = "1.57.0")] + #[rustc_const_stable(feature = "array_as_slice", since = "1.57.0")] pub const fn as_slice(&self) -> &[T] { self } diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 5fd60b759286a..feb9455565844 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -1959,6 +1959,7 @@ impl UnsafeCell { /// ``` #[inline(always)] #[stable(feature = "unsafe_cell_raw_get", since = "1.56.0")] + #[rustc_const_stable(feature = "unsafe_cell_raw_get", since = "1.56.0")] pub const fn raw_get(this: *const Self) -> *mut T { // We can just cast the pointer from `UnsafeCell` to `T` because of // #[repr(transparent)]. This exploits libstd's special status, there is diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 79436c8e8ede4..3164b0c5d3cc6 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -1064,6 +1064,7 @@ macro_rules! int_impl { /// /// ``` #[stable(feature = "saturating_div", since = "1.58.0")] + #[rustc_const_stable(feature = "saturating_div", since = "1.58.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index e21ae48917953..1ebd1c58f2b59 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -972,6 +972,7 @@ macro_rules! nonzero_unsigned_is_power_of_two { /// ``` #[must_use] #[stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] + #[rustc_const_stable(feature = "nonzero_is_power_of_two", since = "1.59.0")] #[inline] pub const fn is_power_of_two(self) -> bool { // LLVM 11 normalizes `unchecked_sub(x, 1) & x == 0` to the implementation seen here. diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 0bb654977764d..c1a134e68cde7 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1132,6 +1132,7 @@ macro_rules! uint_impl { /// /// ``` #[stable(feature = "saturating_div", since = "1.58.0")] + #[rustc_const_stable(feature = "saturating_div", since = "1.58.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/src/test/ui/stability-attribute/missing-const-stability.rs b/src/test/ui/stability-attribute/missing-const-stability.rs index 39af6e9e3b935..57e64737d0faa 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.rs +++ b/src/test/ui/stability-attribute/missing-const-stability.rs @@ -1,11 +1,12 @@ #![feature(staged_api)] +#![feature(const_trait_impl)] #![stable(feature = "stable", since = "1.0.0")] #[stable(feature = "stable", since = "1.0.0")] pub const fn foo() {} //~ ERROR function has missing const stability attribute #[unstable(feature = "unstable", issue = "none")] -pub const fn bar() {} // ok for now +pub const fn bar() {} // ok because function is unstable #[stable(feature = "stable", since = "1.0.0")] pub struct Foo; @@ -14,11 +15,12 @@ impl Foo { pub const fn foo() {} //~ ERROR associated function has missing const stability attribute #[unstable(feature = "unstable", issue = "none")] - pub const fn bar() {} // ok for now + pub const fn bar() {} // ok because function is unstable } -// FIXME When #![feature(const_trait_impl)] is stabilized, add tests for const -// trait impls. Right now, a "trait methods cannot be stable const fn" error is -// emitted, but that's not in the scope of this test. +// FIXME Once #![feature(const_trait_impl)] is allowed to be stable, add a test +// for const trait impls. Right now, a "trait methods cannot be stable const fn" +// error is emitted. This occurs prior to the lint being tested here, such that +// the lint cannot currently be tested on this use case. fn main() {} diff --git a/src/test/ui/stability-attribute/missing-const-stability.stderr b/src/test/ui/stability-attribute/missing-const-stability.stderr index ee98e7b0e3fb1..7eba99a477abe 100644 --- a/src/test/ui/stability-attribute/missing-const-stability.stderr +++ b/src/test/ui/stability-attribute/missing-const-stability.stderr @@ -1,11 +1,11 @@ error: function has missing const stability attribute - --> $DIR/missing-const-stability.rs:5:1 + --> $DIR/missing-const-stability.rs:6:1 | LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^ error: associated function has missing const stability attribute - --> $DIR/missing-const-stability.rs:14:5 + --> $DIR/missing-const-stability.rs:15:5 | LL | pub const fn foo() {} | ^^^^^^^^^^^^^^^^^^^^^