Skip to content

Commit 4020bb0

Browse files
authored
Unrolled build for #153563
Rollup merge of #153563 - Urgau:lint-panics-when-n-is-zero, r=fee1-dead,ShoyuVanilla Lint against iterator functions that panic when `N` is zero This PR extends the deny-by-default `unconditional_panic` lint, by linting on iterator functions that panics when `N` (chunks/windows size) is zero[^attr]. Those methods are [documented](https://doc.rust-lang.org/std/primitive.slice.html#panics-11) to panic if `N` is zero. ``` error: this operation will panic at runtime --> $DIR/const-n-is-zero.rs:11:13 | LL | let _ = s.array_windows::<0>(); | ^^^^^^^^^^^^^^^^^^^^^^ const parameter `N` is zero | = note: `#[deny(unconditional_panic)]` on by default ``` cc @rust-lang/libs-api [^attr]: this is done by introducing a new internal attribute on the const parameter: `#[rustc_panics_when_zero]`
2 parents bf9944f + 24e4698 commit 4020bb0

15 files changed

Lines changed: 212 additions & 22 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use rustc_hir::attrs::{
77
BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior,
88
DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcMirKind,
99
};
10+
use rustc_hir::target::GenericParamKind;
1011
use rustc_span::Symbol;
1112

1213
use super::prelude::*;
@@ -90,6 +91,20 @@ impl NoArgsAttributeParser for RustcNeverReturnsNullPtrParser {
9091

9192
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPtr;
9293
}
94+
95+
pub(crate) struct RustcPanicsWhenZeroParser;
96+
97+
impl NoArgsAttributeParser for RustcPanicsWhenZeroParser {
98+
const PATH: &[Symbol] = &[sym::rustc_panics_when_zero];
99+
const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
100+
Allow(Target::GenericParam { kind: GenericParamKind::Const, has_default: true }),
101+
Allow(Target::GenericParam { kind: GenericParamKind::Const, has_default: false }),
102+
]);
103+
const STABILITY: AttributeStability = unstable!(rustc_attrs);
104+
105+
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPanicsWhenZero;
106+
}
107+
93108
pub(crate) struct RustcNoImplicitAutorefsParser;
94109

