diff --git a/CHANGELOG.md b/CHANGELOG.md index b05fa25fb1b4..7837b899b533 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1022,6 +1022,7 @@ All notable changes to this project will be documented in this file. [`transmute_int_to_float`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_int_to_float [`transmute_ptr_to_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ptr [`transmute_ptr_to_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmute_ptr_to_ref +[`transmuting_null`]: https://rust-lang.github.io/rust-clippy/master/index.html#transmuting_null [`trivial_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivial_regex [`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref [`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity diff --git a/Cargo.toml b/Cargo.toml index 024b8ff28ad4..e41440acc20e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,9 +45,8 @@ semver = "0.9" rustc_tools_util = { version = "0.1.1", path = "rustc_tools_util"} [dev-dependencies] -clippy_dev = { version = "0.0.1", path = "clippy_dev" } cargo_metadata = "0.7.1" -compiletest_rs = "0.3.19" +compiletest_rs = { version = "0.3.21", features = ["tmp"] } lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } diff --git a/README.md b/README.md index 0fd7c557dd61..43b477d2cef3 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 297 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 298 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: diff --git a/clippy_dev/rust-toolchain b/clippy_dev/rust-toolchain new file mode 100644 index 000000000000..2bf5ad0447d3 --- /dev/null +++ b/clippy_dev/rust-toolchain @@ -0,0 +1 @@ +stable diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index b4e4d46a33a6..c054a00894e7 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -208,8 +208,8 @@ impl LintPass for AttrPass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { fn check_attribute(&mut self, cx: &LateContext<'a, 'tcx>, attr: &'tcx Attribute) { if let Some(items) = &attr.meta_item_list() { - if let Some(ident) = attr.ident_str() { - match ident { + if let Some(ident) = attr.ident() { + match &*ident.as_str() { "allow" | "warn" | "deny" | "forbid" => { check_clippy_lint_names(cx, items); }, @@ -242,8 +242,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass { for attr in &item.attrs { if let Some(lint_list) = &attr.meta_item_list() { - if let Some(ident) = attr.ident_str() { - match ident { + if let Some(ident) = attr.ident() { + match &*ident.as_str() { "allow" | "warn" | "deny" | "forbid" => { // whitelist `unused_imports` and `deprecated` for `use` items // and `unused_imports` for `extern crate` items with `macro_use` diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 61bfc78b3de8..66fbf18f3dd0 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -41,6 +41,8 @@ pub enum Constant { Repeat(Box, u64), /// A tuple of constants. Tuple(Vec), + /// A raw pointer. + RawPtr(u128), /// A literal with syntax error. Err(Symbol), } @@ -109,6 +111,9 @@ impl Hash for Constant { c.hash(state); l.hash(state); }, + Constant::RawPtr(u) => { + u.hash(state); + }, Constant::Err(ref s) => { s.hash(state); }, @@ -192,7 +197,7 @@ pub fn constant_simple<'c, 'cc>( constant(lcx, tables, e).and_then(|(cst, res)| if res { None } else { Some(cst) }) } -/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckTables` +/// Creates a `ConstEvalLateContext` from the given `LateContext` and `TypeckTables`. pub fn constant_context<'c, 'cc>( lcx: &LateContext<'c, 'cc>, tables: &'c ty::TypeckTables<'cc>, @@ -215,7 +220,7 @@ pub struct ConstEvalLateContext<'a, 'tcx: 'a> { } impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { - /// simple constant folding: Insert an expression, get a constant or none. + /// Simple constant folding: Insert an expression, get a constant or none. pub fn expr(&mut self, e: &Expr) -> Option { match e.node { ExprKind::Path(ref qpath) => self.fetch_path(qpath, e.hir_id), @@ -238,7 +243,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { }), ExprKind::Binary(op, ref left, ref right) => self.binop(op, left, right), ExprKind::Call(ref callee, ref args) => { - // We only handle a few const functions for now + // We only handle a few const functions for now. if_chain! { if args.is_empty(); if let ExprKind::Path(qpath) = &callee.node; @@ -262,7 +267,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } }, - // TODO: add other expressions + // TODO: add other expressions. _ => None, } } @@ -304,13 +309,13 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } - /// create `Some(Vec![..])` of all constants, unless there is any - /// non-constant part + /// Create `Some(Vec![..])` of all constants, unless there is any + /// non-constant part. fn multi(&mut self, vec: &[Expr]) -> Option> { vec.iter().map(|elem| self.expr(elem)).collect::>() } - /// lookup a possibly constant expression from a ExprKind::Path + /// Lookup a possibly constant expression from a ExprKind::Path. fn fetch_path(&mut self, qpath: &QPath, id: HirId) -> Option { use rustc::mir::interpret::GlobalId; @@ -334,14 +339,14 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { if ret.is_some() { self.needed_resolution = true; } - return ret; + ret }, - _ => {}, + // FIXME: cover all useable cases. + _ => None, } - None } - /// A block can only yield a constant if it only has one constant expression + /// A block can only yield a constant if it only has one constant expression. fn block(&mut self, block: &Block) -> Option { if block.stmts.is_empty() { block.expr.as_ref().and_then(|b| self.expr(b)) @@ -467,7 +472,13 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' ty::Float(FloatTy::F64) => Some(Constant::F64(f64::from_bits( b.try_into().expect("invalid f64 bit representation"), ))), - // FIXME: implement other conversion + ty::RawPtr(type_and_mut) => { + if let ty::Uint(_) = type_and_mut.ty.sty { + return Some(Constant::RawPtr(b)); + } + None + }, + // FIXME: implement other conversions. _ => None, }, ConstValue::Slice(Scalar::Ptr(ptr), n) => match result.ty.sty { @@ -484,7 +495,7 @@ pub fn miri_to_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, result: &ty::Const<' }, _ => None, }, - // FIXME: implement other conversions + // FIXME: implement other conversions. _ => None, } } diff --git a/clippy_lints/src/enum_glob_use.rs b/clippy_lints/src/enum_glob_use.rs index 37575f10f195..afdf27376d80 100644 --- a/clippy_lints/src/enum_glob_use.rs +++ b/clippy_lints/src/enum_glob_use.rs @@ -39,9 +39,10 @@ impl LintPass for EnumGlobUse { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for EnumGlobUse { fn check_mod(&mut self, cx: &LateContext<'a, 'tcx>, m: &'tcx Mod, _: Span, _: HirId) { + let map = cx.tcx.hir(); // only check top level `use` statements for item in &m.item_ids { - self.lint_item(cx, cx.tcx.hir().expect_item(item.id)); + self.lint_item(cx, map.expect_item(map.hir_to_node_id(item.id))); } } } diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index 4788f57d070a..08376bc49d22 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,5 +1,5 @@ use crate::utils::{differing_macro_contexts, in_macro, snippet_opt, span_note_and_lint}; -use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; +use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use syntax::ast; use syntax::ptr::P; @@ -150,6 +150,7 @@ fn check_else(cx: &EarlyContext<'_>, expr: &ast::Expr) { if (is_block(else_) || unsugar_if(else_).is_some()) && !differing_macro_contexts(then.span, else_.span) && !in_macro(then.span) + && !in_external_macro(cx.sess, expr.span) { // workaround for rust-lang/rust#43081 if expr.span.lo().0 == 0 && expr.span.hi().0 == 0 { diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 5378f7d455f7..4313d040474a 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -256,8 +256,7 @@ impl<'a, 'tcx> Functions { hir_id: hir::HirId, ) { let expr = &body.value; - let node_id = cx.tcx.hir().hir_to_node_id(hir_id); - if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(node_id) { + if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(hir_id) { let raw_ptrs = iter_input_pats(decl, body) .zip(decl.inputs.iter()) .filter_map(|(arg, ty)| raw_ptr_arg(arg, ty)) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 4762ce760c9b..177c85adde58 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -148,9 +148,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item, trait_items } } - let trait_node_id = cx.tcx.hir().hir_to_node_id(visited_trait.hir_id); - - if cx.access_levels.is_exported(trait_node_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) { + if cx.access_levels.is_exported(visited_trait.hir_id) && trait_items.iter().any(|i| is_named_self(cx, i, "len")) { let mut current_and_super_traits = FxHashSet::default(); let visited_trait_def_id = cx.tcx.hir().local_def_id_from_hir_id(visited_trait.hir_id); fill_trait_set(visited_trait_def_id, &mut current_and_super_traits, cx); @@ -193,10 +191,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte } let is_empty = if let Some(is_empty) = impl_items.iter().find(|i| is_named_self(cx, i, "is_empty")) { - if cx - .access_levels - .is_exported(cx.tcx.hir().hir_to_node_id(is_empty.id.hir_id)) - { + if cx.access_levels.is_exported(is_empty.id.hir_id) { return; } else { "a private" @@ -206,7 +201,7 @@ fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item, impl_items: &[ImplIte }; if let Some(i) = impl_items.iter().find(|i| is_named_self(cx, i, "len")) { - if cx.access_levels.is_exported(cx.tcx.hir().hir_to_node_id(i.id.hir_id)) { + if cx.access_levels.is_exported(i.id.hir_id) { let def_id = cx.tcx.hir().local_def_id_from_hir_id(item.hir_id); let ty = cx.tcx.type_of(def_id); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index bf98aa7e2b58..d547e0a99b79 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -255,6 +255,7 @@ pub mod suspicious_trait_impl; pub mod swap; pub mod temporary_assignment; pub mod transmute; +pub mod transmuting_null; pub mod trivially_copy_pass_by_ref; pub mod types; pub mod unicode; @@ -279,7 +280,7 @@ mod reexport { /// /// Pre-expansion lints run before any macro expansion has happened. /// -/// Note that due to the architechture of the compiler, currently `cfg_attr` attributes on crate +/// Note that due to the architecture of the compiler, currently `cfg_attr` attributes on crate /// level (i.e `#![cfg_attr(...)]`) will still be expanded even when using a pre-expansion pass. /// /// Used in `./src/driver.rs`. @@ -570,6 +571,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box types::RefToMut); reg.register_late_lint_pass(box assertions_on_constants::AssertionsOnConstants); reg.register_late_lint_pass(box missing_const_for_fn::MissingConstForFn); + reg.register_late_lint_pass(box transmuting_null::Pass); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -841,6 +843,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { transmute::TRANSMUTE_PTR_TO_REF, transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, + transmuting_null::TRANSMUTING_NULL, trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF, types::ABSURD_EXTREME_COMPARISONS, types::BORROWED_BOX, @@ -1078,6 +1081,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL, swap::ALMOST_SWAPPED, transmute::WRONG_TRANSMUTE, + transmuting_null::TRANSMUTING_NULL, types::ABSURD_EXTREME_COMPARISONS, types::CAST_PTR_ALIGNMENT, types::CAST_REF_TO_MUT, diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 4b2ba60090f9..cd717e586e71 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -356,7 +356,8 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { self.collect_anonymous_lifetimes(path, ty); }, TyKind::Def(item, _) => { - if let ItemKind::Existential(ref exist_ty) = self.cx.tcx.hir().expect_item(item.id).node { + let map = self.cx.tcx.hir(); + if let ItemKind::Existential(ref exist_ty) = map.expect_item(map.hir_to_node_id(item.id)).node { for bound in &exist_ty.bounds { if let GenericBound::Outlives(_) = *bound { self.record(&None); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0016625631c7..c2b44ee7018b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -777,7 +777,7 @@ fn check_for_loop<'a, 'tcx>( check_for_loop_range(cx, pat, arg, body, expr); check_for_loop_reverse_range(cx, arg, expr); check_for_loop_arg(cx, pat, arg, expr); - check_for_loop_explicit_counter(cx, arg, body, expr); + check_for_loop_explicit_counter(cx, pat, arg, body, expr); check_for_loop_over_map_kv(cx, pat, arg, body, expr); check_for_mut_range_bound(cx, arg, body); detect_manual_memcpy(cx, pat, arg, body, expr); @@ -1453,6 +1453,7 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr) { fn check_for_loop_explicit_counter<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, + pat: &'tcx Pat, arg: &'tcx Expr, body: &'tcx Expr, expr: &'tcx Expr, @@ -1489,16 +1490,31 @@ fn check_for_loop_explicit_counter<'a, 'tcx>( if visitor2.state == VarState::Warn { if let Some(name) = visitor2.name { - span_lint( + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( cx, EXPLICIT_COUNTER_LOOP, expr.span, - &format!( - "the variable `{0}` is used as a loop counter. Consider using `for ({0}, \ - item) in {1}.enumerate()` or similar iterators", + &format!("the variable `{}` is used as a loop counter.", name), + "consider using", + format!( + "for ({}, {}) in {}.enumerate()", name, - snippet(cx, arg.span, "_") + snippet_with_applicability(cx, pat.span, "item", &mut applicability), + if higher::range(cx, arg).is_some() { + format!( + "({})", + snippet_with_applicability(cx, arg.span, "_", &mut applicability) + ) + } else { + format!( + "{}", + sugg::Sugg::hir_with_applicability(cx, arg, "_", &mut applicability) + .maybe_par() + ) + } ), + applicability, ); } } diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 74a85f1f8174..34cb2422e1c5 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -516,11 +516,11 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { for pat in &arm.pats { if let PatKind::Path(ref path) = pat.deref().node { if let QPath::Resolved(_, p) = path { - missing_variants.retain(|e| e.did != p.def.def_id()); + missing_variants.retain(|e| e.ctor_def_id != Some(p.def.def_id())); } } else if let PatKind::TupleStruct(ref path, ..) = pat.deref().node { if let QPath::Resolved(_, p) = path { - missing_variants.retain(|e| e.did != p.def.def_id()); + missing_variants.retain(|e| e.ctor_def_id != Some(p.def.def_id())); } } } @@ -539,7 +539,7 @@ fn check_wild_enum_match(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm]) { String::new() }; // This path assumes that the enum type is imported into scope. - format!("{}{}{}", ident_str, cx.tcx.def_path_str(v.did), suffix) + format!("{}{}{}", ident_str, cx.tcx.def_path_str(v.def_id), suffix) }) .collect(); diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 3e7403a3fe28..bccabe1a61d8 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -918,8 +918,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next(); if let hir::ItemKind::Impl(_, _, _, _, None, ref self_ty, _) = item.node; then { - let node_id = cx.tcx.hir().hir_to_node_id(implitem.hir_id); - if cx.access_levels.is_exported(node_id) { + if cx.access_levels.is_exported(implitem.hir_id) { // check missing trait implementations for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { if name == method_name && @@ -1636,7 +1635,7 @@ fn lint_get_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &hir::Expr, get_a let mut span = expr.span; - // Handle the case where the result is immedately dereferenced + // Handle the case where the result is immediately dereferenced // by not requiring ref and pulling the dereference into the // suggestion. if_chain! { @@ -2144,7 +2143,8 @@ fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx h then { let mut applicability = Applicability::MachineApplicable; let snip = snippet_with_applicability(cx, arg.span, "..", &mut applicability); - let hint = format!("'{}'", &snip[1..snip.len() - 1]); + let c = &snip[1..snip.len() - 1]; + let hint = format!("'{}'", if c == "'" { "\\'" } else { c }); span_lint_and_sugg( cx, SINGLE_CHAR_PATTERN, diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index ed984f16db5c..721cfd870201 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -58,9 +58,9 @@ impl MissingDoc { if let Some(meta) = meta; if let MetaItemKind::List(list) = meta.node; if let Some(meta) = list.get(0); - if let Some(name) = meta.ident_str(); + if let Some(name) = meta.ident(); then { - name == "include" + name.as_str() == "include" } else { false } diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index d6711900093e..c6b1b7eaf517 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -95,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { return; } - if !cx.access_levels.is_exported(cx.tcx.hir().hir_to_node_id(it.hir_id)) { + if !cx.access_levels.is_exported(it.hir_id) { return; } match it.node { @@ -146,8 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { } // If the item being implemented is not exported, then we don't need #[inline] - let node_id = cx.tcx.hir().hir_to_node_id(impl_item.hir_id); - if !cx.access_levels.is_exported(node_id) { + if !cx.access_levels.is_exported(impl_item.hir_id) { return; } @@ -163,12 +162,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { }; if let Some(trait_def_id) = trait_def_id { - if let Some(n) = cx.tcx.hir().as_local_node_id(trait_def_id) { - if !cx.access_levels.is_exported(n) { - // If a trait is being implemented for an item, and the - // trait is not exported, we don't need #[inline] - return; - } + if cx.tcx.hir().as_local_node_id(trait_def_id).is_some() && !cx.access_levels.is_exported(impl_item.hir_id) + { + // If a trait is being implemented for an item, and the + // trait is not exported, we don't need #[inline] + return; } } diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index fde4081ae8f5..3bf0c22c322c 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -111,7 +111,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { let name = impl_item.ident.name; let id = impl_item.hir_id; - let node_id = cx.tcx.hir().hir_to_node_id(id); if sig.header.constness == hir::Constness::Const { // can't be implemented by default return; @@ -129,7 +128,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { // impl of `Default` return; } - if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(node_id) { + if sig.decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { let self_did = cx.tcx.hir().local_def_id_from_hir_id(cx.tcx.hir().get_parent_item(id)); let self_ty = cx.tcx.type_of(self_did); if_chain! { diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index dae59bc84b95..74a9b353ea97 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -72,7 +72,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { if let ExprKind::Path(ref qpath) = callee.node { let def = cx.tables.qpath_def(qpath, callee.hir_id); match def { - Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => { + Def::Struct(..) | Def::Variant(..) | Def::Ctor(..) => { !has_drop(cx, cx.tables.expr_ty(expr)) && args.iter().all(|arg| has_no_effect(cx, arg)) }, _ => false, @@ -166,9 +166,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option - { + Def::Struct(..) | Def::Variant(..) | Def::Ctor(..) if !has_drop(cx, cx.tables.expr_ty(expr)) => { Some(args.iter().collect()) }, _ => None, diff --git a/clippy_lints/src/non_expressive_names.rs b/clippy_lints/src/non_expressive_names.rs index 7bdeec0a56f0..39d69d0bd51b 100644 --- a/clippy_lints/src/non_expressive_names.rs +++ b/clippy_lints/src/non_expressive_names.rs @@ -88,7 +88,33 @@ struct SimilarNamesLocalVisitor<'a, 'tcx: 'a> { names: Vec, cx: &'a EarlyContext<'tcx>, lint: &'a NonExpressiveNames, - single_char_names: Vec, + + /// A stack of scopes containing the single-character bindings in each scope. + single_char_names: Vec>, +} + +impl<'a, 'tcx: 'a> SimilarNamesLocalVisitor<'a, 'tcx> { + fn check_single_char_names(&self) { + let num_single_char_names = self.single_char_names.iter().flatten().count(); + let threshold = self.lint.single_char_binding_names_threshold; + if num_single_char_names as u64 >= threshold { + let span = self + .single_char_names + .iter() + .flatten() + .map(|ident| ident.span) + .collect::>(); + span_lint( + self.cx, + MANY_SINGLE_CHAR_NAMES, + span, + &format!( + "{} bindings with single-character names in scope", + num_single_char_names + ), + ); + } + } } // this list contains lists of names that are allowed to be similar @@ -109,7 +135,7 @@ struct SimilarNamesNameVisitor<'a: 'b, 'tcx: 'a, 'b>(&'b mut SimilarNamesLocalVi impl<'a, 'tcx: 'a, 'b> Visitor<'tcx> for SimilarNamesNameVisitor<'a, 'tcx, 'b> { fn visit_pat(&mut self, pat: &'tcx Pat) { match pat.node { - PatKind::Ident(_, ident, _) => self.check_name(ident.span, ident.name), + PatKind::Ident(_, ident, _) => self.check_ident(ident), PatKind::Struct(_, ref fields, _) => { for field in fields { if !field.node.is_shorthand { @@ -140,27 +166,24 @@ fn whitelisted(interned_name: &str, list: &[&str]) -> bool { } impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { - fn check_short_name(&mut self, c: char, span: Span) { - // make sure we ignore shadowing - if self.0.single_char_names.contains(&c) { + fn check_short_ident(&mut self, ident: Ident) { + // Ignore shadowing + if self + .0 + .single_char_names + .iter() + .flatten() + .any(|id| id.name == ident.name) + { return; - } - self.0.single_char_names.push(c); - if self.0.single_char_names.len() as u64 >= self.0.lint.single_char_binding_names_threshold { - span_lint( - self.0.cx, - MANY_SINGLE_CHAR_NAMES, - span, - &format!( - "{}th binding whose name is just one char", - self.0.single_char_names.len() - ), - ); + } else if let Some(scope) = &mut self.0.single_char_names.last_mut() { + scope.push(ident); } } + #[allow(clippy::too_many_lines)] - fn check_name(&mut self, span: Span, name: Name) { - let interned_name = name.as_str(); + fn check_ident(&mut self, ident: Ident) { + let interned_name = ident.name.as_str(); if interned_name.chars().any(char::is_uppercase) { return; } @@ -168,7 +191,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { span_lint( self.0.cx, JUST_UNDERSCORES_AND_DIGITS, - span, + ident.span, "consider choosing a more descriptive name", ); return; @@ -176,8 +199,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { let count = interned_name.chars().count(); if count < 3 { if count == 1 { - let c = interned_name.chars().next().expect("already checked"); - self.check_short_name(c, span); + self.check_short_ident(ident); } return; } @@ -247,13 +269,13 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { span_lint_and_then( self.0.cx, SIMILAR_NAMES, - span, + ident.span, "binding's name is too similar to existing binding", |diag| { diag.span_note(existing_name.span, "existing binding defined here"); if let Some(split) = split_at { diag.span_help( - span, + ident.span, &format!( "separate the discriminating character by an \ underscore like: `{}_{}`", @@ -269,7 +291,7 @@ impl<'a, 'tcx, 'b> SimilarNamesNameVisitor<'a, 'tcx, 'b> { self.0.names.push(ExistingName { whitelist: get_whitelist(&interned_name).unwrap_or(&[]), interned: interned_name, - span, + span: ident.span, len: count, }); } @@ -297,15 +319,25 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> { SimilarNamesNameVisitor(self).visit_pat(&*local.pat); } fn visit_block(&mut self, blk: &'tcx Block) { + self.single_char_names.push(vec![]); + self.apply(|this| walk_block(this, blk)); + + self.check_single_char_names(); + self.single_char_names.pop(); } fn visit_arm(&mut self, arm: &'tcx Arm) { + self.single_char_names.push(vec![]); + self.apply(|this| { // just go through the first pattern, as either all patterns // bind the same bindings or rustc would have errored much earlier SimilarNamesNameVisitor(this).visit_pat(&arm.pats[0]); this.apply(|this| walk_expr(this, &arm.body)); }); + + self.check_single_char_names(); + self.single_char_names.pop(); } fn visit_item(&mut self, _: &Item) { // do not recurse into inner items @@ -335,14 +367,17 @@ fn do_check(lint: &mut NonExpressiveNames, cx: &EarlyContext<'_>, attrs: &[Attri names: Vec::new(), cx, lint, - single_char_names: Vec::new(), + single_char_names: vec![vec![]], }; + // initialize with function arguments for arg in &decl.inputs { SimilarNamesNameVisitor(&mut visitor).visit_pat(&arg.pat); } // walk all other bindings walk_block(&mut visitor, blk); + + visitor.check_single_char_names(); } } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 7821ad56ccc8..5c64cd1c15c7 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -128,7 +128,7 @@ impl Pass { }, ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr), ExprKind::Path(ref qp) => { - if let Def::VariantCtor(def_id, _) = cx.tables.qpath_def(qp, expression.hir_id) { + if let Def::Ctor(def_id, def::CtorOf::Variant, _) = cx.tables.qpath_def(qp, expression.hir_id) { return match_def_path(cx.tcx, def_id, &OPTION_NONE); } diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 18dfb963230b..84c9509844fc 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -157,25 +157,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { }) = higher::range(cx, expr); if let Some(y) = y_plus_one(end); then { + let span = expr.span + .ctxt() + .outer() + .expn_info() + .map_or(expr.span, |info| info.call_site); span_lint_and_then( cx, RANGE_PLUS_ONE, - expr.span, + span, "an inclusive range would be more readable", |db| { let start = start.map_or(String::new(), |x| Sugg::hir(cx, x, "x").to_string()); let end = Sugg::hir(cx, y, "y"); - if let Some(is_wrapped) = &snippet_opt(cx, expr.span) { + if let Some(is_wrapped) = &snippet_opt(cx, span) { if is_wrapped.starts_with('(') && is_wrapped.ends_with(')') { db.span_suggestion( - expr.span, + span, "use", format!("({}..={})", start, end), Applicability::MaybeIncorrect, ); } else { db.span_suggestion( - expr.span, + span, "use", format!("{}..={}", start, end), Applicability::MachineApplicable, // snippet diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 086c76c20b63..c764e0ceb837 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -299,7 +299,7 @@ fn base_local_and_movability<'tcx>( place = &proj.base; deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref); if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) { - field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).to_ty(cx.tcx)); + field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).ty); } }, _ => return None, diff --git a/clippy_lints/src/transmuting_null.rs b/clippy_lints/src/transmuting_null.rs new file mode 100644 index 000000000000..445abc4832aa --- /dev/null +++ b/clippy_lints/src/transmuting_null.rs @@ -0,0 +1,112 @@ +use crate::consts::{constant_context, Constant}; +use crate::utils::{match_qpath, span_lint}; +use if_chain::if_chain; +use rustc::hir::{Expr, ExprKind}; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use syntax::ast::LitKind; + +declare_clippy_lint! { + /// **What it does:** Checks for transmute calls which would receive a null pointer. + /// + /// **Why is this bad?** Transmuting a null pointer is undefined behavior. + /// + /// **Known problems:** Not all cases can be detected at the moment of this writing. + /// For example, variables which hold a null pointer and are then fed to a `transmute` + /// call, aren't detectable yet. + /// + /// **Example:** + /// ```rust + /// let null_ref: &u64 = unsafe { std::mem::transmute(0 as *const u64) }; + /// ``` + pub TRANSMUTING_NULL, + correctness, + "transmutes from a null pointer to a reference, which is undefined behavior" +} + +#[derive(Copy, Clone)] +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(TRANSMUTING_NULL,) + } + + fn name(&self) -> &'static str { + "TransmutingNull" + } +} + +const LINT_MSG: &str = "transmuting a known null pointer into a reference."; + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { + fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { + if in_external_macro(cx.sess(), expr.span) { + return; + } + + if_chain! { + if let ExprKind::Call(ref func, ref args) = expr.node; + if let ExprKind::Path(ref path) = func.node; + if match_qpath(path, &["std", "mem", "transmute"]); + if args.len() == 1; + + then { + + // Catching transmute over constants that resolve to `null`. + let mut const_eval_context = constant_context(cx, cx.tables); + if_chain! { + if let ExprKind::Path(ref _qpath) = args[0].node; + let x = const_eval_context.expr(&args[0]); + if let Some(constant) = x; + if let Constant::RawPtr(ptr_value) = constant; + if ptr_value == 0; + then { + span_lint( + cx, + TRANSMUTING_NULL, + expr.span, + LINT_MSG) + } + } + + // Catching: + // `std::mem::transmute(0 as *const i32)` + if_chain! { + if let ExprKind::Cast(ref inner_expr, ref _cast_ty) = args[0].node; + if let ExprKind::Lit(ref lit) = inner_expr.node; + if let LitKind::Int(0, _) = lit.node; + then { + span_lint( + cx, + TRANSMUTING_NULL, + expr.span, + LINT_MSG) + } + } + + // Catching: + // `std::mem::transmute(std::ptr::null::())` + if_chain! { + if let ExprKind::Call(ref func1, ref args1) = args[0].node; + if let ExprKind::Path(ref path1) = func1.node; + if match_qpath(path1, &["std", "ptr", "null"]); + if args1.len() == 0; + then { + span_lint( + cx, + TRANSMUTING_NULL, + expr.span, + LINT_MSG) + } + } + + // FIXME: + // Also catch transmutations of variables which are known nulls. + // To do this, MIR const propagation seems to be the better tool. + // Whenever MIR const prop routines are more developed, this will + // become available. As of this writing (25/03/19) it is not yet. + } + } + } +} diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 2e50222c8a9f..95609d3f3029 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1533,7 +1533,7 @@ impl LintPass for CharLitAsU8 { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CharLitAsU8 { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - use syntax::ast::{LitKind, UintTy}; + use syntax::ast::LitKind; if let ExprKind::Cast(ref e, _) = expr.node { if let ExprKind::Lit(ref l) = e.node { @@ -1818,7 +1818,6 @@ impl Ord for FullInt { fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<(FullInt, FullInt)> { use std::*; - use syntax::ast::{IntTy, UintTy}; if let ExprKind::Cast(ref cast_exp, _) = expr.node { let pre_cast_ty = cx.tables.expr_ty(cast_exp); @@ -2075,7 +2074,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { } } - if !cx.access_levels.is_exported(cx.tcx.hir().hir_to_node_id(item.hir_id)) { + if !cx.access_levels.is_exported(item.hir_id) { return; } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index ac901ab062f3..d3b011a3bd98 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -233,7 +233,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { if path.segments.last().expect(SEGMENTS_MSG).ident.name != SelfUpper.name() { if self.item_path.def == path.def { span_use_self_lint(self.cx, path); - } else if let Def::StructCtor(ctor_did, CtorKind::Fn) = path.def { + } else if let Def::Ctor(ctor_did, def::CtorOf::Struct, CtorKind::Fn) = path.def { if self.item_path.def.opt_def_id() == self.cx.tcx.parent(ctor_did) { span_use_self_lint(self.cx, path); } diff --git a/clippy_lints/src/utils/diagnostics.rs b/clippy_lints/src/utils/diagnostics.rs index fa9a7dac9a0b..5be0a67c64d0 100644 --- a/clippy_lints/src/utils/diagnostics.rs +++ b/clippy_lints/src/utils/diagnostics.rs @@ -5,7 +5,7 @@ use rustc::lint::{LateContext, Lint, LintContext}; use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart, SuggestionStyle}; use std::env; use syntax::errors::DiagnosticBuilder; -use syntax::source_map::Span; +use syntax::source_map::{MultiSpan, Span}; /// Wrapper around `DiagnosticBuilder` that adds a link to Clippy documentation for the emitted lint struct DiagnosticWrapper<'a>(DiagnosticBuilder<'a>); @@ -48,7 +48,7 @@ impl<'a> DiagnosticWrapper<'a> { /// 17 | std::mem::forget(seven); /// | ^^^^^^^^^^^^^^^^^^^^^^^ /// ``` -pub fn span_lint<'a, T: LintContext<'a>>(cx: &T, lint: &'static Lint, sp: Span, msg: &str) { +pub fn span_lint<'a, T: LintContext<'a>>(cx: &T, lint: &'static Lint, sp: impl Into, msg: &str) { DiagnosticWrapper(cx.struct_span_lint(lint, sp, msg)).docs_link(lint); } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 2cf638b939cc..3590b7ae9eea 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -27,7 +27,7 @@ use rustc::hir::def::Def; use rustc::hir::def_id::CrateNum; use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::hir::intravisit::{NestedVisitorMap, Visitor}; -use rustc::hir::map::DisambiguatedDefPathData; +use rustc::hir::map::{DefPathData, DisambiguatedDefPathData}; use rustc::hir::Node; use rustc::hir::*; use rustc::lint::{LateContext, Level, Lint, LintContext}; @@ -178,6 +178,12 @@ impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> { disambiguated_data: &DisambiguatedDefPathData, ) -> Result { let mut path = print_prefix(self)?; + + // Skip `::{{constructor}}` on tuple/unit structs. + if let DefPathData::Ctor = disambiguated_data.data { + return Ok(path); + } + path.push(disambiguated_data.data.as_interned_str().as_str()); Ok(path) } @@ -863,7 +869,7 @@ pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat) -> bool { fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath, id: HirId) -> bool { matches!( cx.tables.qpath_def(qpath, id), - def::Def::Variant(..) | def::Def::VariantCtor(..) + def::Def::Variant(..) | def::Def::Ctor(_, def::CtorOf::Variant, _) ) } diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 51cedfef0f71..9b8b2372c53b 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -59,6 +59,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { then { // report the error around the `vec!` not inside `:` let span = arg.span + .ctxt() + .outer() + .expn_info() + .map(|info| info.call_site) + .expect("unable to get call_site") .ctxt() .outer() .expn_info() diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 53e671e17e03..a45551dbf9c5 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -115,7 +115,7 @@ where all the lint code is. We are going to call the file `clippy_lints/src/foo_functions.rs` and import some initial things we need: ```rust -use rustc::lint::{LintArray, LintPass}; +use rustc::lint::{LintArray, LintPass, EarlyLintPass}; use rustc::{declare_tool_lint, lint_array}; ``` @@ -161,6 +161,8 @@ impl LintPass for FooFunctionsPass { "FooFunctions" } } + +impl EarlyLintPass for FooFunctionsPass {} ``` Don't worry about the `name` method here. As long as it includes the name of the diff --git a/src/driver.rs b/src/driver.rs index 01358f46dd70..834d11861c0d 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -93,7 +93,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { ls.register_early_pass(Some(sess), true, false, pass); } for pass in late_lint_passes { - ls.register_late_pass(Some(sess), true, pass); + ls.register_late_pass(Some(sess), true, false, false, pass); } for (name, (to, deprecated_name)) in lint_groups { diff --git a/tests/compile-test.rs b/tests/compile-test.rs index b6a4beff0469..bafd64e934f3 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -74,6 +74,7 @@ fn run_mode(mode: &str, dir: PathBuf) { compiletest::run_tests(&cfg); } +#[allow(clippy::identity_conversion)] fn run_ui_toml_tests(config: &compiletest::Config, mut tests: Vec) -> Result { let mut result = true; let opts = compiletest::test_opts(config); diff --git a/tests/ui-toml/functions_maxlines/test.rs b/tests/ui-toml/functions_maxlines/test.rs index cd0e00825861..a47677a1f3a2 100644 --- a/tests/ui-toml/functions_maxlines/test.rs +++ b/tests/ui-toml/functions_maxlines/test.rs @@ -38,7 +38,7 @@ fn comment_after_code() { fn comment_before_code() { let _ = "test"; /* This comment extends to the front of - teh code but this line should still count. */ let _ = 5; + the code but this line should still count. */ let _ = 5; } // This should be considered one line. diff --git a/tests/ui-toml/functions_maxlines/test.stderr b/tests/ui-toml/functions_maxlines/test.stderr index 0669e99370b2..4b77ac551e77 100644 --- a/tests/ui-toml/functions_maxlines/test.stderr +++ b/tests/ui-toml/functions_maxlines/test.stderr @@ -15,7 +15,7 @@ error: This function has a large number of lines. LL | / fn comment_before_code() { LL | | let _ = "test"; LL | | /* This comment extends to the front of -LL | | teh code but this line should still count. */ let _ = 5; +LL | | the code but this line should still count. */ let _ = 5; LL | | } | |_^ diff --git a/tests/ui/crashes/associated-constant-ice.rs b/tests/ui/crashes/associated-constant-ice.rs index 948deba3ea6e..4bb833795bb1 100644 --- a/tests/ui/crashes/associated-constant-ice.rs +++ b/tests/ui/crashes/associated-constant-ice.rs @@ -1,3 +1,5 @@ +// run-pass + /// Test for https://github.com/rust-lang/rust-clippy/issues/1698 pub trait Trait { diff --git a/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/tests/ui/crashes/auxiliary/proc_macro_crash.rs new file mode 100644 index 000000000000..71b10ed4db4d --- /dev/null +++ b/tests/ui/crashes/auxiliary/proc_macro_crash.rs @@ -0,0 +1,37 @@ +// no-prefer-dynamic +// ^ compiletest by default builds all aux files as dylibs, but we don't want that for proc-macro +// crates. If we don't set this, compiletest will override the `crate_type` attribute below and +// compile this as dylib. Removing this then causes the test to fail because a `dylib` crate can't +// contain a proc-macro. + +#![feature(repr128)] +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::{Delimiter, Group, Ident, Span, TokenStream, TokenTree}; +use std::iter::FromIterator; + +#[proc_macro] +pub fn macro_test(input_stream: TokenStream) -> TokenStream { + let first_token = input_stream.into_iter().next().unwrap(); + let span = first_token.span(); + + TokenStream::from_iter(vec![ + TokenTree::Ident(Ident::new("fn", Span::call_site())), + TokenTree::Ident(Ident::new("code", Span::call_site())), + TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())), + TokenTree::Group(Group::new(Delimiter::Brace, { + let mut clause = Group::new(Delimiter::Brace, TokenStream::new()); + clause.set_span(span); + + TokenStream::from_iter(vec![ + TokenTree::Ident(Ident::new("if", Span::call_site())), + TokenTree::Ident(Ident::new("true", Span::call_site())), + TokenTree::Group(clause.clone()), + TokenTree::Ident(Ident::new("else", Span::call_site())), + TokenTree::Group(clause.clone()), + ]) + })), + ]) +} diff --git a/tests/ui/crashes/cc_seme.rs b/tests/ui/crashes/cc_seme.rs index 98588be9cf82..c48c7e9e6c6b 100644 --- a/tests/ui/crashes/cc_seme.rs +++ b/tests/ui/crashes/cc_seme.rs @@ -1,3 +1,5 @@ +// run-pass + #[allow(dead_code)] /// Test for https://github.com/rust-lang/rust-clippy/issues/478 diff --git a/tests/ui/crashes/enum-glob-import-crate.rs b/tests/ui/crashes/enum-glob-import-crate.rs index dca32aa3b561..db1fa871afe0 100644 --- a/tests/ui/crashes/enum-glob-import-crate.rs +++ b/tests/ui/crashes/enum-glob-import-crate.rs @@ -1,3 +1,5 @@ +// run-pass + #![deny(clippy::all)] #![allow(unused_imports)] diff --git a/tests/ui/crashes/ice-1588.rs b/tests/ui/crashes/ice-1588.rs index b0a3d11bce46..15d0f705b367 100644 --- a/tests/ui/crashes/ice-1588.rs +++ b/tests/ui/crashes/ice-1588.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow(clippy::all)] /// Test for https://github.com/rust-lang/rust-clippy/issues/1588 diff --git a/tests/ui/crashes/ice-1782.rs b/tests/ui/crashes/ice-1782.rs index 81af88962a64..1ca6b6976b38 100644 --- a/tests/ui/crashes/ice-1782.rs +++ b/tests/ui/crashes/ice-1782.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow(dead_code, unused_variables)] /// Should not trigger an ICE in `SpanlessEq` / `consts::constant` diff --git a/tests/ui/crashes/ice-1969.rs b/tests/ui/crashes/ice-1969.rs index 96a8fe6c24d5..837ec9df31ab 100644 --- a/tests/ui/crashes/ice-1969.rs +++ b/tests/ui/crashes/ice-1969.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow(clippy::all)] /// Test for https://github.com/rust-lang/rust-clippy/issues/1969 diff --git a/tests/ui/crashes/ice-2499.rs b/tests/ui/crashes/ice-2499.rs index 45b3b1869dde..ffef1631775e 100644 --- a/tests/ui/crashes/ice-2499.rs +++ b/tests/ui/crashes/ice-2499.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` diff --git a/tests/ui/crashes/ice-2594.rs b/tests/ui/crashes/ice-2594.rs index 3f3986b6fc69..ac19f1976e91 100644 --- a/tests/ui/crashes/ice-2594.rs +++ b/tests/ui/crashes/ice-2594.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow(dead_code, unused_variables)] /// Should not trigger an ICE in `SpanlessHash` / `consts::constant` diff --git a/tests/ui/crashes/ice-2727.rs b/tests/ui/crashes/ice-2727.rs index 56024abc8f58..d832c2860332 100644 --- a/tests/ui/crashes/ice-2727.rs +++ b/tests/ui/crashes/ice-2727.rs @@ -1,3 +1,5 @@ +// run-pass + /// Test for https://github.com/rust-lang/rust-clippy/issues/2727 pub fn f(new: fn()) { diff --git a/tests/ui/crashes/ice-2760.rs b/tests/ui/crashes/ice-2760.rs index f1a229f3f4fa..9e5e299c336a 100644 --- a/tests/ui/crashes/ice-2760.rs +++ b/tests/ui/crashes/ice-2760.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow( unused_variables, clippy::blacklisted_name, diff --git a/tests/ui/crashes/ice-2774.rs b/tests/ui/crashes/ice-2774.rs index d44b0fae8200..47f8e3b18eea 100644 --- a/tests/ui/crashes/ice-2774.rs +++ b/tests/ui/crashes/ice-2774.rs @@ -1,3 +1,5 @@ +// run-pass + use std::collections::HashSet; // See rust-lang/rust-clippy#2774. diff --git a/tests/ui/crashes/ice-2865.rs b/tests/ui/crashes/ice-2865.rs index 6b1ceb505693..c4f6c0fed682 100644 --- a/tests/ui/crashes/ice-2865.rs +++ b/tests/ui/crashes/ice-2865.rs @@ -1,3 +1,5 @@ +// run-pass + #[allow(dead_code)] /// Test for https://github.com/rust-lang/rust-clippy/issues/2865 diff --git a/tests/ui/crashes/ice-3151.rs b/tests/ui/crashes/ice-3151.rs index fef4d7db84dd..ffad2d06b56e 100644 --- a/tests/ui/crashes/ice-3151.rs +++ b/tests/ui/crashes/ice-3151.rs @@ -1,3 +1,5 @@ +// run-pass + /// Test for https://github.com/rust-lang/rust-clippy/issues/2865 #[derive(Clone)] diff --git a/tests/ui/crashes/ice-3462.rs b/tests/ui/crashes/ice-3462.rs index 7d62e315da2f..95c7dff9be36 100644 --- a/tests/ui/crashes/ice-3462.rs +++ b/tests/ui/crashes/ice-3462.rs @@ -1,3 +1,5 @@ +// run-pass + #![warn(clippy::all)] #![allow(clippy::blacklisted_name)] #![allow(unused)] diff --git a/tests/ui/crashes/ice-3741.rs b/tests/ui/crashes/ice-3741.rs new file mode 100644 index 000000000000..74b9c9c86c81 --- /dev/null +++ b/tests/ui/crashes/ice-3741.rs @@ -0,0 +1,12 @@ +// aux-build:proc_macro_crash.rs +// run-pass + +#![feature(proc_macro_hygiene)] +#![warn(clippy::suspicious_else_formatting)] + +extern crate proc_macro_crash; +use proc_macro_crash::macro_test; + +fn main() { + macro_test!(2); +} diff --git a/tests/ui/crashes/ice-3747.rs b/tests/ui/crashes/ice-3747.rs index cdf018cbc88d..d0b44ebafeeb 100644 --- a/tests/ui/crashes/ice-3747.rs +++ b/tests/ui/crashes/ice-3747.rs @@ -1,3 +1,5 @@ +// run-pass + /// Test for https://github.com/rust-lang/rust-clippy/issues/3747 macro_rules! a { diff --git a/tests/ui/crashes/ice-700.rs b/tests/ui/crashes/ice-700.rs index 0cbceedbd6bd..b06df83d51a5 100644 --- a/tests/ui/crashes/ice-700.rs +++ b/tests/ui/crashes/ice-700.rs @@ -1,3 +1,5 @@ +// run-pass + #![deny(clippy::all)] /// Test for https://github.com/rust-lang/rust-clippy/issues/700 diff --git a/tests/ui/crashes/ice_exacte_size.rs b/tests/ui/crashes/ice_exacte_size.rs index 30e4b11ec0bd..e02eb28ab865 100644 --- a/tests/ui/crashes/ice_exacte_size.rs +++ b/tests/ui/crashes/ice_exacte_size.rs @@ -1,3 +1,5 @@ +// run-pass + #![deny(clippy::all)] /// Test for https://github.com/rust-lang/rust-clippy/issues/1336 diff --git a/tests/ui/crashes/if_same_then_else.rs b/tests/ui/crashes/if_same_then_else.rs index 7b3b881316df..b2a4d541f599 100644 --- a/tests/ui/crashes/if_same_then_else.rs +++ b/tests/ui/crashes/if_same_then_else.rs @@ -1,3 +1,5 @@ +// run-pass + #![deny(clippy::if_same_then_else)] /// Test for https://github.com/rust-lang/rust-clippy/issues/2426 diff --git a/tests/ui/crashes/issue-2862.rs b/tests/ui/crashes/issue-2862.rs index 38e2341e2782..3587a08eab7e 100644 --- a/tests/ui/crashes/issue-2862.rs +++ b/tests/ui/crashes/issue-2862.rs @@ -1,3 +1,5 @@ +// run-pass + /// Test for https://github.com/rust-lang/rust-clippy/issues/2826 pub trait FooMap { diff --git a/tests/ui/crashes/issue-825.rs b/tests/ui/crashes/issue-825.rs index 05696e3d7d56..3d4a88ab3c4e 100644 --- a/tests/ui/crashes/issue-825.rs +++ b/tests/ui/crashes/issue-825.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow(warnings)] /// Test for https://github.com/rust-lang/rust-clippy/issues/825 diff --git a/tests/ui/crashes/issues_loop_mut_cond.rs b/tests/ui/crashes/issues_loop_mut_cond.rs index bb238c81ebc0..c4acd5cda1b0 100644 --- a/tests/ui/crashes/issues_loop_mut_cond.rs +++ b/tests/ui/crashes/issues_loop_mut_cond.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow(dead_code)] /// Issue: https://github.com/rust-lang/rust-clippy/issues/2596 diff --git a/tests/ui/crashes/match_same_arms_const.rs b/tests/ui/crashes/match_same_arms_const.rs index 94c939665e61..848f0ea52ca5 100644 --- a/tests/ui/crashes/match_same_arms_const.rs +++ b/tests/ui/crashes/match_same_arms_const.rs @@ -1,3 +1,5 @@ +// run-pass + #![deny(clippy::match_same_arms)] /// Test for https://github.com/rust-lang/rust-clippy/issues/2427 diff --git a/tests/ui/crashes/mut_mut_macro.rs b/tests/ui/crashes/mut_mut_macro.rs index 6ce3b37a855f..14219f574c59 100644 --- a/tests/ui/crashes/mut_mut_macro.rs +++ b/tests/ui/crashes/mut_mut_macro.rs @@ -1,3 +1,5 @@ +// run-pass + #![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)] #![allow(dead_code)] diff --git a/tests/ui/crashes/needless_borrow_fp.rs b/tests/ui/crashes/needless_borrow_fp.rs index 4f61c76828db..48507efe1e98 100644 --- a/tests/ui/crashes/needless_borrow_fp.rs +++ b/tests/ui/crashes/needless_borrow_fp.rs @@ -1,3 +1,5 @@ +// run-pass + #[deny(clippy::all)] #[derive(Debug)] pub enum Error { diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.rs b/tests/ui/crashes/needless_lifetimes_impl_trait.rs index 676564b2445d..bd1fa4a0b1ef 100644 --- a/tests/ui/crashes/needless_lifetimes_impl_trait.rs +++ b/tests/ui/crashes/needless_lifetimes_impl_trait.rs @@ -1,3 +1,5 @@ +// run-pass + #![deny(clippy::needless_lifetimes)] #![allow(dead_code)] diff --git a/tests/ui/crashes/procedural_macro.rs b/tests/ui/crashes/procedural_macro.rs index c7468493380c..f79d9ab6460b 100644 --- a/tests/ui/crashes/procedural_macro.rs +++ b/tests/ui/crashes/procedural_macro.rs @@ -1,3 +1,5 @@ +// run-pass + #[macro_use] extern crate clippy_mini_macro_test; diff --git a/tests/ui/crashes/regressions.rs b/tests/ui/crashes/regressions.rs index 84470addd4a0..623ae51f9f08 100644 --- a/tests/ui/crashes/regressions.rs +++ b/tests/ui/crashes/regressions.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow(clippy::blacklisted_name)] pub fn foo(bar: *const u8) { diff --git a/tests/ui/crashes/returns.rs b/tests/ui/crashes/returns.rs index 8021ed4607dd..f2153efc3880 100644 --- a/tests/ui/crashes/returns.rs +++ b/tests/ui/crashes/returns.rs @@ -1,3 +1,5 @@ +// run-pass + /// Test for https://github.com/rust-lang/rust-clippy/issues/1346 #[deny(warnings)] diff --git a/tests/ui/crashes/single-match-else.rs b/tests/ui/crashes/single-match-else.rs index 1ba7ac082132..3a4bbe310cca 100644 --- a/tests/ui/crashes/single-match-else.rs +++ b/tests/ui/crashes/single-match-else.rs @@ -1,3 +1,5 @@ +// run-pass + #![warn(clippy::single_match_else)] //! Test for https://github.com/rust-lang/rust-clippy/issues/1588 diff --git a/tests/ui/crashes/used_underscore_binding_macro.rs b/tests/ui/crashes/used_underscore_binding_macro.rs index 6d2124c12fe9..265017c51d92 100644 --- a/tests/ui/crashes/used_underscore_binding_macro.rs +++ b/tests/ui/crashes/used_underscore_binding_macro.rs @@ -1,3 +1,5 @@ +// run-pass + #![allow(clippy::useless_attribute)] //issue #2910 #[macro_use] diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs index 5efac85cf220..71ef1e8674ac 100644 --- a/tests/ui/explicit_counter_loop.rs +++ b/tests/ui/explicit_counter_loop.rs @@ -113,3 +113,12 @@ mod issue_3308 { } } } + +mod issue_1670 { + pub fn test() { + let mut count = 0; + for _i in 3..10 { + count += 1; + } + } +} diff --git a/tests/ui/explicit_counter_loop.stderr b/tests/ui/explicit_counter_loop.stderr index b1cfb31432f2..5efd51abf181 100644 --- a/tests/ui/explicit_counter_loop.stderr +++ b/tests/ui/explicit_counter_loop.stderr @@ -1,28 +1,34 @@ -error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators +error: the variable `_index` is used as a loop counter. --> $DIR/explicit_counter_loop.rs:6:15 | LL | for _v in &vec { - | ^^^^ + | ^^^^ help: consider using: `for (_index, _v) in (&vec).enumerate()` | = note: `-D clippy::explicit-counter-loop` implied by `-D warnings` -error: the variable `_index` is used as a loop counter. Consider using `for (_index, item) in &vec.enumerate()` or similar iterators +error: the variable `_index` is used as a loop counter. --> $DIR/explicit_counter_loop.rs:12:15 | LL | for _v in &vec { - | ^^^^ + | ^^^^ help: consider using: `for (_index, _v) in (&vec).enumerate()` -error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators +error: the variable `count` is used as a loop counter. --> $DIR/explicit_counter_loop.rs:51:19 | LL | for ch in text.chars() { - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()` -error: the variable `count` is used as a loop counter. Consider using `for (count, item) in text.chars().enumerate()` or similar iterators +error: the variable `count` is used as a loop counter. --> $DIR/explicit_counter_loop.rs:62:19 | LL | for ch in text.chars() { - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ help: consider using: `for (count, ch) in text.chars().enumerate()` -error: aborting due to 4 previous errors +error: the variable `count` is used as a loop counter. + --> $DIR/explicit_counter_loop.rs:120:19 + | +LL | for _i in 3..10 { + | ^^^^^ help: consider using: `for (count, _i) in (3..10).enumerate()` + +error: aborting due to 5 previous errors diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index e8964c26796e..c1ad23614840 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -198,7 +198,7 @@ error: it is more concise to loop over references to containers instead of using --> $DIR/for_loop.rs:170:15 | LL | for _v in vec.iter() {} - | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` + | ^^^^^^^^^^ | = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` @@ -206,13 +206,13 @@ error: it is more concise to loop over references to containers instead of using --> $DIR/for_loop.rs:172:15 | LL | for _v in vec.iter_mut() {} - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` + | ^^^^^^^^^^^^^^ error: it is more concise to loop over containers instead of using explicit iteration methods` --> $DIR/for_loop.rs:175:15 | LL | for _v in out_vec.into_iter() {} - | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` + | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` @@ -220,61 +220,61 @@ error: it is more concise to loop over references to containers instead of using --> $DIR/for_loop.rs:178:15 | LL | for _v in array.into_iter() {} - | ^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&array` + | ^^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:183:15 | LL | for _v in [1, 2, 3].iter() {} - | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` + | ^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:187:15 | LL | for _v in [0; 32].iter() {} - | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` + | ^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:192:15 | LL | for _v in ll.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&ll` + | ^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:195:15 | LL | for _v in vd.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&vd` + | ^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:198:15 | LL | for _v in bh.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bh` + | ^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:201:15 | LL | for _v in hm.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&hm` + | ^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:204:15 | LL | for _v in bt.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bt` + | ^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:207:15 | LL | for _v in hs.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&hs` + | ^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods --> $DIR/for_loop.rs:210:15 | LL | for _v in bs.iter() {} - | ^^^^^^^^^ help: to write this more concisely, try: `&bs` + | ^^^^^^^^^ error: you are iterating over `Iterator::next()` which is an Option; this will compile but is probably not what you want --> $DIR/for_loop.rs:212:15 diff --git a/tests/ui/into_iter_on_ref.fixed b/tests/ui/into_iter_on_ref.fixed index f5342be631b0..659fd56f9a9d 100644 --- a/tests/ui/into_iter_on_ref.fixed +++ b/tests/ui/into_iter_on_ref.fixed @@ -10,7 +10,7 @@ fn main() { for _ in &[1, 2, 3] {} for _ in vec![X, X] {} for _ in &vec![X, X] {} - for _ in [1, 2, 3].iter() {} //~ ERROR equivalent to .iter() + for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter() let _ = [1, 2, 3].iter(); //~ ERROR equivalent to .iter() let _ = vec![1, 2, 3].into_iter(); diff --git a/tests/ui/into_iter_on_ref.stderr b/tests/ui/into_iter_on_ref.stderr index 931e4880f938..c3e5c85618b8 100644 --- a/tests/ui/into_iter_on_ref.stderr +++ b/tests/ui/into_iter_on_ref.stderr @@ -1,8 +1,8 @@ error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:13:24 + --> $DIR/into_iter_on_ref.rs:15:23 | -LL | for _ in [1, 2, 3].into_iter() {} //~ ERROR equivalent to .iter() - | ^^^^^^^^^ help: call directly: `iter` +LL | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter() + | ^^^^^^^^^ help: call directly: `iter` | note: lint level defined here --> $DIR/into_iter_on_ref.rs:4:9 @@ -10,12 +10,6 @@ note: lint level defined here LL | #![deny(clippy::into_iter_on_array)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: this .into_iter() call is equivalent to .iter() and will not move the array - --> $DIR/into_iter_on_ref.rs:15:23 - | -LL | let _ = [1, 2, 3].into_iter(); //~ ERROR equivalent to .iter() - | ^^^^^^^^^ help: call directly: `iter` - error: this .into_iter() call is equivalent to .iter() and will not move the Vec --> $DIR/into_iter_on_ref.rs:17:30 | @@ -174,5 +168,5 @@ error: this .into_iter() call is equivalent to .iter() and will not move the Pat LL | let _ = std::path::PathBuf::from("12/34").into_iter(); //~ ERROR equivalent to .iter() | ^^^^^^^^^ help: call directly: `iter` -error: aborting due to 28 previous errors +error: aborting due to 27 previous errors diff --git a/tests/ui/issue_3849.rs b/tests/ui/issue_3849.rs index 33462b0ea77d..bae4570e539a 100644 --- a/tests/ui/issue_3849.rs +++ b/tests/ui/issue_3849.rs @@ -1,6 +1,7 @@ #![allow(dead_code)] #![allow(clippy::zero_ptr)] #![allow(clippy::transmute_ptr_to_ref)] +#![allow(clippy::transmuting_null)] pub const ZPTR: *const usize = 0 as *const _; diff --git a/tests/ui/literals.rs b/tests/ui/literals.rs index ef86b5240ebf..5f3f95bab980 100644 --- a/tests/ui/literals.rs +++ b/tests/ui/literals.rs @@ -37,27 +37,9 @@ fn main() { let ok16 = 0xFE_BAFE_ABAB_ABCD; let ok17 = 0x123_4567_8901_usize; - let fail9 = 0xabcdef; - let fail10 = 0xBAFEBAFE; - let fail11 = 0xabcdeff; - let fail12 = 0xabcabcabcabcabcabc; let fail13 = 0x1_23456_78901_usize; - let fail14 = 2_32; - let fail15 = 4_64; - let fail16 = 7_8; - let fail17 = 23_16; - let ok18 = 23_128; let fail19 = 12_3456_21; - let fail20 = 2__8; - let fail21 = 4___16; let fail22 = 3__4___23; let fail23 = 3__16___23; - - let fail24 = 12.34_64; - let fail25 = 1E2_32; - let fail26 = 43E7_64; - let fail27 = 243E17_32; - let fail28 = 241251235E723_64; - let fail29 = 42279.911_32; } diff --git a/tests/ui/literals.stderr b/tests/ui/literals.stderr index 2a461dba4572..22692160d73a 100644 --- a/tests/ui/literals.stderr +++ b/tests/ui/literals.stderr @@ -86,133 +86,33 @@ help: if you mean to use an octal constant, use `0o` LL | let fail8 = 0o123; | ^^^^^ -error: long literal lacking separators - --> $DIR/literals.rs:40:17 - | -LL | let fail9 = 0xabcdef; - | ^^^^^^^^ help: consider: `0x00ab_cdef` - | - = note: `-D clippy::unreadable-literal` implied by `-D warnings` - -error: long literal lacking separators - --> $DIR/literals.rs:41:18 - | -LL | let fail10 = 0xBAFEBAFE; - | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` - -error: long literal lacking separators - --> $DIR/literals.rs:42:18 - | -LL | let fail11 = 0xabcdeff; - | ^^^^^^^^^ help: consider: `0x0abc_deff` - -error: long literal lacking separators - --> $DIR/literals.rs:43:18 - | -LL | let fail12 = 0xabcabcabcabcabcabc; - | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` - error: digit groups should be smaller - --> $DIR/literals.rs:44:18 + --> $DIR/literals.rs:40:18 | LL | let fail13 = 0x1_23456_78901_usize; | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` | = note: `-D clippy::large-digit-groups` implied by `-D warnings` -error: mistyped literal suffix - --> $DIR/literals.rs:46:18 - | -LL | let fail14 = 2_32; - | ^^^^ help: did you mean to write: `2_i32` - | - = note: #[deny(clippy::mistyped_literal_suffixes)] on by default - -error: mistyped literal suffix - --> $DIR/literals.rs:47:18 - | -LL | let fail15 = 4_64; - | ^^^^ help: did you mean to write: `4_i64` - -error: mistyped literal suffix - --> $DIR/literals.rs:48:18 - | -LL | let fail16 = 7_8; - | ^^^ help: did you mean to write: `7_i8` - -error: mistyped literal suffix - --> $DIR/literals.rs:49:18 - | -LL | let fail17 = 23_16; - | ^^^^^ help: did you mean to write: `23_i16` - error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:51:18 + --> $DIR/literals.rs:42:18 | LL | let fail19 = 12_3456_21; | ^^^^^^^^^^ help: consider: `12_345_621` | = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` -error: mistyped literal suffix - --> $DIR/literals.rs:52:18 - | -LL | let fail20 = 2__8; - | ^^^^ help: did you mean to write: `2_i8` - -error: mistyped literal suffix - --> $DIR/literals.rs:53:18 - | -LL | let fail21 = 4___16; - | ^^^^^^ help: did you mean to write: `4_i16` - error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:54:18 + --> $DIR/literals.rs:43:18 | LL | let fail22 = 3__4___23; | ^^^^^^^^^ help: consider: `3_423` error: digits grouped inconsistently by underscores - --> $DIR/literals.rs:55:18 + --> $DIR/literals.rs:44:18 | LL | let fail23 = 3__16___23; | ^^^^^^^^^^ help: consider: `31_623` -error: mistyped literal suffix - --> $DIR/literals.rs:57:18 - | -LL | let fail24 = 12.34_64; - | ^^^^^^^^ help: did you mean to write: `12.34_f64` - -error: mistyped literal suffix - --> $DIR/literals.rs:58:18 - | -LL | let fail25 = 1E2_32; - | ^^^^^^ help: did you mean to write: `1E2_f32` - -error: mistyped literal suffix - --> $DIR/literals.rs:59:18 - | -LL | let fail26 = 43E7_64; - | ^^^^^^^ help: did you mean to write: `43E7_f64` - -error: mistyped literal suffix - --> $DIR/literals.rs:60:18 - | -LL | let fail27 = 243E17_32; - | ^^^^^^^^^ help: did you mean to write: `243E17_f32` - -error: mistyped literal suffix - --> $DIR/literals.rs:61:18 - | -LL | let fail28 = 241251235E723_64; - | ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64` - -error: mistyped literal suffix - --> $DIR/literals.rs:62:18 - | -LL | let fail29 = 42279.911_32; - | ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32` - -error: aborting due to 31 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/mistyped_literal_suffix.fixed b/tests/ui/mistyped_literal_suffix.fixed new file mode 100644 index 000000000000..531e44a781c2 --- /dev/null +++ b/tests/ui/mistyped_literal_suffix.fixed @@ -0,0 +1,22 @@ +// run-rustfix + +#![allow(dead_code, unused_variables, clippy::excessive_precision)] + +fn main() { + let fail14 = 2_i32; + let fail15 = 4_i64; + let fail16 = 7_i8; // + let fail17 = 23_i16; // + let ok18 = 23_128; + + let fail20 = 2_i8; // + let fail21 = 4_i16; // + + let fail24 = 12.34_f64; + let fail25 = 1E2_f32; + let fail26 = 43E7_f64; + let fail27 = 243E17_f32; + #[allow(overflowing_literals)] + let fail28 = 241_251_235E723_f64; + let fail29 = 42_279.911_f32; +} diff --git a/tests/ui/mistyped_literal_suffix.rs b/tests/ui/mistyped_literal_suffix.rs new file mode 100644 index 000000000000..d67c842b4af4 --- /dev/null +++ b/tests/ui/mistyped_literal_suffix.rs @@ -0,0 +1,22 @@ +// run-rustfix + +#![allow(dead_code, unused_variables, clippy::excessive_precision)] + +fn main() { + let fail14 = 2_32; + let fail15 = 4_64; + let fail16 = 7_8; // + let fail17 = 23_16; // + let ok18 = 23_128; + + let fail20 = 2__8; // + let fail21 = 4___16; // + + let fail24 = 12.34_64; + let fail25 = 1E2_32; + let fail26 = 43E7_64; + let fail27 = 243E17_32; + #[allow(overflowing_literals)] + let fail28 = 241251235E723_64; + let fail29 = 42279.911_32; +} diff --git a/tests/ui/mistyped_literal_suffix.stderr b/tests/ui/mistyped_literal_suffix.stderr new file mode 100644 index 000000000000..c3fed6ae8fdc --- /dev/null +++ b/tests/ui/mistyped_literal_suffix.stderr @@ -0,0 +1,76 @@ +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:6:18 + | +LL | let fail14 = 2_32; + | ^^^^ help: did you mean to write: `2_i32` + | + = note: #[deny(clippy::mistyped_literal_suffixes)] on by default + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:7:18 + | +LL | let fail15 = 4_64; + | ^^^^ help: did you mean to write: `4_i64` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:8:18 + | +LL | let fail16 = 7_8; // + | ^^^ help: did you mean to write: `7_i8` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:9:18 + | +LL | let fail17 = 23_16; // + | ^^^^^ help: did you mean to write: `23_i16` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:12:18 + | +LL | let fail20 = 2__8; // + | ^^^^ help: did you mean to write: `2_i8` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:13:18 + | +LL | let fail21 = 4___16; // + | ^^^^^^ help: did you mean to write: `4_i16` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:15:18 + | +LL | let fail24 = 12.34_64; + | ^^^^^^^^ help: did you mean to write: `12.34_f64` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:16:18 + | +LL | let fail25 = 1E2_32; + | ^^^^^^ help: did you mean to write: `1E2_f32` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:17:18 + | +LL | let fail26 = 43E7_64; + | ^^^^^^^ help: did you mean to write: `43E7_f64` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:18:18 + | +LL | let fail27 = 243E17_32; + | ^^^^^^^^^ help: did you mean to write: `243E17_f32` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:20:18 + | +LL | let fail28 = 241251235E723_64; + | ^^^^^^^^^^^^^^^^ help: did you mean to write: `241_251_235E723_f64` + +error: mistyped literal suffix + --> $DIR/mistyped_literal_suffix.rs:21:18 + | +LL | let fail29 = 42279.911_32; + | ^^^^^^^^^^^^ help: did you mean to write: `42_279.911_f32` + +error: aborting due to 12 previous errors + diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index 0d093adf8cd3..f031dd105c25 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -95,7 +95,7 @@ impl S { s.len() + t.capacity() } - fn bar(_t: T // Ok, since `&T: Serialize` too + fn bar(_t: T, // Ok, since `&T: Serialize` too ) { } diff --git a/tests/ui/non_expressive_names.rs b/tests/ui/non_expressive_names.rs index cd158287ff70..301ff2761206 100644 --- a/tests/ui/non_expressive_names.rs +++ b/tests/ui/non_expressive_names.rs @@ -49,6 +49,45 @@ fn bla() { } } +fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {} + +fn bindings2() { + let (a, b, c, d, e, f, g, h) = unimplemented!(); +} + +fn shadowing() { + let a = 0i32; + let a = 0i32; + let a = 0i32; + let a = 0i32; + let a = 0i32; + let a = 0i32; + { + let a = 0i32; + } +} + +fn patterns() { + enum Z { + A(i32), + B(i32), + C(i32), + D(i32), + E(i32), + F(i32), + } + + // These should not trigger a warning, since the pattern bindings are a new scope. + match Z::A(0) { + Z::A(a) => {}, + Z::B(b) => {}, + Z::C(c) => {}, + Z::D(d) => {}, + Z::E(e) => {}, + Z::F(f) => {}, + } +} + fn underscores_and_numbers() { let _1 = 1; //~ERROR Consider a more descriptive name let ____1 = 1; //~ERROR Consider a more descriptive name diff --git a/tests/ui/non_expressive_names.stderr b/tests/ui/non_expressive_names.stderr index a81ecdfe4de3..b848c07667cd 100644 --- a/tests/ui/non_expressive_names.stderr +++ b/tests/ui/non_expressive_names.stderr @@ -1,31 +1,54 @@ -error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:35:17 +error: 5 bindings with single-character names in scope + --> $DIR/non_expressive_names.rs:27:9 | +LL | let a: i32; + | ^ +LL | let (b, c, d): (i32, i64, i16); + | ^ ^ ^ +... LL | let e: i32; | ^ | = note: `-D clippy::many-single-char-names` implied by `-D warnings` -error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:38:17 +error: 6 bindings with single-character names in scope + --> $DIR/non_expressive_names.rs:27:9 | +LL | let a: i32; + | ^ +LL | let (b, c, d): (i32, i64, i16); + | ^ ^ ^ +... LL | let e: i32; | ^ - -error: 6th binding whose name is just one char - --> $DIR/non_expressive_names.rs:39:17 - | LL | let f: i32; | ^ -error: 5th binding whose name is just one char - --> $DIR/non_expressive_names.rs:43:13 +error: 5 bindings with single-character names in scope + --> $DIR/non_expressive_names.rs:27:9 | +LL | let a: i32; + | ^ +LL | let (b, c, d): (i32, i64, i16); + | ^ ^ ^ +... LL | e => panic!(), | ^ +error: 8 bindings with single-character names in scope + --> $DIR/non_expressive_names.rs:52:13 + | +LL | fn bindings(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {} + | ^ ^ ^ ^ ^ ^ ^ ^ + +error: 8 bindings with single-character names in scope + --> $DIR/non_expressive_names.rs:55:10 + | +LL | let (a, b, c, d, e, f, g, h) = unimplemented!(); + | ^ ^ ^ ^ ^ ^ ^ ^ + error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:53:9 + --> $DIR/non_expressive_names.rs:92:9 | LL | let _1 = 1; //~ERROR Consider a more descriptive name | ^^ @@ -33,34 +56,34 @@ LL | let _1 = 1; //~ERROR Consider a more descriptive name = note: `-D clippy::just-underscores-and-digits` implied by `-D warnings` error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:54:9 + --> $DIR/non_expressive_names.rs:93:9 | LL | let ____1 = 1; //~ERROR Consider a more descriptive name | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:55:9 + --> $DIR/non_expressive_names.rs:94:9 | LL | let __1___2 = 12; //~ERROR Consider a more descriptive name | ^^^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:75:13 + --> $DIR/non_expressive_names.rs:114:13 | LL | let _1 = 1; | ^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:76:13 + --> $DIR/non_expressive_names.rs:115:13 | LL | let ____1 = 1; | ^^^^^ error: consider choosing a more descriptive name - --> $DIR/non_expressive_names.rs:77:13 + --> $DIR/non_expressive_names.rs:116:13 | LL | let __1___2 = 12; | ^^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 11 previous errors diff --git a/tests/ui/non_expressive_names.stdout b/tests/ui/non_expressive_names.stdout new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index 2dd217903891..d5b6d81d0a5d 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -41,6 +41,8 @@ fn main() { x.trim_end_matches('x'); // Make sure we escape characters correctly. x.split('\n'); + x.split('\''); + x.split('\''); let h = HashSet::::new(); h.contains("X"); // should not warn diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index dc2f9fe4959a..73f364854d02 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -41,6 +41,8 @@ fn main() { x.trim_end_matches("x"); // Make sure we escape characters correctly. x.split("\n"); + x.split("'"); + x.split("\'"); let h = HashSet::::new(); h.contains("X"); // should not warn diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 0fcb203dbc12..d394c989c44c 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -109,16 +109,28 @@ LL | x.split("/n"); | ^^^^ help: try using a char instead: `'/n'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:48:31 + --> $DIR/single_char_pattern.rs:44:13 + | +LL | x.split("'"); + | ^^^ help: try using a char instead: `'/''` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:45:13 + | +LL | x.split("/'"); + | ^^^^ help: try using a char instead: `'/''` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:50:31 | LL | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:49:19 + --> $DIR/single_char_pattern.rs:51:19 | LL | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` -error: aborting due to 20 previous errors +error: aborting due to 22 previous errors diff --git a/tests/ui/transmuting_null.rs b/tests/ui/transmuting_null.rs new file mode 100644 index 000000000000..ea3ee8edc81b --- /dev/null +++ b/tests/ui/transmuting_null.rs @@ -0,0 +1,30 @@ +#![allow(dead_code)] +#![warn(clippy::transmuting_null)] +#![allow(clippy::zero_ptr)] +#![allow(clippy::transmute_ptr_to_ref)] +#![allow(clippy::eq_op)] + +// Easy to lint because these only span one line. +fn one_liners() { + unsafe { + let _: &u64 = std::mem::transmute(0 as *const u64); + let _: &u64 = std::mem::transmute(std::ptr::null::()); + } +} + +pub const ZPTR: *const usize = 0 as *const _; +pub const NOT_ZPTR: *const usize = 1 as *const _; + +fn transmute_const() { + unsafe { + // Should raise a lint. + let _: &u64 = std::mem::transmute(ZPTR); + // Should NOT raise a lint. + let _: &u64 = std::mem::transmute(NOT_ZPTR); + } +} + +fn main() { + one_liners(); + transmute_const(); +} diff --git a/tests/ui/transmuting_null.stderr b/tests/ui/transmuting_null.stderr new file mode 100644 index 000000000000..05f91ee2adaa --- /dev/null +++ b/tests/ui/transmuting_null.stderr @@ -0,0 +1,22 @@ +error: transmuting a known null pointer into a reference. + --> $DIR/transmuting_null.rs:10:23 + | +LL | let _: &u64 = std::mem::transmute(0 as *const u64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::transmuting-null` implied by `-D warnings` + +error: transmuting a known null pointer into a reference. + --> $DIR/transmuting_null.rs:11:23 + | +LL | let _: &u64 = std::mem::transmute(std::ptr::null::()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: transmuting a known null pointer into a reference. + --> $DIR/transmuting_null.rs:21:23 + | +LL | let _: &u64 = std::mem::transmute(ZPTR); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/unreadable_literal.fixed b/tests/ui/unreadable_literal.fixed index eede10c771c4..1fc93b9c3a8b 100644 --- a/tests/ui/unreadable_literal.fixed +++ b/tests/ui/unreadable_literal.fixed @@ -17,4 +17,9 @@ fn main() { let bad = (0b11_0110_i64, 0x0123_4567_8901_usize, 123_456_f32, 1.234_567_f32); let good_sci = 1.1234e1; let bad_sci = 1.123_456e1; + + let fail9 = 0x00ab_cdef; + let fail10: u32 = 0xBAFE_BAFE; + let fail11 = 0x0abc_deff; + let fail12: i128 = 0x00ab_cabc_abca_bcab_cabc; } diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 6523f70186f6..ef0ef2b9b9e5 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -17,4 +17,9 @@ fn main() { let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); let good_sci = 1.1234e1; let bad_sci = 1.123456e1; + + let fail9 = 0xabcdef; + let fail10: u32 = 0xBAFEBAFE; + let fail11 = 0xabcdeff; + let fail12: i128 = 0xabcabcabcabcabcabc; } diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 8334139120ea..2ece53782875 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -30,5 +30,29 @@ error: long literal lacking separators LL | let bad_sci = 1.123456e1; | ^^^^^^^^^^ help: consider: `1.123_456e1` -error: aborting due to 5 previous errors +error: long literal lacking separators + --> $DIR/unreadable_literal.rs:21:17 + | +LL | let fail9 = 0xabcdef; + | ^^^^^^^^ help: consider: `0x00ab_cdef` + +error: long literal lacking separators + --> $DIR/unreadable_literal.rs:22:23 + | +LL | let fail10: u32 = 0xBAFEBAFE; + | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` + +error: long literal lacking separators + --> $DIR/unreadable_literal.rs:23:18 + | +LL | let fail11 = 0xabcdeff; + | ^^^^^^^^^ help: consider: `0x0abc_deff` + +error: long literal lacking separators + --> $DIR/unreadable_literal.rs:24:24 + | +LL | let fail12: i128 = 0xabcabcabcabcabcabc; + | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` + +error: aborting due to 9 previous errors diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 730d391848ec..68af85030ab2 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -239,6 +239,7 @@ mod nesting { struct Foo {} impl Foo { fn foo() { + #[allow(unused_imports)] use self::Foo; // Can't use Self here struct Bar { foo: Foo, // Foo != Self diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 008247315121..7a6d415528ad 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -239,6 +239,7 @@ mod nesting { struct Foo {} impl Foo { fn foo() { + #[allow(unused_imports)] use self::Foo; // Can't use Self here struct Bar { foo: Foo, // Foo != Self diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 6e39a28012a8..bf1f41fd64ed 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -151,43 +151,43 @@ LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation error: unnecessary structure name repetition - --> $DIR/use_self.rs:260:21 + --> $DIR/use_self.rs:261:21 | LL | fn baz() -> Foo { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:261:13 + --> $DIR/use_self.rs:262:13 | LL | Foo {} | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:248:29 + --> $DIR/use_self.rs:249:29 | LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:249:21 + --> $DIR/use_self.rs:250:21 | LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:303:13 + --> $DIR/use_self.rs:304:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:304:13 + --> $DIR/use_self.rs:305:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:306:13 + --> $DIR/use_self.rs:307:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self`