Source code for crates.io
The Rust Programming Language Blog
The Rust Programming Language
The Rust package manager
Date and time library for Rust
the compiler
A fuzzer for the MiniJava language
Some boilerplate code used across the @actions-rs Actions
Source code for crates.io
Pull request review commentrust-lang/rust-clippy
Add lint 'ref_option_ref' #1377
+use crate::utils::{last_path_segment, snippet, span_lint_and_sugg};+use rustc_hir::{GenericArg, Mutability, Ty, TyKind};+use rustc_lint::{LateContext, LateLintPass};+use rustc_session::{declare_lint_pass, declare_tool_lint};++use if_chain::if_chain;+use rustc_errors::Applicability;++declare_clippy_lint! {+ /// **What it does:** Checks for usage of `&Option<&T>`.+ ///+ /// **Why is this bad?** Since `&` is Copy, it's useless to have a+ /// reference on `Option<&T>`.+ ///+ /// **Known problems:** It may be irrevelent to use this lint on+ /// public API code as it will make a breaking change to apply it.+ ///+ /// **Example:**+ ///+ /// ```rust,ignore+ /// let x: &Option<&u32> = &Some(&0u32);+ /// ```+ /// Use instead:+ /// ```rust,ignore+ /// let x: Option<&u32> = Some(&0u32);+ /// ```+ pub REF_OPTION_REF,+ style,
pedantic,
We shouldn't have this lint warn-by-default, if it warns on public functions. This was one reason, why trivially_copy_pass_by_rev was downgraded.
comment created time in 15 hours
pull request commentrust-lang/rust-clippy
Identical arguments on assert macro family
Awesome! Thanks for implementing this :)
comment created time in 16 hours
issue commentrust-lang/rust-clippy
CLIPPY_FLAGS to pass options to clippy/ enable disable lints via env vars
Can we close this issue now that RUSTFLAGS works? Or should we document this somewhere first?
comment created time in 3 days
issue commentrust-lang/rust-clippy
Consider reinstating str_to_string and string_to_string
You won't have much luck finding those files, since the repo was at least restructured 2 times since then. You will have to reimplement those lints.
comment created time in 3 days
issue commentrust-lang/rust-clippy
needless_collect: confusing suggestion & questionable transformation
Yeah sure, go ahead! If you have any questions, feel free to ask here, on Zulip or open a WIP PR.
comment created time in 3 days
issue commentrust-lang/rust-clippy
Minimum supported version of Rust (MSVR) config and support
No, just the lints mentioned here. And then, we can iteratively add it to lints in the future, if a issue for them comes up.
comment created time in 3 days
pull request commentrust-lang/rust-clippy
Suggest a compatible shell for setup-toolchain.sh
@bors r+
comment created time in 3 days
push eventflip1995/rust-clippy
commit sha 07b2da884cda8103af50beb327723dec8204fc61
add lint less_concise_than_option_unwrap_or
commit sha 9c9327980becadc15a68307705b3a06c28116ae1
manual-unwrap-or / rename files
commit sha 6d4eeeabcda6d6d25738e1e8e2b64580daefc4b9
manual-unwrap-or / pr remarks
commit sha fc846c37fcc720c4a5c2e2075102c1957433e703
manual_unwrap_or / use consts::constant_simple helper
commit sha a8fb69f065a427f5d3fc7222b834cad9a2a7a712
manual-unwrap-or / more pr remarks
commit sha 690a6a6c0eff1a3edeb5f4c2dcbf9994760c3184
manual-unwrap-or / remove unwrap_or_else suggestion due to ownership issues
commit sha 6d358d29b0eb4e6f21526ccfb29636dea20d8993
Update semver 0.10 -> 0.11
commit sha e351e5ca693d52abc63b3737ab2abeff0aef15ad
Auto merge of #6180 - flip1995:rustup, r=flip1995 Update semver 0.10 -> 0.11 r? `@ghost,` blocking CI changelog: none
commit sha 701c7e2fbac1f05064519f0800128ea92491689a
bump cargo_metadata version
commit sha 81890c541e2da0d22992237c78190379b7497bb4
Auto merge of #6184 - ebroto:bump_cargo_metadata, r=ebroto bump cargo_metadata version changelog: none r? `@ghost` (master broken)
commit sha 4e83a38618cb6160cf6a7297ed3413f434149242
Auto merge of #6123 - montrivo:less_concise_than, r=ebroto add lint manual_unwrap_or Implements partially #5923. changelog: add lint manual_unwrap_or
commit sha 214061b90f9feb3b13679d30dd7b150c4bd418bb
rework use_self impl based on ty::Ty comparison
commit sha 6bd4f78b81fd6ed527d6832b59a9f64ac87008cc
use_self - fix issue with `hir_ty_to_ty`
commit sha c9ac3ecac096629f48dc15fc0b970ba231e479c1
Rewrite use_self lint one more time This rewrite gets rid of complicated visitors, by using the lint infrastructure as much as possible
commit sha 0ffe7c2b12544ebb9ac6838614bdd20bef8b62c6
Update test files
commit sha 68d3892abb756469aebf8c1244cb6b83fe6e8ab7
Remove fixed FIXMEs from tests
commit sha 08280f611946c9f84a24c34a469348be2e6ee2f3
Add back one FIXME of a FN to the tests
push time in 3 days
Pull request review commentrust-lang/rust-clippy
Improve a suggestion in `needless_collect` with many comments
LL | | indirect_contains.contains(&&5); | help: Check if the original Iterator contains an element instead of collecting then checking |-LL | LL | sample.iter().any(|x| x == &&5);+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^++error: avoid using `collect()` when not needed+ --> $DIR/needless_collect_indirect.rs:21:5+ |+LL | / let indirect_contains_with_comments = sample.iter().collect::<VecDeque<_>>();+LL | | // This is some stuff,+LL | | // to pretend that we have some more+LL | | // code present here+... |+LL | | // deal.+LL | | indirect_contains_with_comments.contains(&&5);+ | |____^+ |+help: Check if the original Iterator contains an element instead of collecting then checking |+LL | sample.iter().any(|x| x == &&5);+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Wait, doesn't this remove the comment when auto-applied?
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add large_type_pass_by_value lint
declare_clippy_lint! { "functions taking small copyable arguments by reference" } +declare_clippy_lint! {+ /// **What it does:** Checks for functions taking arguments by value, where+ /// the argument type is not `Copy` (or an array) and large enough to be worth+ /// considering passing by reference.+ ///+ /// **Why is this bad?** Arguments passed by value might require a shallow copy,+ /// which can be expensive and can be easily improved with passing by reference.+ ///
I think it is fine for the other lint, because of auto-deref. But there is no auto-ref, so I would prevent this lint on pub functions.
comment created time in 3 days
pull request commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
@bors retry (please?)
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
declare_clippy_lint! { "integer literals with digits grouped inconsistently" } +declare_clippy_lint! {+ /// **What it does:** Warns if a hexadecimal or binary literal is not grouped
/// **What it does:** Warns if a hexadecimal or binary literals are not grouped
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add new lint for undropped ManuallyDrop values
+#![warn(clippy::undropped_manually_drops)]++struct S;++fn main() {+ let f = std::mem::drop;+ let g = std::mem::ManuallyDrop::drop;+ let mut manual1 = std::mem::ManuallyDrop::new(S);+ let mut manual2 = std::mem::ManuallyDrop::new(S);+ let mut manual3 = std::mem::ManuallyDrop::new(S);+ let mut manual4 = std::mem::ManuallyDrop::new(S);++ // These lines will not drop `S` and should be linted+ drop(std::mem::ManuallyDrop::new(S));+ drop(manual1);+ f(manual2);
Just add a FIXME here and write this in the Known Problems section. I don't think binding mem::drop and then using it is a common enough use case for us to take care of it.
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
New lint: manual-range-contains
impl<'tcx> LateLintPass<'tcx> for Ranges { } } +fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'_>, r: &Expr<'_>, span: Span) {+ let combine_and = match op {+ BinOpKind::And | BinOpKind::BitAnd => true,+ BinOpKind::Or | BinOpKind::BitOr => false,+ _ => return,+ };+ // value, name, order (higher/lower), inclusiveness+ if let (Some((lval, lname, name_span, lval_span, lord, linc)), Some((rval, rname, _, rval_span, rord, rinc))) =+ (check_range_bounds(cx, l), check_range_bounds(cx, r))+ {+ // we only lint comparisons on the same name and with different+ // direction+ if lname != rname || lord == rord {+ return;+ }+ let ord = Constant::partial_cmp(cx.tcx, cx.typeck_results().expr_ty(l), &lval, &rval);+ if combine_and && ord == Some(rord) {+ // order lower bound and upper bound+ let (l_span, u_span, l_inc, u_inc) = if rord == Ordering::Less {+ (lval_span, rval_span, linc, rinc)+ } else {+ (rval_span, lval_span, rinc, linc)+ };+ // we only lint inclusive lower bounds+ if !l_inc {+ return;+ }+ let (range_type, range_op) = if u_inc {+ ("RangeInclusive", "..=")+ } else {+ ("Range", "..")+ };+ span_lint_and_then(+ cx,+ MANUAL_RANGE_CONTAINS,+ span,+ &format!("manual `{}::contains` implementation", range_type),+ |diag| {+ let mut applicability = Applicability::MachineApplicable;+ let name = snippet_with_applicability(cx, name_span, "_", &mut applicability);+ let lo = snippet_with_applicability(cx, l_span, "_", &mut applicability);+ let hi = snippet_with_applicability(cx, u_span, "_", &mut applicability);+ diag.span_suggestion(+ span,+ "use",+ format!("({}{}{}).contains({})", lo, range_op, hi, name),+ applicability,+ );+ },+ );+ } else if !combine_and && ord == Some(lord) {+ // `!_.contains(_)`+ // order lower bound and upper bound+ let (l_span, u_span, l_inc, u_inc) = if lord == Ordering::Less {+ (lval_span, rval_span, linc, rinc)+ } else {+ (rval_span, lval_span, rinc, linc)+ };+ if l_inc {+ return;+ }+ let (range_type, range_op) = if u_inc {+ ("Range", "..")+ } else {+ ("RangeInclusive", "..=")+ };+ span_lint_and_then(+ cx,+ MANUAL_RANGE_CONTAINS,+ span,+ &format!("manual `!{}::contains` implementation", range_type),+ |diag| {+ let mut applicability = Applicability::MachineApplicable;+ let name = snippet_with_applicability(cx, name_span, "_", &mut applicability);+ let lo = snippet_with_applicability(cx, l_span, "_", &mut applicability);+ let hi = snippet_with_applicability(cx, u_span, "_", &mut applicability);+ diag.span_suggestion(+ span,+ "use",+ format!("!({}{}{}).contains({})", lo, range_op, hi, name),+ applicability,+ );+ },+ );+ }+ }+}++fn check_range_bounds(cx: &LateContext<'_>, ex: &Expr<'_>) -> Option<(Constant, Ident, Span, Span, Ordering, bool)> {+ if let ExprKind::Binary(ref op, ref l, ref r) = ex.kind {+ let (inclusive, ordering) = match op.node {+ BinOpKind::Gt => (false, Ordering::Greater),+ BinOpKind::Ge => (true, Ordering::Greater),+ BinOpKind::Lt => (false, Ordering::Less),+ BinOpKind::Le => (true, Ordering::Less),+ _ => return None,+ };+ if let Some(id) = match_ident(l) {+ if let Some((c, _)) = constant(cx, cx.typeck_results(), r) {+ return Some((c, id, l.span, r.span, ordering, inclusive));+ }+ } else if let Some(id) = match_ident(r) {+ if let Some((c, _)) = constant(cx, cx.typeck_results(), l) {+ return Some((c, id, r.span, l.span, ordering.reverse(), inclusive));+ }+ }+ }+ None+}++fn match_ident(e: &Expr<'_>) -> Option<Ident> {+ if let ExprKind::Path(ref qpath) = e.kind {+ if let Some(seg) = single_segment_path(qpath) {+ if seg.args.is_none() {+ return Some(seg.ident);+ }+ }+ }+ None+}++fn check_range_zip_with_len(cx: &LateContext<'_>, path: &PathSegment<'_>, args: &[Expr<'_>], span: Span) {+ let name = path.ident.as_str();+ if name == "zip" && args.len() == 2 {+ let iter = &args[0].kind;+ let zip_arg = &args[1];+ if_chain! {+ // `.iter()` call+ if let ExprKind::MethodCall(ref iter_path, _, ref iter_args, _) = *iter;+ if iter_path.ident.name == sym!(iter);+ // range expression in `.zip()` call: `0..x.len()`+ if let Some(higher::Range { start: Some(start), end: Some(end), .. }) = higher::range(zip_arg);+ if is_integer_const(cx, start, 0);+ // `.len()` call+ if let ExprKind::MethodCall(ref len_path, _, ref len_args, _) = end.kind;+ if len_path.ident.name == sym!(len) && len_args.len() == 1;+ // `.iter()` and `.len()` called on same `Path`+ if let ExprKind::Path(QPath::Resolved(_, ref iter_path)) = iter_args[0].kind;+ if let ExprKind::Path(QPath::Resolved(_, ref len_path)) = len_args[0].kind;+ if SpanlessEq::new(cx).eq_path_segments(&iter_path.segments, &len_path.segments);+ then {+ span_lint(cx,+ RANGE_ZIP_WITH_LEN,+ span,+ &format!("it is more idiomatic to use `{}.iter().enumerate()`",+ snippet(cx, iter_args[0].span, "_")));
span_lint(
cx,
RANGE_ZIP_WITH_LEN,
span,
&format!("it is more idiomatic to use `{}.iter().enumerate()`", snippet(cx, iter_args[0].span, "_"))
);
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
New lint: manual-range-contains
impl<'tcx> LateLintPass<'tcx> for Ranges { } } +fn check_possible_range_contains(cx: &LateContext<'_>, op: BinOpKind, l: &Expr<'_>, r: &Expr<'_>, span: Span) {+ let combine_and = match op {+ BinOpKind::And | BinOpKind::BitAnd => true,+ BinOpKind::Or | BinOpKind::BitOr => false,+ _ => return,+ };+ // value, name, order (higher/lower), inclusiveness+ if let (Some((lval, lname, name_span, lval_span, lord, linc)), Some((rval, rname, _, rval_span, rord, rinc))) =+ (check_range_bounds(cx, l), check_range_bounds(cx, r))+ {+ // we only lint comparisons on the same name and with different+ // direction+ if lname != rname || lord == rord {+ return;+ }+ let ord = Constant::partial_cmp(cx.tcx, cx.typeck_results().expr_ty(l), &lval, &rval);+ if combine_and && ord == Some(rord) {+ // order lower bound and upper bound+ let (l_span, u_span, l_inc, u_inc) = if rord == Ordering::Less {+ (lval_span, rval_span, linc, rinc)+ } else {+ (rval_span, lval_span, rinc, linc)+ };+ // we only lint inclusive lower bounds+ if !l_inc {+ return;+ }+ let (range_type, range_op) = if u_inc {+ ("RangeInclusive", "..=")+ } else {+ ("Range", "..")+ };+ span_lint_and_then(+ cx,+ MANUAL_RANGE_CONTAINS,+ span,+ &format!("manual `{}::contains` implementation", range_type),+ |diag| {+ let mut applicability = Applicability::MachineApplicable;+ let name = snippet_with_applicability(cx, name_span, "_", &mut applicability);+ let lo = snippet_with_applicability(cx, l_span, "_", &mut applicability);+ let hi = snippet_with_applicability(cx, u_span, "_", &mut applicability);+ diag.span_suggestion(+ span,+ "use",+ format!("({}{}{}).contains({})", lo, range_op, hi, name),+ applicability,+ );+ },+ );+ } else if !combine_and && ord == Some(lord) {+ // `!_.contains(_)`+ // order lower bound and upper bound+ let (l_span, u_span, l_inc, u_inc) = if lord == Ordering::Less {+ (lval_span, rval_span, linc, rinc)+ } else {+ (rval_span, lval_span, rinc, linc)+ };+ if l_inc {+ return;+ }+ let (range_type, range_op) = if u_inc {+ ("Range", "..")+ } else {+ ("RangeInclusive", "..=")+ };+ span_lint_and_then(
You can use span_lint_and_sugg here. Same above.
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
New lint: manual-range-contains
fn no_panic_with_fake_range_types() { let _ = Range { foo: 0 }; }++#[warn(clippy::manual_range_contains)]
Can you move those to a new test file and add // run-rustfix there please?
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add lint 'ref_option_ref' #1377
+use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint_and_sugg};+use rustc_hir::{GenericArg, Mutability, Ty, TyKind};+use rustc_lint::{LateContext, LateLintPass};+use rustc_session::{declare_lint_pass, declare_tool_lint};++use if_chain::if_chain;+use rustc_errors::Applicability;++declare_clippy_lint! {+ /// **What it does:** Checks for usage of `&Option<&T>`.+ ///+ /// **Why is this bad?** Since `&` is Copy, it's useless to have a+ /// reference on `Option<&T>`.+ ///+ /// **Known problems:** None.+ ///+ /// **Example:**+ ///+ /// ```rust,ignore+ /// // example code where clippy issues a warning+ /// let x: &Option<&u32> = &Some(&0u32);+ /// ```+ /// Use instead:+ /// ```rust,ignore+ /// // example code which does not raise clippy warning+ /// let x: Option<&u32> = Some(&0u32);+ /// ```+ pub REF_OPTION_REF,+ style,+ "use `Option<&T>` instead of `&Option<&T>`"+}++declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]);++impl<'tcx> LateLintPass<'tcx> for RefOptionRef {+ fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx>) {+ if_chain! {+ if let TyKind::Rptr(_, ref mut_ty) = ty.kind;+ if mut_ty.mutbl == Mutability::Not;+ if let TyKind::Path(ref qpath) = &mut_ty.ty.kind;+ let last = last_path_segment(qpath);+ if let Some(res) = last.res;+ if let Some(def_id) = res.opt_def_id();++ if match_def_path(cx, def_id, &paths::OPTION);
if cx.tcx.is_diagnostic_item(sym!(option_type), def_id);
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add lint 'ref_option_ref' #1377
+use crate::utils::{last_path_segment, match_def_path, paths, snippet, span_lint_and_sugg};+use rustc_hir::{GenericArg, Mutability, Ty, TyKind};+use rustc_lint::{LateContext, LateLintPass};+use rustc_session::{declare_lint_pass, declare_tool_lint};++use if_chain::if_chain;+use rustc_errors::Applicability;++declare_clippy_lint! {+ /// **What it does:** Checks for usage of `&Option<&T>`.+ ///+ /// **Why is this bad?** Since `&` is Copy, it's useless to have a+ /// reference on `Option<&T>`.+ ///+ /// **Known problems:** None.+ ///+ /// **Example:**+ ///+ /// ```rust,ignore+ /// // example code where clippy issues a warning+ /// let x: &Option<&u32> = &Some(&0u32);+ /// ```+ /// Use instead:+ /// ```rust,ignore+ /// // example code which does not raise clippy warning+ /// let x: Option<&u32> = Some(&0u32);
/// let x: &Option<&u32> = &Some(&0u32);
/// ```
/// Use instead:
/// ```rust,ignore
/// let x: Option<&u32> = Some(&0u32);
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add a case to `lint_search_is_some` to handle searching strings
fn search_is_some() { x < 0 } ).is_some();-- // Check that we don't lint if the caller is not an `Iterator`.+ + let s1 = String::from("hello world");+ let s2 = String::from("world");+ // Check caller `find()` is a &`static str case+ let _ = "hello world".find("world").is_some();+ let _ = "hello world".find(&s2).is_some();+ let _ = "hello world".find(&s2[2..]).is_some();+ // Check caller of `find()` is a String case+ let _ = s1.find("world").is_some();+ let _ = s1.find(&s2).is_some();+ let _ = s1.find(&s2[2..]).is_some();+ // Check caller of `find()` is a slice of String case+ let _ = s1[2..].find("world").is_some();+ let _ = s1[2..].find(&s2).is_some();+ let _ = s1[2..].find(&s2[2..]).is_some();++ // Check that we don't lint if `find()` is called with+ // Pattern that is not a string+ let _ = s1.find(|c: char| c == 'o' || c == 'l').is_some();++ // Check that we don't lint if the caller is not an `Iterator` or string let foo = IteratorFalsePositives { foo: 0 }; let _ = foo.find().is_some(); let _ = foo.position().is_some();
All the tests for the search_is_some lint please. GH doesn't let you comment on unchanged code ;)
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add lint for `&mut Mutex::lock`
+use crate::utils::{is_type_diagnostic_item, span_lint_and_sugg};+use if_chain::if_chain;+use rustc_errors::Applicability;+use rustc_hir::{Expr, ExprKind, Mutability};+use rustc_lint::{LateContext, LateLintPass};+use rustc_middle::ty;+use rustc_session::{declare_lint_pass, declare_tool_lint};++declare_clippy_lint! {+ /// **What it does:** Checks for `&mut Mutex::lock` calls+ ///+ /// **Why is this bad?** `Mutex::lock` is less efficient than+ /// calling `Mutex::get_mut`. In addition you also have a statically+ /// guarantee that the mutex isn't locked, instead of just a runtime+ /// guarantee.+ ///+ /// **Known problems:** None.+ ///+ /// **Example:**+ ///+ /// ```rust+ /// use std::sync::{Arc, Mutex};+ ///+ /// let mut value_rc = Arc::new(Mutex::new(42_u8));+ /// let value_mutex = Arc::get_mut(&mut value_rc).unwrap();+ ///+ /// let mut value = value_mutex.lock().unwrap();+ /// *value += 1;+ /// ```+ /// Use instead:+ /// ```rust+ /// use std::sync::{Arc, Mutex};+ ///+ /// let mut value_rc = Arc::new(Mutex::new(42_u8));+ /// let value_mutex = Arc::get_mut(&mut value_rc).unwrap();+ ///+ /// let value = value_mutex.get_mut().unwrap();+ /// *value += 1;+ /// ```+ pub MUT_MUTEX_LOCK,+ correctness,+ "`&mut Mutex::lock` does unnecessary locking"+}++declare_lint_pass!(MutMutexLock => [MUT_MUTEX_LOCK]);++impl<'tcx> LateLintPass<'tcx> for MutMutexLock {+ fn check_expr(&mut self, cx: &LateContext<'tcx>, ex: &'tcx Expr<'tcx>) {+ if_chain! {+ if let ExprKind::MethodCall(path, method_span, args, _) = &ex.kind;+ if path.ident.name == sym!(lock);+ let ty = cx.typeck_results().expr_ty(&args[0]);+ if let ty::Ref(_, inner_ty, Mutability::Mut) = ty.kind();+ if is_type_diagnostic_item(cx, inner_ty, sym!(mutex_type));+ then {+ span_lint_and_sugg(+ cx,+ MUT_MUTEX_LOCK,+ *method_span,+ "calling `&mut Mutex::lock` unnecessarily locks an exclusive (mutable) reference",+ "change this to",+ "get_mut".to_owned(),+ Applicability::MachineApplicable,
This is
Applicability::MaybeIncorrect,
since it may lead to compiler errors afterwards, because of the mutable borrow it introduces.
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add lint for `&mut Mutex::lock`
+use crate::utils::{is_type_diagnostic_item, span_lint_and_sugg};+use if_chain::if_chain;+use rustc_errors::Applicability;+use rustc_hir::{Expr, ExprKind, Mutability};+use rustc_lint::{LateContext, LateLintPass};+use rustc_middle::ty;+use rustc_session::{declare_lint_pass, declare_tool_lint};++declare_clippy_lint! {+ /// **What it does:** Checks for `&mut Mutex::lock` calls+ ///+ /// **Why is this bad?** `Mutex::lock` is less efficient than+ /// calling `Mutex::get_mut`. In addition you also have a statically+ /// guarantee that the mutex isn't locked, instead of just a runtime+ /// guarantee.+ ///+ /// **Known problems:** None.+ ///+ /// **Example:**+ ///+ /// ```rust+ /// use std::sync::{Arc, Mutex};+ ///+ /// let mut value_rc = Arc::new(Mutex::new(42_u8));+ /// let value_mutex = Arc::get_mut(&mut value_rc).unwrap();+ ///+ /// let mut value = value_mutex.lock().unwrap();+ /// *value += 1;+ /// ```+ /// Use instead:+ /// ```rust+ /// use std::sync::{Arc, Mutex};+ ///+ /// let mut value_rc = Arc::new(Mutex::new(42_u8));+ /// let value_mutex = Arc::get_mut(&mut value_rc).unwrap();+ ///+ /// let value = value_mutex.get_mut().unwrap();+ /// *value += 1;+ /// ```+ pub MUT_MUTEX_LOCK,+ correctness,
style,
I would only classify this as a style lint, rather than a correctness lint.
comment created time in 3 days
pull request commentrust-lang/rust-clippy
Add lint: from_iter_instead_of_collect
Thanks! Only the dogfood error (https://github.com/rust-lang/rust-clippy/pull/6101#issuecomment-702277887) is now left to fix
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add new lint `unnecessary_wrap`
+use crate::utils::{+ is_type_diagnostic_item, match_qpath, paths, return_ty, snippet, span_lint_and_then,+ visitors::find_all_ret_expressions,+};+use if_chain::if_chain;+use rustc_errors::Applicability;+use rustc_hir::intravisit::FnKind;+use rustc_hir::*;+use rustc_lint::{LateContext, LateLintPass};+use rustc_middle::ty::subst::GenericArgKind;+use rustc_session::{declare_lint_pass, declare_tool_lint};+use rustc_span::Span;++declare_clippy_lint! {+ /// **What it does:** Checks for private functions that only return `Ok` or `Some`.+ ///+ /// **Why is this bad?** It is not meaningful to wrap values when no `None` or `Err` is returned.+ ///+ /// **Known problems:** Since this lint changes function type signature, you may need to+ /// adjust some code at callee side.+ ///+ /// **Example:**+ ///+ /// ```rust+ /// fn get_cool_number(a: bool, b: bool) -> Option<i32> {+ /// if a && b {+ /// return Some(50);+ /// }+ /// if a {+ /// Some(0)+ /// } else {+ /// Some(10)+ /// }+ /// }+ /// ```+ /// Use instead:+ /// ```rust+ /// fn get_cool_number(a: bool, b: bool) -> i32 {+ /// if a && b {+ /// return 50;+ /// }+ /// if a {+ /// 0+ /// } else {+ /// 10+ /// }+ /// }+ /// ```+ pub UNNECESSARY_WRAP,+ complexity,+ "functions that only return `Ok` or `Some`"+}++declare_lint_pass!(UnnecessaryWrap => [UNNECESSARY_WRAP]);++impl<'tcx> LateLintPass<'tcx> for UnnecessaryWrap {+ fn check_fn(+ &mut self,+ cx: &LateContext<'tcx>,+ fn_kind: FnKind<'tcx>,+ fn_decl: &FnDecl<'tcx>,+ body: &Body<'tcx>,+ span: Span,+ hir_id: HirId,+ ) {+ if_chain! {+ if let FnKind::ItemFn(.., visibility, _) = fn_kind;+ if visibility.node.is_pub();+ then {+ return;+ }+ }++ let (return_type, path) = if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym!(option_type)) {
The call to return_ty panics in 106 tests when called on a closure. You could either just exclude closures from this lint with the FnKind or try to get the return type of the closure with cx.tcx.typeck_results().expr_ty(&body.value). Which should give you a ty::Closure(..) where you can get the return_ty from the SubstsRef with cx.tcx.erase_late_bound_regions(substs.as_closure().sig().output())
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add new lint `unnecessary_wrap`
+use rustc_hir as hir;
Nah, don't revert the commit, we can do this here. The extra PR for the other visitors would still be appreciated though!
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add lint for holding RefCell Ref across an await
fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool { || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_READ_GUARD) || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD) }++declare_clippy_lint! {
NIT: usually lint declarations are on top of the file
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add lint for holding RefCell Ref across an await
fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool { || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_READ_GUARD) || match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD) }++declare_clippy_lint! {+ /// **What it does:** Checks for calls to await while holding a+ /// `RefCell` `Ref` or `RefMut`.+ ///+ /// **Why is this bad?** `RefCell` refs only check for exclusive mutable access+ /// at runtime. Holding onto a `RefCell` ref across an `await` suspension point+ /// risks panics from a mutable ref shared while other refs are outstanding.+ ///+ /// **Known problems:** None.+ ///+ /// **Example:**+ ///+ /// ```rust,ignore+ /// use std::cell::RefCell;+ ///+ /// async fn foo(x: &RefCell<u32>) {+ /// let b = x.borrow_mut()();+ /// *ref += 1;+ /// bar.await;+ /// }+ /// ```+ ///+ /// Use instead:+ /// ```rust,ignore+ /// use std::cell::RefCell;+ ///+ /// async fn foo(x: &RefCell<u32>) {+ /// {+ /// let b = x.borrow_mut();+ /// *ref += 1;+ /// }+ /// bar.await;+ /// }+ /// ```+ pub AWAIT_HOLDING_REFCELL_REF,+ pedantic,+ "Inside an async function, holding a RefCell ref while calling await"+}++declare_lint_pass!(AwaitHoldingRefCellRef => [AWAIT_HOLDING_REFCELL_REF]);++impl LateLintPass<'_> for AwaitHoldingRefCellRef {+ fn check_body(&mut self, cx: &LateContext<'_>, body: &'_ Body<'_>) {+ use AsyncGeneratorKind::{Block, Closure, Fn};+ if let Some(GeneratorKind::Async(Block | Closure | Fn)) = body.generator_kind {+ let body_id = BodyId {+ hir_id: body.value.hir_id,+ };+ let def_id = cx.tcx.hir().body_owner_def_id(body_id);+ let typeck_results = cx.tcx.typeck(def_id);
this is exactly the same code as in line 55. You can just combine the two lint passes.
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add lint for holding RefCell Ref across an await
LL | | } | |_^ error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await.- --> $DIR/await_holding_invalid.rs:41:13+ --> $DIR/await_holding_invalid.rs:42:13 | LL | let guard = x.lock().unwrap(); | ^^^^^ | note: these are all the await points this lock is held through- --> $DIR/await_holding_invalid.rs:41:9+ --> $DIR/await_holding_invalid.rs:42:9 | LL | / let guard = x.lock().unwrap(); LL | | baz().await LL | | }; | |_____^ error: this MutexGuard is held across an 'await' point. Consider using an async-aware Mutex type or ensuring the MutexGuard is dropped before calling await.- --> $DIR/await_holding_invalid.rs:53:13+ --> $DIR/await_holding_invalid.rs:54:13 | LL | let guard = x.lock().unwrap(); | ^^^^^ | note: these are all the await points this lock is held through- --> $DIR/await_holding_invalid.rs:53:9+ --> $DIR/await_holding_invalid.rs:54:9 | LL | / let guard = x.lock().unwrap(); LL | | baz().await LL | | } | |_____^ -error: aborting due to 4 previous errors+error: this RefCell Ref is held across an 'await' point. Consider ensuring the Ref is dropped before calling await.
It would be nice to keep the tests separated.
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add linter for a single element for loop
+// Tests from for_loop.rs that don't have suggestions
// run-rustfix
// Tests from for_loop.rs that don't have suggestions
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add linter for a single element for loop
fn check_for_loop_over_map_kv<'tcx>( } } +fn check_for_single_element_loop<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>) {+ if_chain! {+ if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = arg.kind;+ if let PatKind::Binding(.., target, _) = pat.kind;+ if let ExprKind::Array(ref expr_list) = expr.kind;+ if expr_list.len() == 1;+ if let ExprKind::Path(ref list_item) = expr_list[0].kind;+ if let Some(list_tem_name) = single_segment_path(list_item).map(|ps| ps.ident.name);++ then {+ span_lint_and_sugg(+ cx,+ SINGLE_ELEMENT_LOOP,+ expr.span,
You should use the span from the start of the for loop to the end of expr. You can do this, by also passing the expr from the check_for_loop function and then use the span for_expr.span.with_hi(expr.span.hi()).
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add linter for a single element for loop
fn check_for_loop_over_map_kv<'tcx>( } } +fn check_for_single_element_loop<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>) {+ if_chain! {+ if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = arg.kind;+ if let PatKind::Binding(.., target, _) = pat.kind;+ if let ExprKind::Array(ref expr_list) = expr.kind;+ if expr_list.len() == 1;+ if let ExprKind::Path(ref list_item) = expr_list[0].kind;+ if let Some(list_tem_name) = single_segment_path(list_item).map(|ps| ps.ident.name);++ then {+ span_lint_and_sugg(+ cx,+ SINGLE_ELEMENT_LOOP,+ expr.span,+ "do not iterate over a single element array",+ "try",
"`for` loop over a single element",
"try",
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add linter for a single element for loop
fn check_for_loop_over_map_kv<'tcx>( } } +fn check_for_single_element_loop<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>) {+ if_chain! {+ if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = arg.kind;+ if let PatKind::Binding(.., target, _) = pat.kind;+ if let ExprKind::Array(ref expr_list) = expr.kind;+ if expr_list.len() == 1;+ if let ExprKind::Path(ref list_item) = expr_list[0].kind;
if let [expr] = expr_list; // or a more fitting name than "expr"
if let ExprKind::Path(ref list_item) = expr.kind;
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
Add linter for a single element for loop
fn check_for_loop_over_map_kv<'tcx>( } } +fn check_for_single_element_loop<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, arg: &'tcx Expr<'_>) {+ if_chain! {+ if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = arg.kind;+ if let PatKind::Binding(.., target, _) = pat.kind;+ if let ExprKind::Array(ref expr_list) = expr.kind;+ if expr_list.len() == 1;+ if let ExprKind::Path(ref list_item) = expr_list[0].kind;+ if let Some(list_tem_name) = single_segment_path(list_item).map(|ps| ps.ident.name);
if let Some(list_item_name) = single_segment_path(list_item).map(|ps| ps.ident.name);
comment created time in 3 days
Pull request review commentrust-lang/rust-clippy
[WIP] Rework use_self impl based on ty::Ty comparison #3410 | Take 2
declare_clippy_lint! { "unnecessary structure name repetition whereas `Self` is applicable" } -declare_lint_pass!(UseSelf => [USE_SELF]);+#[derive(Default)]+pub struct UseSelf {+ stack: Vec<StackItem>,+ types_to_skip: Vec<HirId>,+ types_to_lint: Vec<HirId>,+}++#[derive(Debug, PartialEq, Eq, Copy, Clone)]+enum StackItem {+ Check {+ hir_id: HirId,+ impl_trait_ref_def_id: Option<LocalDefId>,+ },+ NoCheck,+}++impl_lint_pass!(UseSelf => [USE_SELF]); const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; +impl<'tcx> LateLintPass<'tcx> for UseSelf {+ fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) {+ // We push the self types of `impl`s on a stack here. Only the top type on the stack is+ // relevant for linting, since this is the self type of the `impl` we're currently in. To+ // avoid linting on nested items, we push `StackItem::NoCheck` on the stack to signal, that+ // we're in an `impl` or nested item, that we don't want to lint+ //+ // NB: If you push something on the stack in this method, remember to also pop it in the+ // `check_item_post` method.+ use ItemKind::{Const, Enum, Fn, Impl, Static, Struct, Trait, Union};+ match &item.kind {+ Impl {+ self_ty: hir_self_ty,+ of_trait,+ ..+ } => {+ let should_check = if let TyKind::Path(QPath::Resolved(_, ref item_path)) = hir_self_ty.kind {+ let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;+ parameters.as_ref().map_or(true, |params| {+ !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_)))+ })+ } else {+ false+ };+ let impl_trait_ref_def_id = of_trait.as_ref().map(|_| cx.tcx.hir().local_def_id(item.hir_id));+ if should_check {+ self.stack.push(StackItem::Check {+ hir_id: hir_self_ty.hir_id,+ impl_trait_ref_def_id,+ });+ } else {+ self.stack.push(StackItem::NoCheck);+ }+ },+ Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..) => {+ self.stack.push(StackItem::NoCheck);+ },+ _ => (),+ }+ }++ fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) {+ use ItemKind::{Const, Enum, Fn, Impl, Static, Struct, Trait, Union};+ match item.kind {+ Impl { .. } | Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..) => {+ self.stack.pop();+ },+ _ => (),+ }+ }++ fn check_impl_item(&mut self, cx: &LateContext<'_>, impl_item: &hir::ImplItem<'_>) {+ // We want to skip types in trait `impl`s that aren't declared as `Self` in the trait+ // declaration. The collection of those types is all this method implementation does.+ if_chain! {+ if let ImplItemKind::Fn(FnSig { decl, .. }, ..) = impl_item.kind;+ if let Some(StackItem::Check { impl_trait_ref_def_id: Some(def_id), .. }) = self.stack.last().copied();+ if let Some(impl_trait_ref) = cx.tcx.impl_trait_ref(def_id);+ then {+ // `self_ty` is the semantic self type of `impl <trait> for <type>`. This cannot be+ // `Self`.+ let self_ty = impl_trait_ref.self_ty();++ // `trait_method_sig` is the signature of the function, how it is declared in the+ // trait, not in the impl of the trait.+ let trait_method = cx+ .tcx+ .associated_items(impl_trait_ref.def_id)+ .find_by_name_and_kind(cx.tcx, impl_item.ident, AssocKind::Fn, impl_trait_ref.def_id)+ .expect("impl method matches a trait method");+ let trait_method_sig = cx.tcx.fn_sig(trait_method.def_id);+ let trait_method_sig = cx.tcx.erase_late_bound_regions(&trait_method_sig);++ // `impl_inputs_outputs` is an iterator over the types (`hir::Ty`) declared in the+ // implementation of the trait.+ let output_hir_ty = if let FnRetTy::Return(ty) = &decl.output {+ Some(&**ty)+ } else {+ None+ };+ let impl_inputs_outputs = decl.inputs.iter().chain(output_hir_ty);++ // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature.+ //+ // `trait_sem_ty` (of type `ty::Ty`) is the semantic type for the signature in the+ // trait declaration. This is used to check if `Self` was used in the trait+ // declaration.+ //+ // If `any`where in the `trait_sem_ty` the `self_ty` was used verbatim (as opposed+ // to `Self`), we want to skip linting that type and all subtypes of it. This+ // avoids suggestions to e.g. replace `Vec<u8>` with `Vec<Self>`, in an `impl Trait+ // for u8`, when the trait always uses `Vec<u8>`.+ //+ // See also https://github.com/rust-lang/rust-clippy/issues/2894.+ for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {+ if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {+ let mut visitor = SkipTyCollector::default();+ visitor.visit_ty(&impl_hir_ty);+ self.types_to_skip.extend(visitor.types_to_skip);+ }+ }+ }+ }+ }++ fn check_impl_item_post(&mut self, _: &LateContext<'_>, _: &hir::ImplItem<'_>) {+ self.types_to_skip.clear();+ }++ fn check_body(&mut self, cx: &LateContext<'tcx>, body: &'tcx hir::Body<'_>) {+ // `hir_ty_to_ty` cannot be called in `Body`s or it will panic (sometimes). But in bodies+ // we can use `cx.typeck_results.node_type(..)` to get the `ty::Ty` from a `hir::Ty`.
I discovered it randomly by searching for hir_ty_to_ty in rustc. This is used like that in rustc_privacy. https://github.com/rust-lang/rust/blob/8850893d96252172700727fe9e746c8e1ebd5853/compiler/rustc_privacy/src/lib.rs#L1246-L1258
comment created time in 4 days
pull request commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
@bors retry
comment created time in 4 days
PR opened rust-lang/rust-clippy
r? @ghost, blocking CI
changelog: none
pr created time in 4 days
push eventflip1995/rust-clippy
commit sha 6d358d29b0eb4e6f21526ccfb29636dea20d8993
Update semver 0.10 -> 0.11
push time in 4 days
push eventflip1995/rust-clippy
commit sha 1385eb9b5562ec78f772341e1ad5c3d2f5443141
Replace run_compiler with RunCompiler builder pattern. RunCompiler::new takes non-optional params, and optional params can be set using set_*field_name* method. finally `run` will forward all fields to `run_compiler`.
commit sha fbf2430f0279adb8132efe60b16f8dd7b6a2acb3
Merge commit '2f6439ae6a6803d030cceb3ee14c9150e91b328b' into clippyup
commit sha ecd308ec394f9d01b4392ee0315ea64d52ab7caa
ICEs should print the top of the query stack
commit sha a9053e4baf251f53d8d6b95cd3f5b8a829ad0ba6
run full query stack print just when RUST_BACKTRACE is set
commit sha 49bc85e947ab7ca793c14b6f3af4a8e9d8db0337
fix clippy custom_ice_message test
commit sha 7f07577e6f873f4a1b3428d29bf520189f4ef79e
add new line
commit sha 3c94914f0c87ba00987e515063dcc9e079a8918d
rebase with master
commit sha 117877745738f21e851686efe57a09e14606dadc
Refactor how SwitchInt stores jump targets
commit sha 29cff6feffd9da569fe3aa171d10db2647bf86c9
Auto merge of #77649 - dash2507:replace_run_compiler, r=matthewjasper Replace run_compiler with RunCompiler builder pattern Fixes #77286. Replaces rustc_driver:run_compiler with RunCompiler builder pattern.
commit sha bf947fcba226a7ec0964bb6be17237e54e04ccdb
Auto merge of #77796 - jonas-schievink:switchint-refactor, r=oli-obk Refactor how SwitchInt stores jump targets Closes https://github.com/rust-lang/rust/issues/65693
commit sha ab0fc477b8b83cb14c584aca281b16fb5cce4c1a
fix stderr file of clippy/custom_ice_message test
commit sha 2c1e8cfc622652ebfb1f0256aa8d2afae91bf416
Remove rustc_session::config::Config The wrapper type led to tons of target.target across the compiler. Its ptr_width field isn't required any more, as target_pointer_width is already present in parsed form.
commit sha d2feccc1efcbeff9dfb99daa754b8b47cdac7eaf
Rollup merge of #77493 - hosseind88:ICEs_should_always_print_the_top_of_the_query_stack, r=oli-obk ICEs should always print the top of the query stack see #76920
push time in 4 days
push eventflip1995/rust-clippy
commit sha dc89bb1135afc31fc9ee2272e627192c04354d22
Use if_chain in Increment/InitializeVisitor
commit sha 116f30dc33d9e3744f257f2f7f5467acfbff178b
Use else blocks instead of return statements in Increment/InitializeVisitor
commit sha b2d5b89a1de15df9052fdf44d01b174add82837f
Check if it's after the loop earlier
commit sha 31cb1109648bf4242cab47571343578244e7fb9d
add concinient methods to Increment/InitializeVisitor
commit sha c599e2fcfaaedb12b560f4136bab3d0b450acf8f
Split VarState
commit sha 13c207d3756754c54a6b20d852087616d5abfbf4
Generalise `InitializeVisitor`
commit sha 9573a0d378033a81e55ca834a5d305d3cf2be24d
Rename variables
commit sha 1026b42f0694eb9239b5cebe80be743d5ded0da5
Rename a struct and variables
commit sha b4b4da162f19e9a4c63854a2b5a6167b83f9d8b9
Introduce Start and StartKind
commit sha 720f19f2ec4282f636889b35beabf31272e3b1b2
Implement detecting `manual_memcpy` with loop counters
commit sha de56279cd9047832216e1d1c06dc45375bf01b31
Implement building the `manual_memcpy` sugggestion with loop counters
commit sha 8da6cfd17b7707d678d01a6688572169015ea83e
fmt
commit sha d9a88be0b05c2cfec0679caf428d129c9d46256d
Rename `get_offset` and its private items
commit sha 774e82a566c6c3349700a8bece44d6a8c6755039
Add the tests for `manual_memcpy` with loop counters
commit sha 9aad38bf614c3fb6d306f5dec4a0af606bb3c9c8
Update `manual_memcpy.stderr` to reflect additional parentheses
commit sha 4ea4a972500a8ddecfc737d51eec960324dcb02f
Add tests for bitwise operations
commit sha eb3ffe6ed2999e9d3385be0ff981e30082ea0d2c
make use of macros in operator overloading
commit sha 10d7a18f72155f03dbd27b872a52b5dd45def8db
fmt
commit sha 174065fc98ef9335ea45a234aa18286cdf6c3934
fix the multiple counters test
commit sha 44187383f4724bd7e4b2b220235e93438043947a
Use operator overloading instead of direct calls of `make_binop`
push time in 4 days
PR closed rust-lang/rust-clippy
use_self lint refactoring. As suggested by @eddyb , implement the lint based on ty::Ty comparison instead of hir::Path checks.
This PR introduces negative regressions. The cases were covered in the previous implementation. See the test file.
It fixes #3410, #2843, #3859, #4734 and #4140. Should fix #4143 (example doesn't compile). #4305 false positive seems also fixed but the uitest fails to compile the unmodified test case in use_self.rs.fixed. Implements #5078.
Generally the implementation checks are done at mir level and offers higher guarantees against false positives. It is probably fixing other unreported false positives.
changelog: fix use_self generics false positives
pr closed time in 4 days
pull request commentrust-lang/rust-clippy
rework use_self impl based on ty::Ty comparison #3410
Closing in favor of #6179.
@montrivo Your commits will of course be merged, so your work will not get thrown away.
The only issue left to fix is now #4140. I would be happy to work this out together with you in #6179. If you want to work on my branch, I can give you push access to my fork.
comment created time in 4 days
PR opened rust-lang/rust-clippy
This builds on top of #5531
I already reviewed and approved the commits by @montrivo. So only the review of my commits should be necessary.
I would also appreciate your review @montrivo, since you are familiar with the challenges here.
Fixes #3410 and Fixes #4143 (same problem) Fixes #2843 Fixes #3859 Fixes #4734 Fixes #4305 Fixes #5078 (even at expression level now 🎉)
Not yet: #4140 (test added)
All the credit for the fixes goes to @montrivo. I only refactored and copy and pasted his code.
changelog: none
pr created time in 4 days
push eventflip1995/rust-clippy
commit sha 5892c82bb762b3e0450075ea0d32f41d51b7ad6c
Remove fixed FIXMEs from tests
commit sha f074bebf8e30ce0ee97b06c9e805e43f920482e1
Add back one FIXME of a FN to the tests
push time in 4 days
push eventflip1995/rust-clippy
commit sha 91722217832c6eaa9c63f91085a549f0a52aa430
Add back one FIXME of a FN to the tests
push time in 4 days
push eventflip1995/rust-clippy
commit sha e79a1b735f0b9d806d7c95f3721995b65e488ff5
Rewrite use_self lint one more time This rewrite gets rid of complicated visitors, by using the lint infrastructure as much as possible
commit sha b6c8439e726c3ca154e6e5e1e07b953bd86f0dca
Update test files
commit sha 10538312fe00719740db568b46610cc145d59ef5
Remove fixed FIXMEs from tests
push time in 4 days
push eventflip1995/rust-clippy
commit sha 9f321e75b1edf419d454fa8fc1de57a8e922c176
WIP
push time in 4 days
pull request commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
@bors r+
Thanks!
comment created time in 4 days
issue commentrust-lang/rust-clippy
git subtree crashes: can't sync rustc clippy changes into rust-lang/rust-clippy
Only the first time. Once it is cached, it is a matter of seconds. Still not optimal though.
comment created time in 4 days
push eventflip1995/rust-clippy
commit sha e5e19f1f93914547aa466872a6896a55726a90e8
WIP
push time in 5 days
issue commentrust-lang/rust
Uplift `declare_interior_mutable_const` and `borrow_interior_mutable_const` from clippy to rustc
I don't think this lint is ready to get uplifted, because it has too many FPs. I will do a review round in Clippy tomorrow and also take a look at rust-lang/rust-clippy#6110. If my opinion about that changes with rust-lang/rust-clippy#6110 merged, I'll write that here.
That being said, a FP free version of this lint would definitely be great in rustc.
comment created time in 5 days
pull request commentrust-lang/rust-clippy
rework use_self impl based on ty::Ty comparison #3410
So my idea to rewrite this and removing the visitors seems to work. My rewrite is at the state, that it fixed all the FIXMEs that you added. Now I have to fix some FPs I didn't yet address in my prototype rewrite.
comment created time in 5 days
Pull request review commentrust-lang/rust-clippy
rework use_self impl based on ty::Ty comparison #3410
impl<'a, 'tcx> Visitor<'tcx> for ImplVisitor<'a, 'tcx> { } } +struct FnSigVisitor<'a, 'tcx> {+ cx: &'a LateContext<'tcx>,+ self_ty: Ty<'tcx>,+}++impl<'a, 'tcx> Visitor<'tcx> for FnSigVisitor<'a, 'tcx> {+ type Map = Map<'tcx>;++ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {+ NestedVisitorMap::None+ }++ fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) {+ if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind {+ match path.res {+ def::Res::SelfTy(..) => {},+ _ => {+ match self.cx.tcx.hir().find(self.cx.tcx.hir().get_parent_node(hir_ty.hir_id)) {+ Some(Node::Expr(Expr {+ kind: ExprKind::Path(QPath::TypeRelative(_, segment)),+ ..+ })) => {+ // The following block correctly identifies applicable lint locations+ // but `hir_ty_to_ty` calls cause odd ICEs.+ //
Is this comment still applicable here?
comment created time in 5 days
Pull request review commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** Checks for empty `loop` expressions. ///- /// **Why is this bad?** Those busy loops burn CPU cycles without doing- /// anything. Think of the environment and either block on something or at least- /// make the thread sleep for some microseconds.+ /// **Why is this bad?** Due to [an LLVM codegen bug](https://github.com/rust-lang/rust/issues/28728)+ /// these expressions can be miscompiled or 'optimized' out. Also, these busy loops+ /// burn CPU cycles without doing anything. ///- /// **Known problems:** None.+ /// It is _almost always_ a better idea to `panic!` than to have a busy loop.+ ///+ /// If panicking isn't possible, think of the environment and either:+ /// - block on something+ /// - sleep the thread for some microseconds+ /// - yield or pause the thread+ ///+ /// For `std` targets, this can be done with+ /// [`std::thread::sleep`](https://doc.rust-lang.org/std/thread/fn.sleep.html)+ /// or [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html).+ ///+ /// For `no_std` targets, doing this is more complicated, especially because+ /// `#[panic_handler]`s can't panic. To stop/pause the thread, you will+ /// probably need to invoke some target-specific intrinsic. Examples include:+ /// - [`x86_64::instructions::hlt`](https://docs.rs/x86_64/0.12.2/x86_64/instructions/fn.hlt.html)+ /// - [`cortex_m::asm::wfi`](https://docs.rs/cortex-m/0.6.3/cortex_m/asm/fn.wfi.html)+ ///+ /// If you just care about fixing the LLVM bug (and don't care about burning+ /// CPU), you can:+ /// - On nightly, insert a non-`pure` `asm!` statement. For example:
I would still include the hint to -Zinsert-sideeffect
comment created time in 5 days
issue commentapache/incubator-tvm
[VTA] Tutorial on how to deploy and execute model on device without RPC
Or to be more precise, you have to load your model like this:
import ctypes
import tvm
from tvm.contrib import graph_runtime as runtime
libvta_path = "/home/xilinx/tvm/build/libvta.so"
ctypes.CDLL(libvta_path, ctypes.RTLD_GLOBAL)
# load compiled model
with open("graph.json", "r") as graph_file:
graph = graph_file.read()
with open("params.params", "rb") as params_file:
params = bytearray(params_file.read())
lib = tvm.module.load("./lib.tar")
ctx = tvm.ext_dev(0)
module = runtime.create(graph, lib, ctx)
module.load_params(params)
After that module.run(**<input-dict>) should work
comment created time in 5 days
issue commentapache/incubator-tvm
[VTA] Tutorial on how to deploy and execute model on device without RPC
Oh damn, I totally forgot about it. Basically you have to add those two lines to your python script, that runs your model on the PYNQ:
dll_path = "/home/xilinx/tvm/build/libvta.so"
ctypes.CDLL(dll_path, ctypes.RTLD_GLOBAL)
before the graph_runtime.create(..) command.
I hope this still works. I haven't used TVM/VTA for a long time now.
comment created time in 5 days
Pull request review commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** Checks for empty `loop` expressions. ///- /// **Why is this bad?** Those busy loops burn CPU cycles without doing- /// anything. Think of the environment and either block on something or at least- /// make the thread sleep for some microseconds.+ /// **Why is this bad?** Due to [an LLVM codegen bug](https://github.com/rust-lang/rust/issues/28728)+ /// these expressions can produce undefined behavior. Also, these busy loops+ /// burn CPU cycles without doing anything. ///- /// **Known problems:** None.+ /// It is _almost always_ a better idea to `panic!` than to have a busy loop.+ ///+ /// If panicking isn't possible, think of the environment and either:+ /// - block on something+ /// - sleep the thread for some microseconds+ /// - yield or pause the thread+ ///+ /// For `std` targets, this can be done with+ /// [`std::thread::sleep`](https://doc.rust-lang.org/std/thread/fn.sleep.html)+ /// or [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html).+ ///+ /// For `no_std` targets, doing this is more complicated, especially because+ /// `#[panic_handler]`s can't panic. To stop/pause the thread, you will+ /// probably need to invoke some target-specific intrinsic. Examples include:+ /// - [`x86_64::instructions::hlt`](https://docs.rs/x86_64/0.12.2/x86_64/instructions/fn.hlt.html)+ /// - [`cortex_m::asm::wfi`](https://docs.rs/cortex-m/0.6.3/cortex_m/asm/fn.wfi.html)+ ///+ /// If you just care about fixing the LLVM bug (and don't care about burning+ /// CPU), you can:+ /// - On nightly, compile your code with `-Z insert-sideeffect`
The
-Zflag is most certainly perma unstable, it may resurface under a-Cflag
Oh yeah, -Z flags are of course perma unstable, oops. Time to sleep 🛌
comment created time in 6 days
Pull request review commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** Checks for empty `loop` expressions. ///- /// **Why is this bad?** Those busy loops burn CPU cycles without doing- /// anything. Think of the environment and either block on something or at least- /// make the thread sleep for some microseconds.+ /// **Why is this bad?** Due to [an LLVM codegen bug](https://github.com/rust-lang/rust/issues/28728)+ /// these expressions can produce undefined behavior. Also, these busy loops+ /// burn CPU cycles without doing anything. ///- /// **Known problems:** None.+ /// It is _almost always_ a better idea to `panic!` than to have a busy loop.+ ///+ /// If panicking isn't possible, think of the environment and either:+ /// - block on something+ /// - sleep the thread for some microseconds+ /// - yield or pause the thread+ ///+ /// For `std` targets, this can be done with+ /// [`std::thread::sleep`](https://doc.rust-lang.org/std/thread/fn.sleep.html)+ /// or [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html).+ ///+ /// For `no_std` targets, doing this is more complicated, especially because+ /// `#[panic_handler]`s can't panic. To stop/pause the thread, you will+ /// probably need to invoke some target-specific intrinsic. Examples include:+ /// - [`x86_64::instructions::hlt`](https://docs.rs/x86_64/0.12.2/x86_64/instructions/fn.hlt.html)+ /// - [`cortex_m::asm::wfi`](https://docs.rs/cortex-m/0.6.3/cortex_m/asm/fn.wfi.html)+ ///+ /// If you just care about fixing the LLVM bug (and don't care about burning+ /// CPU), you can:+ /// - On nightly, compile your code with `-Z insert-sideeffect`
https://github.com/rust-lang/rfcs/pull/2843 / https://github.com/rust-lang/rust/issues/70173
Ah asm! should be reimplemented, so it can become stable sometime in the future. Alright, in that case we should suggest to use asm!
comment created time in 6 days
Pull request review commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** Checks for empty `loop` expressions. ///- /// **Why is this bad?** Those busy loops burn CPU cycles without doing- /// anything. Think of the environment and either block on something or at least- /// make the thread sleep for some microseconds.+ /// **Why is this bad?** Due to [an LLVM codegen bug](https://github.com/rust-lang/rust/issues/28728)+ /// these expressions can produce undefined behavior. Also, these busy loops+ /// burn CPU cycles without doing anything. ///- /// **Known problems:** None.+ /// It is _almost always_ a better idea to `panic!` than to have a busy loop.+ ///+ /// If panicking isn't possible, think of the environment and either:+ /// - block on something+ /// - sleep the thread for some microseconds+ /// - yield or pause the thread+ ///+ /// For `std` targets, this can be done with+ /// [`std::thread::sleep`](https://doc.rust-lang.org/std/thread/fn.sleep.html)+ /// or [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html).+ ///+ /// For `no_std` targets, doing this is more complicated, especially because+ /// `#[panic_handler]`s can't panic. To stop/pause the thread, you will+ /// probably need to invoke some target-specific intrinsic. Examples include:+ /// - [`x86_64::instructions::hlt`](https://docs.rs/x86_64/0.12.2/x86_64/instructions/fn.hlt.html)+ /// - [`cortex_m::asm::wfi`](https://docs.rs/cortex-m/0.6.3/cortex_m/asm/fn.wfi.html)+ ///+ /// If you just care about fixing the LLVM bug (and don't care about burning+ /// CPU), you can:+ /// - On nightly, compile your code with `-Z insert-sideeffect`
Isn't asm! deprecated and got replaced with llvm_asm! or something?
-Zinsert-sideeffect isn't necessarily perma unstable and may become the default behavior sometime in the future, IIUC.
comment created time in 6 days
Pull request review commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** Checks for empty `loop` expressions. ///- /// **Why is this bad?** Those busy loops burn CPU cycles without doing- /// anything. Think of the environment and either block on something or at least- /// make the thread sleep for some microseconds.+ /// **Why is this bad?** Due to [an LLVM codegen bug](https://github.com/rust-lang/rust/issues/28728)+ /// these expressions can produce undefined behavior. Also, these busy loops
I'm good with both or a combination "can be miscompiled, producing undefined behavior"
comment created time in 6 days
pull request commentactions-rs/install
Use GitHub Actions cache for installed binaries
@svartalf Can you take another look at actions-rs/core#125 in combination with 57e52b9 then, please?
comment created time in 6 days
pull request commentrust-lang/rust-clippy
Identical arguments on assert macro family
2 things:
- (you already noticed that) This would greatly profit from #4694 being implemented first
- counter example:
assert_ne!(my_special_iter.next(), my_special_iter.next())could be a valid test for some iterator implementation on a type.
comment created time in 6 days
Pull request review commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** Checks for empty `loop` expressions. ///- /// **Why is this bad?** Those busy loops burn CPU cycles without doing- /// anything. Think of the environment and either block on something or at least- /// make the thread sleep for some microseconds.+ /// **Why is this bad?** Due to [an LLVM codegen bug](https://github.com/rust-lang/rust/issues/28728)+ /// these expressions can produce undefined behavior. Also, these busy loops
/// these expressions can produce undefined behavior (in release mode). Also, these busy loops
comment created time in 6 days
Pull request review commentrust-lang/rust-clippy
Enable empty_loop for no_std crates.
declare_clippy_lint! { declare_clippy_lint! { /// **What it does:** Checks for empty `loop` expressions. ///- /// **Why is this bad?** Those busy loops burn CPU cycles without doing- /// anything. Think of the environment and either block on something or at least- /// make the thread sleep for some microseconds.+ /// **Why is this bad?** Due to [an LLVM codegen bug](https://github.com/rust-lang/rust/issues/28728)+ /// these expressions can produce undefined behavior. Also, these busy loops+ /// burn CPU cycles without doing anything. ///- /// **Known problems:** None.+ /// It is _almost always_ a better idea to `panic!` than to have a busy loop.+ ///+ /// If panicking isn't possible, think of the environment and either:+ /// - block on something+ /// - sleep the thread for some microseconds+ /// - yield or pause the thread+ ///+ /// For `std` targets, this can be done with+ /// [`std::thread::sleep`](https://doc.rust-lang.org/std/thread/fn.sleep.html)+ /// or [`std::thread::yield_now`](https://doc.rust-lang.org/std/thread/fn.yield_now.html).+ ///+ /// For `no_std` targets, doing this is more complicated, especially because+ /// `#[panic_handler]`s can't panic. To stop/pause the thread, you will+ /// probably need to invoke some target-specific intrinsic. Examples include:+ /// - [`x86_64::instructions::hlt`](https://docs.rs/x86_64/0.12.2/x86_64/instructions/fn.hlt.html)+ /// - [`cortex_m::asm::wfi`](https://docs.rs/cortex-m/0.6.3/cortex_m/asm/fn.wfi.html)+ ///+ /// If you just care about fixing the LLVM bug (and don't care about burning+ /// CPU), you can:+ /// - On nightly, compile your code with `-Z insert-sideeffect`
Should we also suggest the llvm_asm! version here for nightly? That way the user won't have to set any compiler flags and just has to change some code. Also the llvm_asm! version is a bit better than the read_volatile version, since it doesn't insert any code. (Even though the inserted code doesn't really make a difference performance wise or in any other way, since, as you stated, the program will be trapped in an infinite loop)
comment created time in 6 days