95110
impl NoArgsAttributeParser for RustcNoImplicitAutorefsParser {

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ attribute_parsers!(
340340
Single<WithoutArgs<RustcNonnullOptimizationGuaranteedParser>>,
341341
Single<WithoutArgs<RustcNounwindParser>>,
342342
Single<WithoutArgs<RustcOffloadKernelParser>>,
343+
Single<WithoutArgs<RustcPanicsWhenZeroParser>>,
343344
Single<WithoutArgs<RustcParenSugarParser>>,
344345
Single<WithoutArgs<RustcPassByValueParser>>,
345346
Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,7 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[
353353
sym::rustc_dyn_incompatible_trait,
354354
sym::rustc_has_incoherent_inherent_impls,
355355
sym::rustc_non_const_trait_method,
356+
sym::rustc_panics_when_zero,
356357

357358
sym::rustc_canonical_symbol,
358359
sym::rustc_diagnostic_item,

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,6 +1576,9 @@ pub enum AttributeKind {
15761576
/// Represents `#[rustc_offload_kernel]`
15771577
RustcOffloadKernel,
15781578

1579+
/// Represents `#[rustc_panics_when_zero]` (used for linting).
1580+
RustcPanicsWhenZero,
1581+
15791582
/// Represents `#[rustc_paren_sugar]`.
15801583
RustcParenSugar,
15811584

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ impl AttributeKind {
175175
RustcObjcClass { .. } => No,
176176
RustcObjcSelector { .. } => No,
177177
RustcOffloadKernel => Yes,
178+
RustcPanicsWhenZero => Yes,
178179
RustcParenSugar => No,
179180
RustcPassByValue => Yes,
180181
RustcPassIndirectlyInNonRusticAbis(..) => No,

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
948948
| DefKind::AssocConst { .. }
949949
| DefKind::Macro(_)
950950
| DefKind::Field
951+
| DefKind::ConstParam
951952
| DefKind::Impl { .. } => true,
952953
// Encoding attrs for `Use` items allows `#[doc(hidden)]` on re-exports
953954
// to be read cross-crate, which is needed for diagnostic path selection
@@ -960,7 +961,6 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
960961
DefKind::Closure => true,
961962
DefKind::SyntheticCoroutineBody => false,
962963
DefKind::TyParam
963-
| DefKind::ConstParam
964964
| DefKind::Ctor(..)
965965
| DefKind::ExternCrate
966966
| DefKind::ForeignMod

compiler/rustc_mir_transform/src/diagnostics.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,14 @@ impl AssertLintKind {
125125
}
126126
}
127127

128+
#[derive(Diagnostic)]
129+
#[diag("this operation will panic at runtime")]
130+
pub(crate) struct ConstNIsZero {
131+
#[label("const parameter `{$const_param_name}` is zero")]
132+
pub const_param_span: Span,
133+
pub const_param_name: Symbol,
134+
}
135+
128136
#[derive(Diagnostic)]
129137
#[diag("call to inline assembly that may unwind")]
130138
pub(crate) struct AsmUnwindCall {

compiler/rustc_mir_transform/src/known_panics_lint.rs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,23 @@ use rustc_const_eval::interpret::{
1010
ImmTy, InterpCx, InterpResult, Projectable, Scalar, format_interp_error, interp_ok,
1111
};
1212
use rustc_data_structures::fx::FxHashSet;
13-
use rustc_hir::HirId;
1413
use rustc_hir::def::DefKind;
14+
use rustc_hir::{HirId, find_attr};
1515
use rustc_index::IndexVec;
1616
use rustc_index::bit_set::DenseBitSet;
1717
use rustc_middle::bug;
1818
use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor};
1919
use rustc_middle::mir::*;
2020
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
21-
use rustc_middle::ty::{self, ConstInt, ScalarInt, Ty, TyCtxt, TypeVisitableExt, Unnormalized};
21+
use rustc_middle::ty::{
22+
self, ConstInt, GenericArgKind, GenericParamDefKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
23+
Unnormalized,
24+
};
25+
use rustc_session::lint::builtin::UNCONDITIONAL_PANIC;
2226
use rustc_span::Span;
2327
use tracing::{debug, instrument, trace};
2428

25-
use crate::diagnostics::{AssertLint, AssertLintKind};
29+
use crate::diagnostics::{AssertLint, AssertLintKind, ConstNIsZero};
2630

2731
pub(super) struct KnownPanicsLint;
2832

@@ -768,6 +772,38 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
768772
}
769773
// We failed to evaluate the discriminant, fallback to visiting all successors.
770774
}
775+
TerminatorKind::Call { func, args: _, .. } => {
776+
if let Some((def_id, generic_args)) = func.const_fn_def() {
777+
for (index, arg) in generic_args.iter().enumerate() {
778+
if let GenericArgKind::Const(ct) = arg.kind() {
779+
let generics = self.tcx.generics_of(def_id);
780+
let param_def = generics.param_at(index, self.tcx);
781+
782+
if let GenericParamDefKind::Const { .. } = param_def.kind
783+
&& find_attr!(self.tcx, param_def.def_id, RustcPanicsWhenZero)
784+
&& let Some(0) = ct.try_to_target_usize(self.tcx)
785+
{
786+
// We managed to figure-out that the value of a
787+
// `#[rustc_panics_when_zero]` const-generic parameter is zero.
788+
//
789+
// Let's report it as an unconditional panic.
790+
let source_info = self.body.source_info(location);
791+
if let Some(lint_root) = self.lint_root(*source_info) {
792+
self.tcx.emit_node_span_lint(
793+
UNCONDITIONAL_PANIC,
794+
lint_root,
795+
source_info.span,
796+
ConstNIsZero {
797+
const_param_span: source_info.span,
798+
const_param_name: param_def.name,
799+
},
800+
);
801+
}
802+
}
803+
}
804+
}
805+
}
806+
}
771807
// None of these have Operands to const-propagate.
772808
TerminatorKind::Goto { .. }
773809
| TerminatorKind::UnwindResume
@@ -780,7 +816,6 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
780816
| TerminatorKind::CoroutineDrop
781817
| TerminatorKind::FalseEdge { .. }
782818
| TerminatorKind::FalseUnwind { .. }
783-
| TerminatorKind::Call { .. }
784819
| TerminatorKind::InlineAsm { .. } => {}
785820
}
786821

compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
375375
AttributeKind::RustcObjcClass { .. } => (),
376376
AttributeKind::RustcObjcSelector { .. } => (),
377377
AttributeKind::RustcOffloadKernel => (),
378+
AttributeKind::RustcPanicsWhenZero => (),
378379
AttributeKind::RustcParenSugar => (),
379380
AttributeKind::RustcPassByValue => (),
380381
AttributeKind::RustcPassIndirectlyInNonRusticAbis(..) => (),

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1835,6 +1835,7 @@ symbols! {
18351835
rustc_objc_selector,
18361836
rustc_offload_kernel,
18371837
rustc_on_unimplemented,
1838+
rustc_panics_when_zero,
18381839
rustc_paren_sugar,
18391840
rustc_partition_codegened,
18401841
rustc_partition_reused,

0 commit comments

Comments
 (0)