diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index bf5fc2562e4c9..4255f6b519cb0 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -28,7 +28,7 @@ use rustc_infer::traits::query::NoSolution; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TypeVisitableExt, Unnormalized}; +use rustc_middle::ty::{self, AdtKind, ConstKind, GenericArgsRef, Ty, TypeVisitableExt, Unnormalized}; use rustc_session::diagnostics::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::DesugaringKind; @@ -1739,17 +1739,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ); - let count_is_zero = { - if let Ok(count) = tcx.try_normalize_erasing_regions( - self.typing_env(self.param_env), - Unnormalized::new_wip(count), - ) { - count.try_to_value().and_then(|c| c.try_to_target_usize(tcx)) == Some(0) - } else { - false - } - }; - let uty = match expected { ExpectHasType(uty) => uty.builtin_index(), _ => None, @@ -1776,6 +1765,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // This is a problem, because it means if `CONST` is `const { panic!() }`, the side effect // of panic / failing compilation never happens. In such cases we need to ignore divergence // from the `CONST`, as otherwise we can end up executing code that was assumed unreachable. + let count_is_zero = match count.kind() { + // This is the exact check that mir building does + ConstKind::Value(v) => v.try_to_target_usize(tcx) == Some(0), + + // An infer const can get inferred to 0. + // + // We could check the expectation here to do ad-hoc inference, but that feels quite + // error prone and annoying. + ConstKind::Infer(_) => true, + + // While const generic params can be substituted with 0, mir building specifically + // checks for value 0 before monomorphization, so they (alongside aliases, etc) cannot + // trigger the bug. + ConstKind::Param(_) + | ConstKind::Placeholder(_) + | ConstKind::Alias(..) + | ConstKind::Error(_) + | ConstKind::Expr(_) => false, + + ConstKind::Bound(..) => bug!(), + }; + if count_is_zero && element.is_constant_for_zero_repeat() { self.diverges.set(old_diverges); } diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index 5da0323167fe6..955493a02d2e6 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -696,7 +696,7 @@ fn get_trait_item_order(cx: &LateContext<'_>, trait_impl: &rustc_hir::Impl<'_>) cx.tcx .associated_items(def_id) .in_definition_order() - .map(rustc_middle::ty::AssocItem::name) + .filter_map(rustc_middle::ty::AssocItem::opt_name) .collect() }) } diff --git a/src/tools/clippy/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs b/src/tools/clippy/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs index 53bc4e08abc5c..9263d0940a890 100644 --- a/src/tools/clippy/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs @@ -12,10 +12,11 @@ use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; declare_clippy_lint! { /// ### What it does - /// Checks for unsafe usage of `NonNull::new_unchecked(Box::into_raw(x))`, and suggests calling `NonNull::from_mut(Box::leak(x))` instead. + /// Checks for uses of `NonNull::new_unchecked(Box::into_raw(x))`. /// /// ### Why is this bad? - /// `NonNull::new_unchecked` is an unsafe function, which we don't need to call at all if we can instead use a mutable reference. + /// `NonNull::new_unchecked` is an unsafe function with a safe alternative when coming + /// from a `Box`. /// /// ### Example /// ```no_run @@ -27,12 +28,12 @@ declare_clippy_lint! { /// ```no_run /// use std::ptr::NonNull; /// let one = Box::new(1); - /// let ptr = NonNull::from_mut(Box::leak(one)); + /// let ptr = Box::into_non_null(one); /// ``` #[clippy::version = "1.98.0"] pub NONNULL_UNCHECKED_ON_BOX_PTR, complexity, - "using `NonNull::new_unchecked` with `Box::into_raw`, while `NonNull::from_mut` with `Box::leak` can be used instead" + "checks for uses of `NonNull::new_unchecked` with `Box::into_raw`" } impl_lint_pass!(NonnullUncheckedOnBoxPtr => [NONNULL_UNCHECKED_ON_BOX_PTR]); @@ -62,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for NonnullUncheckedOnBoxPtr { .opt_parent(cx) .opt_impl_ty(cx) .is_lang_item(cx, LangItem::OwnedBox) - && self.msrv.meets(cx, msrvs::BOX_LEAK) + && self.msrv.meets(cx, msrvs::BOX_INTO_NON_NULL) { let ctxt = expr.span.ctxt(); let span = match cx.tcx.parent_hir_node(expr.hir_id) { @@ -83,14 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for NonnullUncheckedOnBoxPtr { |diag| { let mut app = Applicability::MachineApplicable; let arg_name = snippet_with_context(cx, arg.span, ctxt, "_", &mut app).0; - - let sugg = if self.msrv.meets(cx, msrvs::NONNULL_FROM_MUT) { - format!("NonNull::from_mut(Box::leak({arg_name}))") - } else { - format!("NonNull::from(Box::leak({arg_name}))") - }; - - diag.span_suggestion(span, "try", sugg, app); + diag.span_suggestion(span, "try", format!("Box::into_non_null({arg_name})"), app); }, ); } diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index e724e1f25615b..1e0721fd66470 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_in_test; -use clippy_utils::source::{snippet, snippet_with_applicability}; +use clippy_utils::source::{SpanExt as _, snippet_with_applicability}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; @@ -127,19 +127,26 @@ impl LateLintPass<'_> for WildcardImports { return; } if let ItemKind::Use(tree) = &item.kind { - self.check_use_tree(cx, tree, item.hir_id(), item.owner_id.def_id); + self.check_use_tree(cx, tree, item.hir_id(), item.owner_id.def_id, item.span); } } } impl WildcardImports { - fn check_use_tree(&mut self, cx: &LateContext<'_>, tree: &UseTree<'_>, hir_id: HirId, def_id: LocalDefId) { + fn check_use_tree( + &mut self, + cx: &LateContext<'_>, + tree: &UseTree<'_>, + hir_id: HirId, + def_id: LocalDefId, + item_span: Span, + ) { match tree.kind { UseKind::Single(_) => return, UseKind::Glob => {}, UseKind::Nested { items } => { for (tree, id, def_id) in items { - self.check_use_tree(cx, tree, *id, *def_id); + self.check_use_tree(cx, tree, *id, *def_id, item_span); } return; }, @@ -164,14 +171,26 @@ impl WildcardImports { // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we // can just use the end of the item span let mut span = use_path.span; - if snippet(cx, span, "").ends_with(';') { - span = use_path.span.with_hi(span.hi() - BytePos(1)); + + if span.check_text(cx, |s| s.ends_with(';')) { + span = span.with_hi(span.hi() - BytePos(1)); + } + + let Ok(span_until_glob) = cx.sess().source_map().span_extend_while(span, |c| c != '*') else { + return; + }; + let span_with_glob = span_until_glob.with_hi(span_until_glob.hi() + BytePos(1)); + if !span_with_glob.check_text(cx, |s| s.ends_with('*')) { + return; } - while !snippet(cx, span, "").ends_with('*') { - span = use_path.span.with_hi(span.hi() + BytePos(1)); + + // For macros, the `*` might belong to unrelated code since `span_extend_while` doesn't know where the + // `use` item end, (e.g: a later `a * b`) + if !item_span.contains(span_with_glob) { + return; } - (span, false) + (span_with_glob, false) }; let mut imports: Vec<_> = used_imports.iter().map(ToString::to_string).collect(); diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index 5f30692a677af..4f1d3fa00b08d 100644 --- a/src/tools/clippy/clippy_utils/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -25,6 +25,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,99,0 { BOX_INTO_NON_NULL } 1,98,0 { MAP_OR_DEFAULT } 1,97,0 { ISOLATE_LOWEST_ONE, BIT_WIDTH } 1,94,0 { EULER_GAMMA, GOLDEN_RATIO, MUL_ADD_CONST } diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order.rs index 03e0fbfa31d20..57408d0f5aadf 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order.rs +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order.rs @@ -77,6 +77,21 @@ impl WithDefault2 for FullImpl { fn c() {} } +// Tests return position impl trait in trait (RPITIT). +trait Rpitit { + async fn a(); + fn b(); + fn c() -> impl Sized; +} + +struct FullImpl2; + +impl Rpitit for FullImpl2 { + async fn a() {} + fn b() {} + fn c() -> impl Sized {} +} + // Tests `const` in trait. trait ConstTrait { const A: bool; diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.rs index ff96d0669e119..21f6c82e0decb 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.rs +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.rs @@ -103,4 +103,30 @@ impl ConstTrait2 for SkipMiddleFailed2 { fn method() {} } +// Tests return position impl trait in trait (RPITIT) failed by invalid trait definition order (e.g. +// Not in alphabetical order). +trait Rpitit { + async fn a(); + fn b(); + fn c() -> impl Sized; +} + +struct FullImplFailed4; + +impl Rpitit for FullImplFailed4 { + fn b() {} + fn c() -> impl Sized {} + async fn a() {} + //~^ arbitrary_source_item_ordering +} + +struct FullImplFailed5; + +impl Rpitit for FullImplFailed5 { + fn b() {} + async fn a() {} + //~^ arbitrary_source_item_ordering + fn c() -> impl Sized {} +} + fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.stderr index b0b8c9e483889..848fd8250e54f 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.stderr +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.stderr @@ -87,5 +87,29 @@ note: should be placed before `C` LL | const C: bool = true; | ^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: incorrect ordering of impl items (should follow the trait definition order) + --> tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.rs:119:5 + | +LL | async fn a() {} + | ^^^^^^^^^^^^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.rs:118:5 + | +LL | fn c() -> impl Sized {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: incorrect ordering of impl items (should follow the trait definition order) + --> tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.rs:127:5 + | +LL | async fn a() {} + | ^^^^^^^^^^^^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/alphabetical_or_trait_item_order/alphabetical_or_trait_item_order_failed.rs:126:5 + | +LL | fn b() {} + | ^^^^^^ + +error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order.rs index 31554937e9dd7..3257d540debac 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order.rs +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order.rs @@ -91,4 +91,19 @@ impl ConstTrait2 for SkipImpl { fn method() {} } +// Tests return position impl trait in trait (RPITIT). +trait Rpitit { + async fn a(); + fn b(); + fn c() -> impl Sized; +} + +struct FullImpl4; + +impl Rpitit for FullImpl4 { + async fn a() {} + fn b() {} + fn c() -> impl Sized {} +} + fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.rs b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.rs index 510df33de322f..2b044ebec3bc8 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.rs +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.rs @@ -102,4 +102,37 @@ impl SkipConstTrait for WrongInBothOrder4 { fn method() {} } +// Tests return position impl trait in trait (RPITIT) failed by invalid trait definition order (e.g. +// Not in alphabetical order); its own ordering check is not what this test is about. +#[allow(clippy::arbitrary_source_item_ordering)] +trait Rpitit { + async fn a(); + fn c() -> impl Sized; + fn b(); +} + +struct NotInTraitOrder; + +impl Rpitit for NotInTraitOrder { + async fn a() {} + fn b() {} + fn c() -> impl Sized {} + //~^ arbitrary_source_item_ordering +} + +trait Rpitit2 { + async fn a(); + fn b(); + fn c() -> impl Sized; +} + +struct WrongInBothOrder5; + +impl Rpitit2 for WrongInBothOrder5 { + async fn a() {} + fn c() -> impl Sized {} + fn b() {} + //~^ arbitrary_source_item_ordering +} + fn main() {} diff --git a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.trait_def.stderr b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.trait_def.stderr index c70c3c9e7978f..1ed05a88ebea5 100644 --- a/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.trait_def.stderr +++ b/src/tools/clippy/tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.trait_def.stderr @@ -75,5 +75,29 @@ note: should be placed before `C` LL | const C: bool = true; | ^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: incorrect ordering of impl items (should follow the trait definition order) + --> tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.rs:119:5 + | +LL | fn c() -> impl Sized {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: should be placed before `b` + --> tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.rs:118:5 + | +LL | fn b() {} + | ^^^^^^ + +error: incorrect ordering of impl items (should follow the trait definition order) + --> tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.rs:134:5 + | +LL | fn b() {} + | ^^^^^^ + | +note: should be placed before `c` + --> tests/ui-toml/arbitrary_source_item_ordering/trait_definition_order/trait_definition_order_failed.rs:133:5 + | +LL | fn c() -> impl Sized {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors diff --git a/src/tools/clippy/tests/ui/crashes/ice-17799.rs b/src/tools/clippy/tests/ui/crashes/ice-17799.rs new file mode 100644 index 0000000000000..38b714ea52a4b --- /dev/null +++ b/src/tools/clippy/tests/ui/crashes/ice-17799.rs @@ -0,0 +1,11 @@ +//@check-pass +#![warn(clippy::wildcard_imports)] + +macro_rules! glob_import { + ($p:path) => { + use $p::*; + fn __glob_used(_e: Error) {} + }; +} + +glob_import!(std::io); diff --git a/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.fixed b/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.fixed index 746bd29764dc1..1cdeb942ecadc 100644 --- a/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.fixed +++ b/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.fixed @@ -32,78 +32,78 @@ unsafe fn unsafe_identity(x: T) -> T { fn lint() { fn basic() { let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(identity(one))); + let _ = Box::into_non_null(identity(one)); } fn qualifiers() { let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); { use Box as Box2; use NonNull as NonNull2; let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); } { type Box2 = Box; type NonNull2 = NonNull; let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); } } fn macros() { let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = identity!(NonNull::from_mut(Box::leak(one))); + let _ = identity!(Box::into_non_null(one)); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(weird!(one))); + let _ = Box::into_non_null(weird!(one)); } fn keep_unsafe_block() { let one = Box::new(1); let _ = unsafe { - NonNull::from_mut(Box::leak(unsafe_identity(one))) + Box::into_non_null(unsafe_identity(one)) //~^ nonnull_unchecked_on_box_ptr }; let one = Box::new(1); let _ = unsafe { - identity(NonNull::from_mut(Box::leak(one))) + identity(Box::into_non_null(one)) //~^ nonnull_unchecked_on_box_ptr }; let one = Box::new(1); let _ = unsafe { - unsafe_identity(NonNull::from_mut(Box::leak(one))) + unsafe_identity(Box::into_non_null(one)) //~^ nonnull_unchecked_on_box_ptr }; let _ = unsafe { - NonNull::from_mut(Box::leak(Box::new(std::num::NonZeroI32::new_unchecked(1)))) + Box::into_non_null(Box::new(std::num::NonZeroI32::new_unchecked(1))) //~^ nonnull_unchecked_on_box_ptr }; let _ = unsafe { let one = Box::new(1); - NonNull::from_mut(Box::leak(one)) + Box::into_non_null(one) //~^ nonnull_unchecked_on_box_ptr }; } @@ -135,22 +135,16 @@ fn no_lint() { } } -#[clippy::msrv = "1.25"] -fn msrv_1_25() { +#[clippy::msrv = "1.98"] +fn msrv_1_98() { let one = Box::new(1); let _ = unsafe { NonNull::new_unchecked(Box::into_raw(one)) }; } -#[clippy::msrv = "1.26"] -fn msrv_1_26() { - let one = Box::new(1); - let _ = NonNull::from(Box::leak(one)); -} - -#[clippy::msrv = "1.89"] -fn msrv_1_89() { +#[clippy::msrv = "1.99"] +fn msrv_1_99() { let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); } fn main() {} diff --git a/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.rs b/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.rs index 2acc5c9270c88..a78a953ff7f38 100644 --- a/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.rs +++ b/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.rs @@ -168,23 +168,14 @@ fn no_lint() { } } -#[clippy::msrv = "1.25"] -fn msrv_1_25() { +#[clippy::msrv = "1.98"] +fn msrv_1_98() { let one = Box::new(1); let _ = unsafe { NonNull::new_unchecked(Box::into_raw(one)) }; } -#[clippy::msrv = "1.26"] -fn msrv_1_26() { - let one = Box::new(1); - let _ = unsafe { - //~^ nonnull_unchecked_on_box_ptr - NonNull::new_unchecked(Box::into_raw(one)) - }; -} - -#[clippy::msrv = "1.89"] -fn msrv_1_89() { +#[clippy::msrv = "1.99"] +fn msrv_1_99() { let one = Box::new(1); let _ = unsafe { //~^ nonnull_unchecked_on_box_ptr diff --git a/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.stderr b/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.stderr index 8d26914cde7b0..9e452143bfa53 100644 --- a/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.stderr +++ b/src/tools/clippy/tests/ui/nonnull_unchecked_on_box_ptr.stderr @@ -6,7 +6,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(one)) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` | = note: `-D clippy::nonnull-unchecked-on-box-ptr` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::nonnull_unchecked_on_box_ptr)]` @@ -19,7 +19,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(identity(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(identity(one)))` + | |_________^ help: try: `Box::into_non_null(identity(one))` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:49:17 @@ -29,7 +29,7 @@ LL | let _ = unsafe { LL | | LL | | std::ptr::NonNull::new_unchecked(std::boxed::Box::into_raw(one)) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:58:21 @@ -39,7 +39,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull2::new_unchecked(Box2::into_raw(one)) LL | | }; - | |_____________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_____________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:68:21 @@ -49,7 +49,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull2::new_unchecked(Box2::into_raw(one)) LL | | }; - | |_____________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_____________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:77:17 @@ -59,7 +59,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(identity!(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:83:27 @@ -69,7 +69,7 @@ LL | let _ = identity!(unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(one)) LL | | }); - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:89:17 @@ -79,7 +79,7 @@ LL | let _ = unsafe { LL | | LL | | identity!(NonNull::new_unchecked(Box::into_raw(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:95:17 @@ -89,7 +89,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(identity!(Box::into_raw(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:101:17 @@ -99,7 +99,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(identity!(Box::into_raw(identity!(one)))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:107:17 @@ -109,37 +109,37 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(weird!(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(weird!(one)))` + | |_________^ help: try: `Box::into_non_null(weird!(one))` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:116:13 | LL | NonNull::new_unchecked(Box::into_raw(unsafe_identity(one))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(unsafe_identity(one)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(unsafe_identity(one))` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:122:22 | LL | identity(NonNull::new_unchecked(Box::into_raw(one))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(one))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:128:29 | LL | unsafe_identity(NonNull::new_unchecked(Box::into_raw(one))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(one))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:133:13 | LL | NonNull::new_unchecked(Box::into_raw(Box::new(std::num::NonZeroI32::new_unchecked(1)))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(Box::new(std::num::NonZeroI32::new_unchecked(1))))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(Box::new(std::num::NonZeroI32::new_unchecked(1)))` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:139:13 | LL | NonNull::new_unchecked(Box::into_raw(one)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(one))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:180:13 @@ -149,17 +149,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(one)) LL | | }; - | |_____^ help: try: `NonNull::from(Box::leak(one))` + | |_____^ help: try: `Box::into_non_null(one)` -error: use of `NonNull::new_unchecked` with `Box::into_raw` - --> tests/ui/nonnull_unchecked_on_box_ptr.rs:189:13 - | -LL | let _ = unsafe { - | _____________^ -LL | | -LL | | NonNull::new_unchecked(Box::into_raw(one)) -LL | | }; - | |_____^ help: try: `NonNull::from_mut(Box::leak(one))` - -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed index a2854d3f1b0fe..7ea501413d299 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed @@ -297,3 +297,19 @@ mod super_imports { } } } + +mod issue_17799 { + // see `https://github.com/rust-lang/rust-clippy/pull/17828#discussion_r4169531242` + macro_rules! glob_import { + ($p:path) => { + use $p::*; + fn __glob_used(_e: Error) {} + }; + } + + glob_import!(std::io); + + fn lol() -> usize { + 2 * 3 + } +} diff --git a/src/tools/clippy/tests/ui/wildcard_imports.rs b/src/tools/clippy/tests/ui/wildcard_imports.rs index 226f26412cc1b..5632ee8fa1998 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.rs +++ b/src/tools/clippy/tests/ui/wildcard_imports.rs @@ -299,3 +299,19 @@ mod super_imports { } } } + +mod issue_17799 { + // see `https://github.com/rust-lang/rust-clippy/pull/17828#discussion_r4169531242` + macro_rules! glob_import { + ($p:path) => { + use $p::*; + fn __glob_used(_e: Error) {} + }; + } + + glob_import!(std::io); + + fn lol() -> usize { + 2 * 3 + } +} diff --git a/tests/ui/repeat-expr/zero_assoc_diverging_consts.rs b/tests/ui/repeat-expr/zero_assoc_diverging_consts.rs new file mode 100644 index 0000000000000..fc57de8ed43bc --- /dev/null +++ b/tests/ui/repeat-expr/zero_assoc_diverging_consts.rs @@ -0,0 +1,29 @@ +// Check that repeating a diverging constant 0 times doesn't lead to unsoundness. +// +// This specific test checks that using an associated const that evaluates to 0, rather than just +// plain literal 0, doesn't allow the unsoundness either. +// +// Issue: +// +//@ build-fail +#![feature(generic_const_exprs)] + +trait Trait { + const ZERO: usize; +} + +impl Trait for () { + const ZERO: usize = 0; +} + +fn ex_nihilo() -> u32 +where + [(); T::ZERO]:, +{ + [const { panic!() } as !; T::ZERO]; + //~^ error: evaluation panicked: explicit panic +} + +fn main() { + dbg!(ex_nihilo::<()>()); +} diff --git a/tests/ui/repeat-expr/zero_assoc_diverging_consts.stderr b/tests/ui/repeat-expr/zero_assoc_diverging_consts.stderr new file mode 100644 index 0000000000000..a9d946394e7ea --- /dev/null +++ b/tests/ui/repeat-expr/zero_assoc_diverging_consts.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation panicked: explicit panic + --> $DIR/zero_assoc_diverging_consts.rs:23:14 + | +LL | [const { panic!() } as !; T::ZERO]; + | ^^^^^^^^ evaluation of `ex_nihilo::<()>::{constant#1}` failed here + +note: erroneous constant encountered + --> $DIR/zero_assoc_diverging_consts.rs:23:6 + | +LL | [const { panic!() } as !; T::ZERO]; + | ^^^^^^^^^^^^^^^^^^ + +note: the above error was encountered while instantiating `fn ex_nihilo::<()>` + --> $DIR/zero_assoc_diverging_consts.rs:28:10 + | +LL | dbg!(ex_nihilo::<()>()); + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/repeat-expr/zero_diverging_type_relative_consts_consts.rs b/tests/ui/repeat-expr/zero_diverging_type_relative_consts.rs similarity index 100% rename from tests/ui/repeat-expr/zero_diverging_type_relative_consts_consts.rs rename to tests/ui/repeat-expr/zero_diverging_type_relative_consts.rs diff --git a/tests/ui/repeat-expr/zero_diverging_type_relative_consts_consts.stderr b/tests/ui/repeat-expr/zero_diverging_type_relative_consts.stderr similarity index 83% rename from tests/ui/repeat-expr/zero_diverging_type_relative_consts_consts.stderr rename to tests/ui/repeat-expr/zero_diverging_type_relative_consts.stderr index cddb6fb897ef4..0311068803300 100644 --- a/tests/ui/repeat-expr/zero_diverging_type_relative_consts_consts.stderr +++ b/tests/ui/repeat-expr/zero_diverging_type_relative_consts.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/zero_diverging_type_relative_consts_consts.rs:14:19 + --> $DIR/zero_diverging_type_relative_consts.rs:14:19 | LL | fn ex_nihilo() -> u32 { | --------- ^^^ expected `u32`, found `()` diff --git a/tests/ui/repeat-expr/zero_infer_diverging_consts.rs b/tests/ui/repeat-expr/zero_infer_diverging_consts.rs new file mode 100644 index 0000000000000..4e174fbf2a7b4 --- /dev/null +++ b/tests/ui/repeat-expr/zero_infer_diverging_consts.rs @@ -0,0 +1,20 @@ +// Check that repeating a diverging constant 0 times (inferred via `_`) +// doesn't lead to unsoundness. +// +// Issue: + +fn ex_nihilo() -> u32 { + //~^ error: mismatched types + let _: [_; 0] = [const { panic!() } as !; _]; +} + +fn ex_nihilo2() -> u32 { + //~^ error: mismatched types + let a = [const { panic!() } as !; _]; + let _: [_; 0] = a; +} + +fn main() { + dbg!(ex_nihilo()); + dbg!(ex_nihilo2()); +} diff --git a/tests/ui/repeat-expr/zero_infer_diverging_consts.stderr b/tests/ui/repeat-expr/zero_infer_diverging_consts.stderr new file mode 100644 index 0000000000000..db55732073786 --- /dev/null +++ b/tests/ui/repeat-expr/zero_infer_diverging_consts.stderr @@ -0,0 +1,19 @@ +error[E0308]: mismatched types + --> $DIR/zero_infer_diverging_consts.rs:6:19 + | +LL | fn ex_nihilo() -> u32 { + | --------- ^^^ expected `u32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error[E0308]: mismatched types + --> $DIR/zero_infer_diverging_consts.rs:11:20 + | +LL | fn ex_nihilo2() -> u32 { + | ---------- ^^^ expected `u32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/repeat-expr/zero_param_diverging_consts.rs b/tests/ui/repeat-expr/zero_param_diverging_consts.rs new file mode 100644 index 0000000000000..cc0c11ba6a033 --- /dev/null +++ b/tests/ui/repeat-expr/zero_param_diverging_consts.rs @@ -0,0 +1,17 @@ +// Check that repeating a diverging constant 0 times doesn't lead to unsoundness. +// +// This specific test checks that using a generic const argument that is substited with 0, rather +// than just plain literal 0, doesn't allow the unsoundness either. +// +// Issue: +// +//@ build-fail + +fn ex_nihilo() -> u32 { + [const { panic!() } as !; N]; + //~^ error: evaluation panicked: explicit panic +} + +fn main() { + dbg!(ex_nihilo::<0>()); +} diff --git a/tests/ui/repeat-expr/zero_param_diverging_consts.stderr b/tests/ui/repeat-expr/zero_param_diverging_consts.stderr new file mode 100644 index 0000000000000..98697fe317906 --- /dev/null +++ b/tests/ui/repeat-expr/zero_param_diverging_consts.stderr @@ -0,0 +1,21 @@ +error[E0080]: evaluation panicked: explicit panic + --> $DIR/zero_param_diverging_consts.rs:11:14 + | +LL | [const { panic!() } as !; N]; + | ^^^^^^^^ evaluation of `ex_nihilo::<0>::{constant#0}` failed here + +note: erroneous constant encountered + --> $DIR/zero_param_diverging_consts.rs:11:6 + | +LL | [const { panic!() } as !; N]; + | ^^^^^^^^^^^^^^^^^^ + +note: the above error was encountered while instantiating `fn ex_nihilo::<0>` + --> $DIR/zero_param_diverging_consts.rs:16:10 + | +LL | dbg!(ex_nihilo::<0>()); + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`.