Skip to content

Commit

Permalink
Merge branch 'master' into redundant_local
Browse files Browse the repository at this point in the history
  • Loading branch information
max-niederman authored Jun 5, 2023
2 parents 7bd35cb + eacd095 commit a057cdf
Show file tree
Hide file tree
Showing 31 changed files with 1,832 additions and 51 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4641,6 +4641,7 @@ Released 2018-09-13
[`await_holding_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_lock
[`await_holding_refcell_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#await_holding_refcell_ref
[`bad_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#bad_bit_mask
[`big_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#big_endian_bytes
[`bind_instead_of_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#bind_instead_of_map
[`blacklisted_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#blacklisted_name
[`blanket_clippy_restriction_lints`]: https://rust-lang.github.io/rust-clippy/master/index.html#blanket_clippy_restriction_lints
Expand Down Expand Up @@ -4811,6 +4812,7 @@ Released 2018-09-13
[`get_first`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_first
[`get_last_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_last_with_len
[`get_unwrap`]: https://rust-lang.github.io/rust-clippy/master/index.html#get_unwrap
[`host_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#host_endian_bytes
[`identity_conversion`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_conversion
[`identity_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#identity_op
[`if_let_mutex`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_let_mutex
Expand Down Expand Up @@ -4892,6 +4894,7 @@ Released 2018-09-13
[`let_with_type_underscore`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_with_type_underscore
[`lines_filter_map_ok`]: https://rust-lang.github.io/rust-clippy/master/index.html#lines_filter_map_ok
[`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist
[`little_endian_bytes`]: https://rust-lang.github.io/rust-clippy/master/index.html#little_endian_bytes
[`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug
[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
[`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports
Expand Down
3 changes: 2 additions & 1 deletion clippy_lints/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = { version = "1.0", optional = true }
tempfile = { version = "3.3.0", optional = true }
toml = "0.7.3"
regex = { version = "1.5", optional = true }
unicode-normalization = "0.1"
unicode-script = { version = "0.5", default-features = false }
semver = "1.0"
Expand All @@ -31,7 +32,7 @@ url = "2.2"
[features]
deny-warnings = ["clippy_utils/deny-warnings"]
# build clippy with internal lints enabled, off by default
internal = ["clippy_utils/internal", "serde_json", "tempfile"]
internal = ["clippy_utils/internal", "serde_json", "tempfile", "regex"]

[package.metadata.rust-analyzer]
# This crate uses #[feature(rustc_private)]
Expand Down
7 changes: 4 additions & 3 deletions clippy_lints/src/allow_attributes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use ast::AttrStyle;
use clippy_utils::diagnostics::span_lint_and_sugg;
use ast::{AttrStyle, Attribute};
use clippy_utils::{diagnostics::span_lint_and_sugg, is_from_proc_macro};
use rustc_ast as ast;
use rustc_errors::Applicability;
use rustc_lint::{LateContext, LateLintPass, LintContext};
Expand Down Expand Up @@ -50,13 +50,14 @@ declare_lint_pass!(AllowAttribute => [ALLOW_ATTRIBUTES]);

impl LateLintPass<'_> for AllowAttribute {
// Separate each crate's features.
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
fn check_attribute<'cx>(&mut self, cx: &LateContext<'cx>, attr: &'cx Attribute) {
if_chain! {
if !in_external_macro(cx.sess(), attr.span);
if cx.tcx.features().lint_reasons;
if let AttrStyle::Outer = attr.style;
if let Some(ident) = attr.ident();
if ident.name == rustc_span::symbol::sym::allow;
if !is_from_proc_macro(cx, &attr);
then {
span_lint_and_sugg(
cx,
Expand Down
9 changes: 6 additions & 3 deletions clippy_lints/src/attrs.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
//! checks for attributes
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
use clippy_utils::macros::{is_panic, macro_backtrace};
use clippy_utils::msrvs::{self, Msrv};
use clippy_utils::source::{first_line_of_span, is_present_in_source, snippet_opt, without_block_comments};
use clippy_utils::{
diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then},
is_from_proc_macro,
};
use if_chain::if_chain;
use rustc_ast::{AttrKind, AttrStyle, Attribute, LitKind, MetaItemKind, MetaItemLit, NestedMetaItem};
use rustc_errors::Applicability;
Expand Down Expand Up @@ -566,7 +569,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_>, name: Symbol, items: &[NestedMe
}
}

fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem], attr: &'_ Attribute) {
fn check_lint_reason<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[NestedMetaItem], attr: &'cx Attribute) {
// Check for the feature
if !cx.tcx.features().lint_reasons {
return;
Expand All @@ -581,7 +584,7 @@ fn check_lint_reason(cx: &LateContext<'_>, name: Symbol, items: &[NestedMetaItem
}

// Check if the attribute is in an external macro and therefore out of the developer's control
if in_external_macro(cx.sess(), attr.span) {
if in_external_macro(cx.sess(), attr.span) || is_from_proc_macro(cx, &attr) {
return;
}

Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/casts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ declare_clippy_lint! {

declare_clippy_lint! {
/// ### What it does
/// Check for the usage of `as _` conversion using inferred type.
/// Checks for the usage of `as _` conversion using inferred type.
///
/// ### Why is this bad?
/// The conversion might include lossy conversion and dangerous cast that might go
Expand Down
5 changes: 5 additions & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// Manual edits will be overwritten.

pub(crate) static LINTS: &[&crate::LintInfo] = &[
#[cfg(feature = "internal")]
crate::utils::internal_lints::almost_standard_lint_formulation::ALMOST_STANDARD_LINT_FORMULATION_INFO,
#[cfg(feature = "internal")]
crate::utils::internal_lints::clippy_lints_internal::CLIPPY_LINTS_INTERNAL_INFO,
#[cfg(feature = "internal")]
Expand Down Expand Up @@ -143,6 +145,9 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::empty_drop::EMPTY_DROP_INFO,
crate::empty_enum::EMPTY_ENUM_INFO,
crate::empty_structs_with_brackets::EMPTY_STRUCTS_WITH_BRACKETS_INFO,
crate::endian_bytes::BIG_ENDIAN_BYTES_INFO,
crate::endian_bytes::HOST_ENDIAN_BYTES_INFO,
crate::endian_bytes::LITTLE_ENDIAN_BYTES_INFO,
crate::entry::MAP_ENTRY_INFO,
crate::enum_clike::ENUM_CLIKE_UNPORTABLE_VARIANT_INFO,
crate::enum_variants::ENUM_VARIANT_NAMES_INFO,
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/default_constructed_unit_structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};

declare_clippy_lint! {
/// ### What it does
/// Check for construction on unit struct using `default`.
/// Checks for construction on unit struct using `default`.
///
/// ### Why is this bad?
/// This adds code complexity and an unnecessary function call.
Expand Down
21 changes: 16 additions & 5 deletions clippy_lints/src/dereference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,11 @@ declare_clippy_lint! {
/// let b = &*a;
/// ```
///
/// This lint excludes:
/// This lint excludes all of:
/// ```rust,ignore
/// let _ = d.unwrap().deref();
/// let _ = Foo::deref(&foo);
/// let _ = <Foo as Deref>::deref(&foo);
/// ```
#[clippy::version = "1.44.0"]
pub EXPLICIT_DEREF_METHODS,
Expand Down Expand Up @@ -1480,7 +1482,7 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
target_mut,
} => {
let mut app = Applicability::MachineApplicable;
let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
let (expr_str, _expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app);
let ty = cx.typeck_results().expr_ty(expr);
let (_, ref_count) = peel_mid_ty_refs(ty);
let deref_str = if ty_changed_count >= ref_count && ref_count != 0 {
Expand All @@ -1503,11 +1505,20 @@ fn report<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, state: State, data
"&"
};

let expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
format!("({expr_str})")
// expr_str (the suggestion) is never shown if is_final_ufcs is true, since it's
// `expr.kind == ExprKind::Call`. Therefore, this is, afaik, always unnecessary.
/*
expr_str = if !expr_is_macro_call && is_final_ufcs && expr.precedence().order() < PREC_PREFIX {
Cow::Owned(format!("({expr_str})"))
} else {
expr_str.into_owned()
expr_str
};
*/

// Fix #10850, do not lint if it's `Foo::deref` instead of `foo.deref()`.
if is_final_ufcs {
return;
}

span_lint_and_sugg(
cx,
Expand Down
216 changes: 216 additions & 0 deletions clippy_lints/src/endian_bytes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
use crate::Lint;
use clippy_utils::{diagnostics::span_lint_and_then, is_lint_allowed};
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::{lint::in_external_macro, ty::Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::Symbol;
use std::borrow::Cow;

declare_clippy_lint! {
/// ### What it does
/// Checks for the usage of the `to_ne_bytes` method and/or the function `from_ne_bytes`.
///
/// ### Why is this bad?
/// It's not, but some may prefer to specify the target endianness explicitly.
///
/// ### Example
/// ```rust,ignore
/// let _x = 2i32.to_ne_bytes();
/// let _y = 2i64.to_ne_bytes();
/// ```
#[clippy::version = "1.71.0"]
pub HOST_ENDIAN_BYTES,
restriction,
"disallows usage of the `to_ne_bytes` method"
}

declare_clippy_lint! {
/// ### What it does
/// Checks for the usage of the `to_le_bytes` method and/or the function `from_le_bytes`.
///
/// ### Why is this bad?
/// It's not, but some may wish to lint usage of this method, either to suggest using the host
/// endianness or big endian.
///
/// ### Example
/// ```rust,ignore
/// let _x = 2i32.to_le_bytes();
/// let _y = 2i64.to_le_bytes();
/// ```
#[clippy::version = "1.71.0"]
pub LITTLE_ENDIAN_BYTES,
restriction,
"disallows usage of the `to_le_bytes` method"
}

declare_clippy_lint! {
/// ### What it does
/// Checks for the usage of the `to_be_bytes` method and/or the function `from_be_bytes`.
///
/// ### Why is this bad?
/// It's not, but some may wish to lint usage of this method, either to suggest using the host
/// endianness or little endian.
///
/// ### Example
/// ```rust,ignore
/// let _x = 2i32.to_be_bytes();
/// let _y = 2i64.to_be_bytes();
/// ```
#[clippy::version = "1.71.0"]
pub BIG_ENDIAN_BYTES,
restriction,
"disallows usage of the `to_be_bytes` method"
}

declare_lint_pass!(EndianBytes => [HOST_ENDIAN_BYTES, LITTLE_ENDIAN_BYTES, BIG_ENDIAN_BYTES]);

const HOST_NAMES: [&str; 2] = ["from_ne_bytes", "to_ne_bytes"];
const LITTLE_NAMES: [&str; 2] = ["from_le_bytes", "to_le_bytes"];
const BIG_NAMES: [&str; 2] = ["from_be_bytes", "to_be_bytes"];

#[derive(Clone, Debug)]
enum LintKind {
Host,
Little,
Big,
}

#[derive(Clone, Copy, PartialEq)]
enum Prefix {
From,
To,
}

impl LintKind {
fn allowed(&self, cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
is_lint_allowed(cx, self.as_lint(), expr.hir_id)
}

fn as_lint(&self) -> &'static Lint {
match self {
LintKind::Host => HOST_ENDIAN_BYTES,
LintKind::Little => LITTLE_ENDIAN_BYTES,
LintKind::Big => BIG_ENDIAN_BYTES,
}
}

fn as_name(&self, prefix: Prefix) -> &str {
let index = usize::from(prefix == Prefix::To);

match self {
LintKind::Host => HOST_NAMES[index],
LintKind::Little => LITTLE_NAMES[index],
LintKind::Big => BIG_NAMES[index],
}
}
}

impl LateLintPass<'_> for EndianBytes {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
if in_external_macro(cx.sess(), expr.span) {
return;
}

if_chain! {
if let ExprKind::MethodCall(method_name, receiver, args, ..) = expr.kind;
if args.is_empty();
let ty = cx.typeck_results().expr_ty(receiver);
if ty.is_primitive_ty();
if maybe_lint_endian_bytes(cx, expr, Prefix::To, method_name.ident.name, ty);
then {
return;
}
}

if_chain! {
if let ExprKind::Call(function, ..) = expr.kind;
if let ExprKind::Path(qpath) = function.kind;
if let Some(def_id) = cx.qpath_res(&qpath, function.hir_id).opt_def_id();
if let Some(function_name) = cx.get_def_path(def_id).last();
let ty = cx.typeck_results().expr_ty(expr);
if ty.is_primitive_ty();
then {
maybe_lint_endian_bytes(cx, expr, Prefix::From, *function_name, ty);
}
}
}
}

fn maybe_lint_endian_bytes(cx: &LateContext<'_>, expr: &Expr<'_>, prefix: Prefix, name: Symbol, ty: Ty<'_>) -> bool {
let ne = LintKind::Host.as_name(prefix);
let le = LintKind::Little.as_name(prefix);
let be = LintKind::Big.as_name(prefix);

let (lint, other_lints) = match name.as_str() {
name if name == ne => ((&LintKind::Host), [(&LintKind::Little), (&LintKind::Big)]),
name if name == le => ((&LintKind::Little), [(&LintKind::Host), (&LintKind::Big)]),
name if name == be => ((&LintKind::Big), [(&LintKind::Host), (&LintKind::Little)]),
_ => return false,
};

let mut help = None;

'build_help: {
// all lints disallowed, don't give help here
if [&[lint], other_lints.as_slice()]
.concat()
.iter()
.all(|lint| !lint.allowed(cx, expr))
{
break 'build_help;
}

// ne_bytes and all other lints allowed
if lint.as_name(prefix) == ne && other_lints.iter().all(|lint| lint.allowed(cx, expr)) {
help = Some(Cow::Borrowed("specify the desired endianness explicitly"));
break 'build_help;
}

// le_bytes where ne_bytes allowed but be_bytes is not, or le_bytes where ne_bytes allowed but
// le_bytes is not
if (lint.as_name(prefix) == le || lint.as_name(prefix) == be) && LintKind::Host.allowed(cx, expr) {
help = Some(Cow::Borrowed("use the native endianness instead"));
break 'build_help;
}

let allowed_lints = other_lints.iter().filter(|lint| lint.allowed(cx, expr));
let len = allowed_lints.clone().count();

let mut help_str = "use ".to_owned();

for (i, lint) in allowed_lints.enumerate() {
let only_one = len == 1;
if !only_one {
help_str.push_str("either of ");
}

help_str.push_str(&format!("`{ty}::{}` ", lint.as_name(prefix)));

if i != len && !only_one {
help_str.push_str("or ");
}
}

help = Some(Cow::Owned(help_str + "instead"));
}

span_lint_and_then(
cx,
lint.as_lint(),
expr.span,
&format!(
"usage of the {}`{ty}::{}`{}",
if prefix == Prefix::From { "function " } else { "" },
lint.as_name(prefix),
if prefix == Prefix::To { " method" } else { "" },
),
move |diag| {
if let Some(help) = help {
diag.help(help);
}
},
);

true
}
Loading

0 comments on commit a057cdf

Please sign in to comment.