Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 23 additions & 12 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand All @@ -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);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
}
20 changes: 7 additions & 13 deletions src/tools/clippy/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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]);
Expand Down Expand Up @@ -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) {
Expand All @@ -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);
},
);
}
Expand Down
37 changes: 28 additions & 9 deletions src/tools/clippy/clippy_lints/src/wildcard_imports.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand Down Expand Up @@ -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;
},
Expand All @@ -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();
Expand Down
1 change: 1 addition & 0 deletions src/tools/clippy/clippy_utils/src/msrvs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Original file line number Diff line number Diff line change
Expand Up @@ -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

11 changes: 11 additions & 0 deletions src/tools/clippy/tests/ui/crashes/ice-17799.rs
Original file line number Diff line number Diff line change
@@ -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);
Loading
Loading