From ab2dd0d8d2d57667189cc5714442e6fb16f19d00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 2 Dec 2019 23:09:48 +0100 Subject: [PATCH] submodules: update clippy from 7b8e8293 to 7a943a9d Changes: ```` Normalize custom ICE test Rustup to rust-lang/rust#64736 Use assert_crate_local for a more explicit error Rustup to https://github.com/rust-lang/rust/pull/66789 account for external macro in MISSING_INLINE_IN_PUBLIC_ITEMS lint build(tests/fmt): use shared target dir chore: fix and split some ui tests on 32bit system build: set up build job for i686 targets remove needless my_lint ui test git quiet deploy: cd to out/ before adding files to git Less needless_doctest_main false positives fmt Feed the dog Use rustc_env instead of exec_env for test Make triggering this lint less likely :paperclip: Use exec_env to set backtrace level and normalize output Update custom ICE function with latest rustc Use Clippy version in ICE message Add custom ICE message that points to Clippy repo Fix master deployment Run update_lints Add projections check to EUV for escape analysis Use infer_ctxt Move use_self to nursery Use `println!` on success instead of `eprintln!` Revert "Disable chalk integration test. Output too large" Remove the old integration-tests.sh script Use rust implementation for integration tests in CI Rust implementation of integration test Don't error on clippy.toml of dependencies Fix categorizations Fix arguments on ExprUseVisitor::new euv moved from middle to typeck cmt_ -> Place build: check if RTIM is not installed make use of Result::map_or trigger string_lit_as_bytes when literal has escapes Remove negative float literal checks. Enable deny-warnings feature everywhere in CI Remove unused debugging feature implemented `as_conversions` lint fixing a typo [comparison_chain] #4827 Check `core::cmp::Ord` is implemented add a good example for the approx_const lint Add suggested good cases in docs for lifetimes lint ```` --- .github/deploy.sh | 2 + .travis.yml | 27 ++-- CHANGELOG.md | 1 + Cargo.toml | 5 +- README.md | 2 +- appveyor.yml | 4 +- ci/base-tests.sh | 14 +- ci/integration-tests.sh | 37 ------ clippy_dev/Cargo.toml | 3 + clippy_dev/src/lib.rs | 2 + clippy_dev/src/main.rs | 2 + clippy_lints/Cargo.toml | 2 +- clippy_lints/src/approx_const.rs | 6 + clippy_lints/src/arithmetic.rs | 10 +- clippy_lints/src/as_conversions.rs | 56 ++++++++ clippy_lints/src/comparison_chain.rs | 12 +- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/enum_clike.rs | 1 + clippy_lints/src/escape.rs | 70 +++++----- clippy_lints/src/lib.rs | 9 +- clippy_lints/src/lifetimes.rs | 12 ++ clippy_lints/src/loops.rs | 27 ++-- clippy_lints/src/methods/mod.rs | 14 +- clippy_lints/src/missing_inline.rs | 6 +- clippy_lints/src/needless_pass_by_value.rs | 32 ++--- clippy_lints/src/redundant_clone.rs | 16 ++- clippy_lints/src/strings.rs | 87 ++++++------- clippy_lints/src/use_self.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 39 ++++++ clippy_lints/src/utils/usage.rs | 36 ++---- rustc_tools_util/Cargo.toml | 4 + rustc_tools_util/src/lib.rs | 2 + setup-toolchain.sh | 15 ++- src/driver.rs | 73 ++++++++++- src/lintlist/mod.rs | 13 +- tests/fmt.rs | 4 +- tests/integration.rs | 75 +++++++++++ tests/ui/arithmetic.rs | 4 + tests/ui/as_conversions.rs | 7 + tests/ui/as_conversions.stderr | 27 ++++ tests/ui/cast_size.rs | 1 + tests/ui/cast_size.stderr | 36 +++--- tests/ui/cast_size_32bit.rs | 35 +++++ tests/ui/cast_size_32bit.stderr | 132 +++++++++++++++++++ tests/ui/comparison_chain.rs | 61 +++++++++ tests/ui/comparison_chain.stderr | 42 +++++- tests/ui/custom_ice_message.rs | 10 ++ tests/ui/custom_ice_message.stderr | 11 ++ tests/ui/fn_to_numeric_cast.rs | 2 +- tests/ui/fn_to_numeric_cast_32bit.rs | 55 ++++++++ tests/ui/fn_to_numeric_cast_32bit.stderr | 144 +++++++++++++++++++++ tests/ui/large_digit_groups.fixed | 11 +- tests/ui/large_digit_groups.rs | 11 +- tests/ui/large_digit_groups.stderr | 8 +- tests/ui/missing_inline.rs | 4 + tests/ui/my_lint.rs | 7 - tests/ui/needless_doc_main.rs | 33 +++++ tests/ui/needless_doc_main.stderr | 10 ++ tests/ui/result_map_unwrap_or_else.stderr | 12 +- tests/ui/string_lit_as_bytes.fixed | 2 + tests/ui/string_lit_as_bytes.rs | 2 + tests/ui/string_lit_as_bytes.stderr | 8 +- tests/ui/transmute_32bit.rs | 4 +- tests/ui/transmute_32bit.stderr | 28 ++++ tests/ui/transmute_64bit.rs | 3 +- tests/ui/transmute_64bit.stderr | 4 +- tests/ui/types.fixed | 2 +- tests/ui/types.rs | 2 +- tests/ui/unreadable_literal.fixed | 20 +-- tests/ui/unreadable_literal.rs | 20 +-- tests/ui/unreadable_literal.stderr | 54 ++++---- 71 files changed, 1189 insertions(+), 347 deletions(-) delete mode 100755 ci/integration-tests.sh create mode 100644 clippy_lints/src/as_conversions.rs create mode 100644 tests/integration.rs create mode 100644 tests/ui/as_conversions.rs create mode 100644 tests/ui/as_conversions.stderr create mode 100644 tests/ui/cast_size_32bit.rs create mode 100644 tests/ui/cast_size_32bit.stderr create mode 100644 tests/ui/custom_ice_message.rs create mode 100644 tests/ui/custom_ice_message.stderr create mode 100644 tests/ui/fn_to_numeric_cast_32bit.rs create mode 100644 tests/ui/fn_to_numeric_cast_32bit.stderr delete mode 100644 tests/ui/my_lint.rs create mode 100644 tests/ui/needless_doc_main.rs create mode 100644 tests/ui/needless_doc_main.stderr create mode 100644 tests/ui/transmute_32bit.stderr diff --git a/.github/deploy.sh b/.github/deploy.sh index b82091592846..19dc4017166c 100755 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -60,6 +60,7 @@ if git diff --exit-code --quiet; then echo "No changes to the output on this push; exiting." exit 0 fi +cd - # Get the deploy key by using Travis's stored variables to decrypt deploy_key.enc ENCRYPTION_LABEL=e3a2d77100be @@ -72,6 +73,7 @@ chmod 600 .github/deploy_key eval "$(ssh-agent -s)" ssh-add .github/deploy_key +cd out git add . git commit -m "Automatic deploy to GitHub Pages: ${SHA}" diff --git a/.travis.yml b/.travis.yml index 187079602114..41d19b209b6d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,8 @@ dist: xenial language: bash +git: + depth: 1 + quiet: true branches: # Don't build these branches @@ -22,6 +25,7 @@ env: - secure: "OKulfkA5OGd/d1IhvBKzRkHQwMcWjzrzbimo7+5NhkUkWxndAzl+719TB3wWvIh1i2wXXrEXsyZkXM5FtRrHm55v1VKQ5ibjEvFg1w3NIg81iDyoLq186fLqywvxGkOAFPrsePPsBj5USd5xvhwwbrjO6L7/RK6Z8shBwOSc41s=" before_install: + - export CARGO_TARGET_DIR="$TRAVIS_BUILD_DIR/target" - curl -sSL https://sh.rustup.rs | sh -s -- -y --default-toolchain=nightly --profile=minimal - export PATH="$HOME/.cargo/bin:$PATH" install: @@ -48,6 +52,15 @@ matrix: include: # Builds that are executed for every PR - os: linux + # i686 toolchain could run on x86_64 system. + - os: linux + env: HOST_TOOLCHAIN=i686-unknown-linux-gnu + addons: + apt: + packages: + - gcc-multilib + - libssl-dev:i386 # openssl dev in Cargo.toml + if: branch IN (auto, try) - os: windows env: CARGO_INCREMENTAL=0 OS_WINDOWS=true @@ -61,14 +74,12 @@ matrix: if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=rust-lang/cargo if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - # FIXME: Output too large - # - env: INTEGRATION=rust-lang-nursery/chalk - # if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) + - env: INTEGRATION=rust-lang/chalk + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=Geal/nom if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - # FIXME blocked on https://github.com/rust-lang/rust-clippy/issues/4727 - #- env: INTEGRATION=rust-lang/rustfmt - # if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) + - env: INTEGRATION=rust-lang/rustfmt + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=hyperium/hyper if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=bluss/rust-itertools @@ -116,7 +127,7 @@ before_script: SYSROOT=$(rustc --print sysroot) case "$TRAVIS_OS_NAME" in windows ) export PATH="${SYSROOT}/bin:${PATH}" ;; - linux ) export LD_LIBRARY_PATH="${SYSROOT}/lib" ;; + linux ) export LD_LIBRARY_PATH="${SYSROOT}/lib${LD_LIBRARY_PATH+:${LD_LIBRARY_PATH}}" ;; osx ) # See sudo mkdir -p /usr/local/lib @@ -127,7 +138,7 @@ before_script: script: - | if [[ -n ${INTEGRATION} ]]; then - ./ci/integration-tests.sh && sleep 5 + cargo test --test integration --features integration && sleep 5 else ./ci/base-tests.sh && sleep 5 fi diff --git a/CHANGELOG.md b/CHANGELOG.md index f21174c0bcef..4e747524e9ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -929,6 +929,7 @@ Released 2018-09-13 [`absurd_extreme_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#absurd_extreme_comparisons [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant +[`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions [`assertions_on_constants`]: https://rust-lang.github.io/rust-clippy/master/index.html#assertions_on_constants [`assign_op_pattern`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_op_pattern [`assign_ops`]: https://rust-lang.github.io/rust-clippy/master/index.html#assign_ops diff --git a/Cargo.toml b/Cargo.toml index 82a2e71bb2b9..6b757ac0a2fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,6 +38,9 @@ clippy_lints = { version = "0.0.212", path = "clippy_lints" } regex = "1" semver = "0.9" rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} +git2 = { version = "0.10", optional = true } +tempfile = { version = "3.1.0", optional = true } +lazy_static = "1.0" [dev-dependencies] cargo_metadata = "0.9.0" @@ -58,4 +61,4 @@ rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} [features] deny-warnings = [] -debugging = [] +integration = ["git2", "tempfile"] diff --git a/README.md b/README.md index d467e05257b7..e8818412e90e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 337 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 338 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/appveyor.yml b/appveyor.yml index 075c519cd4bf..bf6133e98a06 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -37,10 +37,10 @@ install: build: false build_script: - - cargo build --features debugging + - cargo build --features deny-warnings test_script: - - cargo test --features debugging + - cargo test --features deny-warnings notifications: - provider: Email diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 4a64b19d80ab..010c8919752f 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -1,10 +1,6 @@ #!/usr/bin/env bash set -ex -# for faster build, share target dir between subcrates -CARGO_TARGET_DIR=$(pwd)/target/ -export CARGO_TARGET_DIR - echo "Running clippy base tests" PATH=$PATH:./node_modules/.bin @@ -12,12 +8,12 @@ if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then remark -f ./*.md -f doc/*.md > /dev/null fi # build clippy in debug mode and run tests -cargo build --features "debugging deny-warnings" -cargo test --features "debugging deny-warnings" +cargo build --features deny-warnings +cargo test --features deny-warnings -(cd clippy_lints && cargo test) -(cd rustc_tools_util && cargo test) -(cd clippy_dev && cargo test) +(cd clippy_lints && cargo test --features deny-warnings) +(cd rustc_tools_util && cargo test --features deny-warnings) +(cd clippy_dev && cargo test --features deny-warnings) # make sure clippy can be called via ./path/to/cargo-clippy ( diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh deleted file mode 100755 index f6540769bb03..000000000000 --- a/ci/integration-tests.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -set -ex - -if [[ -z "$INTEGRATION" ]]; then - exit 0 -fi - -CARGO_TARGET_DIR=$(pwd)/target/ -export CARGO_TARGET_DIR - -rm ~/.cargo/bin/cargo-clippy -cargo install --force --debug --path . - -echo "Running integration test for crate ${INTEGRATION}" - -git clone --depth=1 "https://github.com/${INTEGRATION}.git" checkout -cd checkout - -# run clippy on a project, try to be verbose and trigger as many warnings -# as possible for greater coverage -# NOTE: we use `tee` to print any warnings and errors to stdout -# to avoid build timeout in Travis -RUST_BACKTRACE=full \ -cargo clippy \ - --all-targets \ - --all-features \ - -- \ - --cap-lints warn \ - -W clippy::pedantic \ - -W clippy::nursery \ - 2>&1 | tee clippy_output - -cargo uninstall clippy - -if grep -q "internal compiler error\|query stack during panic\|E0463" clippy_output; then - exit 1 -fi diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index e2e946d06f27..b30ba61d2991 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -11,3 +11,6 @@ regex = "1" lazy_static = "1.0" shell-escape = "0.1" walkdir = "2" + +[features] +deny-warnings = [] diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 327774ea0f26..f73e7b86720d 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "deny-warnings", deny(warnings))] + use itertools::Itertools; use lazy_static::lazy_static; use regex::Regex; diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 9c9d3eae5885..3010e0d2489d 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "deny-warnings", deny(warnings))] + extern crate clap; extern crate clippy_dev; extern crate regex; diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 608fb668c5ae..dae403cbb4f1 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -35,4 +35,4 @@ semver = "0.9.0" url = { version = "2.1.0", features = ["serde"] } [features] -debugging = [] +deny-warnings = [] diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index fac75cffeba6..9f665a3361da 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -23,7 +23,13 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad /// let x = 3.14; + /// let y = 1_f64 / x; + /// + /// // Good + /// let x = std::f32::consts::PI; + /// let y = std::f64::consts::FRAC_1_PI; /// ``` pub APPROX_CONSTANT, correctness, diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index 1cca897e7390..2c46bf2dc12d 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -92,14 +92,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic { }, hir::ExprKind::Unary(hir::UnOp::UnNeg, arg) => { let ty = cx.tables.expr_ty(arg); - if ty.is_integral() { - if constant_simple(cx, cx.tables, expr).is_none() { + if constant_simple(cx, cx.tables, expr).is_none() { + if ty.is_integral() { span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected"); self.expr_span = Some(expr.span); + } else if ty.is_floating_point() { + span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); + self.expr_span = Some(expr.span); } - } else if ty.is_floating_point() { - span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected"); - self.expr_span = Some(expr.span); } }, _ => (), diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs new file mode 100644 index 000000000000..ee6357359d16 --- /dev/null +++ b/clippy_lints/src/as_conversions.rs @@ -0,0 +1,56 @@ +use rustc::lint::{in_external_macro, EarlyContext, EarlyLintPass, LintArray, LintContext, LintPass}; +use rustc::{declare_lint_pass, declare_tool_lint}; +use syntax::ast::*; + +use crate::utils::span_help_and_lint; + +declare_clippy_lint! { + /// **What it does:** Checks for usage of `as` conversions. + /// + /// **Why is this bad?** `as` conversions will perform many kinds of + /// conversions, including silently lossy conversions and dangerous coercions. + /// There are cases when it makes sense to use `as`, so the lint is + /// Allow by default. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust,ignore + /// let a: u32; + /// ... + /// f(a as u16); + /// ``` + /// + /// Usually better represents the semantics you expect: + /// ```rust,ignore + /// f(a.try_into()?); + /// ``` + /// or + /// ```rust,ignore + /// f(a.try_into().expect("Unexpected u16 overflow in f")); + /// ``` + /// + pub AS_CONVERSIONS, + restriction, + "using a potentially dangerous silent `as` conversion" +} + +declare_lint_pass!(AsConversions => [AS_CONVERSIONS]); + +impl EarlyLintPass for AsConversions { + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if in_external_macro(cx.sess(), expr.span) { + return; + } + + if let ExprKind::Cast(_, _) = expr.kind { + span_help_and_lint( + cx, + AS_CONVERSIONS, + expr.span, + "using a potentially dangerous silent `as` conversion", + "consider using a safe wrapper for this conversion", + ); + } + } +} diff --git a/clippy_lints/src/comparison_chain.rs b/clippy_lints/src/comparison_chain.rs index 6968d8f65599..087bceaffd98 100644 --- a/clippy_lints/src/comparison_chain.rs +++ b/clippy_lints/src/comparison_chain.rs @@ -1,4 +1,6 @@ -use crate::utils::{if_sequence, parent_node_is_if_expr, span_help_and_lint, SpanlessEq}; +use crate::utils::{ + get_trait_def_id, if_sequence, implements_trait, parent_node_is_if_expr, paths, span_help_and_lint, SpanlessEq, +}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_lint_pass, declare_tool_lint}; @@ -84,6 +86,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ComparisonChain { { return; } + + // Check that the type being compared implements `core::cmp::Ord` + let ty = cx.tables.expr_ty(lhs1); + let is_ord = get_trait_def_id(cx, &paths::ORD).map_or(false, |id| implements_trait(cx, ty, id, &[])); + + if !is_ord { + return; + } } else { // We only care about comparison chains return; diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index e014d191276c..a8858a24e0f3 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -343,7 +343,7 @@ fn check_doc<'a, Events: Iterator, Range, text: &str, span: Span) { - if text.contains("fn main() {") { + if text.contains("fn main() {") && !(text.contains("static") || text.contains("fn main() {}")) { span_lint(cx, NEEDLESS_DOCTEST_MAIN, span, "needless `fn main` in doctest"); } } diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 2a361856a123..abdfe409b78d 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -24,6 +24,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # #[cfg(target_pointer_width = "64")] /// #[repr(usize)] /// enum NonPortable { /// X = 0x1_0000_0000, diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index bb6e0e5c51c2..e796b465944d 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,12 +1,11 @@ use rustc::hir::intravisit as visit; use rustc::hir::{self, *}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::middle::expr_use_visitor::*; -use rustc::middle::mem_categorization::{cmt_, Categorization}; use rustc::ty::layout::LayoutOf; use rustc::ty::{self, Ty}; use rustc::util::nodemap::HirIdSet; use rustc::{declare_tool_lint, impl_lint_pass}; +use rustc_typeck::expr_use_visitor::*; use syntax::source_map::Span; use crate::utils::span_lint; @@ -77,8 +76,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal { }; let fn_def_id = cx.tcx.hir().local_def_id(hir_id); - let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id); - ExprUseVisitor::new(&mut v, cx.tcx, fn_def_id, cx.param_env, region_scope_tree, cx.tables).consume_body(body); + cx.tcx.infer_ctxt().enter(|infcx| { + ExprUseVisitor::new(&mut v, &infcx, fn_def_id, cx.param_env, cx.tables).consume_body(body); + }); for node in v.set { span_lint( @@ -105,45 +105,49 @@ fn is_argument(map: &hir::map::Map<'_>, id: HirId) -> bool { } impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { - fn consume(&mut self, cmt: &cmt_<'tcx>, mode: ConsumeMode) { - if let Categorization::Local(lid) = cmt.cat { - if let ConsumeMode::Move = mode { - // moved out or in. clearly can't be localized - self.set.remove(&lid); - } - } - let map = &self.cx.tcx.hir(); - if let Categorization::Local(lid) = cmt.cat { - if let Some(Node::Binding(_)) = map.find(cmt.hir_id) { - if self.set.contains(&lid) { - // let y = x where x is known - // remove x, insert y - self.set.insert(cmt.hir_id); + fn consume(&mut self, cmt: &Place<'tcx>, mode: ConsumeMode) { + if cmt.projections.is_empty() { + if let PlaceBase::Local(lid) = cmt.base { + if let ConsumeMode::Move = mode { + // moved out or in. clearly can't be localized self.set.remove(&lid); } + let map = &self.cx.tcx.hir(); + if let Some(Node::Binding(_)) = map.find(cmt.hir_id) { + if self.set.contains(&lid) { + // let y = x where x is known + // remove x, insert y + self.set.insert(cmt.hir_id); + self.set.remove(&lid); + } + } } } } - fn borrow(&mut self, cmt: &cmt_<'tcx>, _: ty::BorrowKind) { - if let Categorization::Local(lid) = cmt.cat { - self.set.remove(&lid); + fn borrow(&mut self, cmt: &Place<'tcx>, _: ty::BorrowKind) { + if cmt.projections.is_empty() { + if let PlaceBase::Local(lid) = cmt.base { + self.set.remove(&lid); + } } } - fn mutate(&mut self, cmt: &cmt_<'tcx>) { - let map = &self.cx.tcx.hir(); - if is_argument(map, cmt.hir_id) { - // Skip closure arguments - let parent_id = map.get_parent_node(cmt.hir_id); - if let Some(Node::Expr(..)) = map.find(map.get_parent_node(parent_id)) { - return; - } + fn mutate(&mut self, cmt: &Place<'tcx>) { + if cmt.projections.is_empty() { + let map = &self.cx.tcx.hir(); + if is_argument(map, cmt.hir_id) { + // Skip closure arguments + let parent_id = map.get_parent_node(cmt.hir_id); + if let Some(Node::Expr(..)) = map.find(map.get_parent_node(parent_id)) { + return; + } - if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { - self.set.insert(cmt.hir_id); + if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { + self.set.insert(cmt.hir_id); + } + return; } - return; } } } @@ -152,7 +156,7 @@ impl<'a, 'tcx> EscapeDelegate<'a, 'tcx> { fn is_large_box(&self, ty: Ty<'tcx>) -> bool { // Large types need to be boxed to avoid stack overflows. if ty.is_box() { - self.cx.layout_of(ty.boxed_ty()).ok().map_or(0, |l| l.size.bytes()) > self.too_large_for_stack + self.cx.layout_of(ty.boxed_ty()).map_or(0, |l| l.size.bytes()) > self.too_large_for_stack } else { false } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c8954aef2ba8..c1113daadd81 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -12,6 +12,7 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] #![feature(crate_visibility_modifier)] #![feature(concat_idents)] +#![feature(result_map_or)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) @@ -155,6 +156,7 @@ mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` pub mod approx_const; pub mod arithmetic; +pub mod as_conversions; pub mod assertions_on_constants; pub mod assign_ops; pub mod attrs; @@ -448,6 +450,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf &approx_const::APPROX_CONSTANT, &arithmetic::FLOAT_ARITHMETIC, &arithmetic::INTEGER_ARITHMETIC, + &as_conversions::AS_CONVERSIONS, &assertions_on_constants::ASSERTIONS_ON_CONSTANTS, &assign_ops::ASSIGN_OP_PATTERN, &assign_ops::MISREFACTORED_ASSIGN_OP, @@ -959,10 +962,13 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf store.register_late_pass(|| box to_digit_is_some::ToDigitIsSome); let array_size_threshold = conf.array_size_threshold; store.register_late_pass(move || box large_stack_arrays::LargeStackArrays::new(array_size_threshold)); + store.register_early_pass(|| box as_conversions::AsConversions); + store.register_early_pass(|| box utils::internal_lints::ProduceIce); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), LintId::of(&arithmetic::INTEGER_ARITHMETIC), + LintId::of(&as_conversions::AS_CONVERSIONS), LintId::of(&dbg_macro::DBG_MACRO), LintId::of(&else_if_without_else::ELSE_IF_WITHOUT_ELSE), LintId::of(&exit::EXIT), @@ -1045,7 +1051,6 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf LintId::of(&unicode::NON_ASCII_LITERAL), LintId::of(&unicode::UNICODE_NOT_NFC), LintId::of(&unused_self::UNUSED_SELF), - LintId::of(&use_self::USE_SELF), ]); store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![ @@ -1053,6 +1058,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf LintId::of(&utils::internal_lints::COMPILER_LINT_FUNCTIONS), LintId::of(&utils::internal_lints::LINT_WITHOUT_LINT_PASS), LintId::of(&utils::internal_lints::OUTER_EXPN_EXPN_DATA), + LintId::of(&utils::internal_lints::PRODUCE_ICE), ]); store.register_group(true, "clippy::all", Some("clippy"), vec![ @@ -1574,6 +1580,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf LintId::of(&mutex_atomic::MUTEX_INTEGER), LintId::of(&needless_borrow::NEEDLESS_BORROW), LintId::of(&path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE), + LintId::of(&use_self::USE_SELF), ]); } diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index fad54c3de659..fe8938c581fa 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -24,9 +24,15 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad: unnecessary lifetime annotations /// fn in_and_out<'a>(x: &'a u8, y: u8) -> &'a u8 { /// x /// } + /// + /// // Good + /// fn elided(x: &u8, y: u8) -> &u8 { + /// x + /// } /// ``` pub NEEDLESS_LIFETIMES, complexity, @@ -46,9 +52,15 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// // Bad: unnecessary lifetimes /// fn unused_lifetime<'a>(x: u8) { /// // .. /// } + /// + /// // Good + /// fn no_lifetime(x: u8) { + /// // ... + /// } /// ``` pub EXTRA_UNUSED_LIFETIMES, complexity, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0f0323c13aa1..4212f9c1e64f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -12,13 +12,11 @@ use rustc::{declare_lint_pass, declare_tool_lint}; use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; use crate::utils::{is_type_diagnostic_item, qpath_res, sext, sugg}; -use rustc::middle::expr_use_visitor::*; -use rustc::middle::mem_categorization::cmt_; -use rustc::middle::mem_categorization::Categorization; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; +use rustc_typeck::expr_use_visitor::*; use std::iter::{once, Iterator}; use std::mem; use syntax::ast; @@ -1586,11 +1584,11 @@ struct MutatePairDelegate { } impl<'tcx> Delegate<'tcx> for MutatePairDelegate { - fn consume(&mut self, _: &cmt_<'tcx>, _: ConsumeMode) {} + fn consume(&mut self, _: &Place<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, cmt: &cmt_<'tcx>, bk: ty::BorrowKind) { + fn borrow(&mut self, cmt: &Place<'tcx>, bk: ty::BorrowKind) { if let ty::BorrowKind::MutBorrow = bk { - if let Categorization::Local(id) = cmt.cat { + if let PlaceBase::Local(id) = cmt.base { if Some(id) == self.hir_id_low { self.span_low = Some(cmt.span) } @@ -1601,8 +1599,8 @@ impl<'tcx> Delegate<'tcx> for MutatePairDelegate { } } - fn mutate(&mut self, cmt: &cmt_<'tcx>) { - if let Categorization::Local(id) = cmt.cat { + fn mutate(&mut self, cmt: &Place<'tcx>) { + if let PlaceBase::Local(id) = cmt.base { if Some(id) == self.hir_id_low { self.span_low = Some(cmt.span) } @@ -1680,16 +1678,9 @@ fn check_for_mutation( span_high: None, }; let def_id = def_id::DefId::local(body.hir_id.owner); - let region_scope_tree = &cx.tcx.region_scope_tree(def_id); - ExprUseVisitor::new( - &mut delegate, - cx.tcx, - def_id, - cx.param_env, - region_scope_tree, - cx.tables, - ) - .walk_expr(body); + cx.tcx.infer_ctxt().enter(|infcx| { + ExprUseVisitor::new(&mut delegate, &infcx, def_id, cx.param_env, cx.tables).walk_expr(body); + }); delegate.mutation_span() } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 5448eecb90e9..057d1f3bedf7 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -291,7 +291,7 @@ declare_clippy_lint! { /// **What it does:** Checks for usage of `result.map(_).unwrap_or_else(_)`. /// /// **Why is this bad?** Readability, this can be written more concisely as - /// `result.ok().map_or_else(_, _)`. + /// `result.map_or_else(_, _)`. /// /// **Known problems:** None. /// @@ -303,7 +303,7 @@ declare_clippy_lint! { /// ``` pub RESULT_MAP_UNWRAP_OR_ELSE, pedantic, - "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.ok().map_or_else(g, f)`" + "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.map_or_else(g, f)`" } declare_clippy_lint! { @@ -1075,7 +1075,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```ignore - /// unsafe { (&() as *const ()).offest(1) }; + /// unsafe { (&() as *const ()).offset(1) }; /// ``` pub ZST_OFFSET, correctness, @@ -2217,7 +2217,7 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( `map_or_else(g, f)` instead" } else { "called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling \ - `ok().map_or_else(g, f)` instead" + `.map_or_else(g, f)` instead" }; // get snippets for args to map() and unwrap_or_else() let map_snippet = snippet(cx, map_args[1].span, ".."); @@ -2238,10 +2238,8 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( msg, expr.span, &format!( - "replace `map({0}).unwrap_or_else({1})` with `{2}map_or_else({1}, {0})`", - map_snippet, - unwrap_snippet, - if is_result { "ok()." } else { "" } + "replace `map({0}).unwrap_or_else({1})` with `map_or_else({1}, {0})`", + map_snippet, unwrap_snippet, ), ); } else if same_span && multiline { diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index d9cd78dcd41d..927ead77a24f 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -1,6 +1,6 @@ use crate::utils::span_lint; use rustc::hir; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::lint::{self, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::{declare_lint_pass, declare_tool_lint}; use syntax::ast; use syntax::source_map::Span; @@ -81,7 +81,7 @@ declare_lint_pass!(MissingInline => [MISSING_INLINE_IN_PUBLIC_ITEMS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item) { - if is_executable(cx) { + if lint::in_external_macro(cx.sess(), it.span) || is_executable(cx) { return; } @@ -131,7 +131,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem) { use rustc::ty::{ImplContainer, TraitContainer}; - if is_executable(cx) { + if lint::in_external_macro(cx.sess(), impl_item.span) || is_executable(cx) { return; } diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 80f178289e4d..05894de5cb70 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -8,14 +8,13 @@ use matches::matches; use rustc::hir::intravisit::FnKind; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::middle::expr_use_visitor as euv; -use rustc::middle::mem_categorization as mc; use rustc::traits; use rustc::ty::{self, RegionKind, TypeFoldable}; use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; use rustc_target::spec::abi::Abi; +use rustc_typeck::expr_use_visitor as euv; use std::borrow::Cow; use syntax::ast::Attribute; use syntax::errors::DiagnosticBuilder; @@ -135,9 +134,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { .. } = { let mut ctx = MovedVariablesCtxt::default(); - let region_scope_tree = &cx.tcx.region_scope_tree(fn_def_id); - euv::ExprUseVisitor::new(&mut ctx, cx.tcx, fn_def_id, cx.param_env, region_scope_tree, cx.tables) - .consume_body(body); + cx.tcx.infer_ctxt().enter(|infcx| { + euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.tables).consume_body(body); + }); ctx }; @@ -326,34 +325,21 @@ struct MovedVariablesCtxt { } impl MovedVariablesCtxt { - fn move_common(&mut self, cmt: &mc::cmt_<'_>) { - let cmt = unwrap_downcast_or_interior(cmt); - - if let mc::Categorization::Local(vid) = cmt.cat { + fn move_common(&mut self, cmt: &euv::Place<'_>) { + if let euv::PlaceBase::Local(vid) = cmt.base { self.moved_vars.insert(vid); } } } impl<'tcx> euv::Delegate<'tcx> for MovedVariablesCtxt { - fn consume(&mut self, cmt: &mc::cmt_<'tcx>, mode: euv::ConsumeMode) { + fn consume(&mut self, cmt: &euv::Place<'tcx>, mode: euv::ConsumeMode) { if let euv::ConsumeMode::Move = mode { self.move_common(cmt); } } - fn borrow(&mut self, _: &mc::cmt_<'tcx>, _: ty::BorrowKind) {} - - fn mutate(&mut self, _: &mc::cmt_<'tcx>) {} -} + fn borrow(&mut self, _: &euv::Place<'tcx>, _: ty::BorrowKind) {} -fn unwrap_downcast_or_interior<'a, 'tcx>(mut cmt: &'a mc::cmt_<'tcx>) -> mc::cmt_<'tcx> { - loop { - match cmt.cat { - mc::Categorization::Downcast(ref c, _) | mc::Categorization::Interior(ref c, _) => { - cmt = c; - }, - _ => return (*cmt).clone(), - } - } + fn mutate(&mut self, _: &euv::Place<'tcx>) {} } diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 478ca2e04ffb..ca0d6ace03f5 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -81,6 +81,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { ) { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); let mir = cx.tcx.optimized_mir(def_id); + let mir_read_only = mir.unwrap_read_only(); let dead_unwinds = BitSet::new_empty(mir.basic_blocks().len()); let maybe_storage_live_result = do_dataflow( @@ -94,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { ); let mut possible_borrower = { let mut vis = PossibleBorrowerVisitor::new(cx, mir); - vis.visit_body(mir); + vis.visit_body(mir_read_only); vis.into_map(cx, maybe_storage_live_result) }; @@ -146,7 +147,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { // `arg` is a reference as it is `.deref()`ed in the previous block. // Look into the predecessor block and find out the source of deref. - let ps = mir.predecessors_for(bb); + let ps = mir_read_only.predecessors_for(bb); if ps.len() != 1 { continue; } @@ -208,11 +209,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { if !used_later { let span = terminator.source_info.span; - let node = if let mir::ClearCrossCrate::Set(scope_local_data) = &mir.source_scope_local_data { - scope_local_data[terminator.source_info.scope].lint_root - } else { - unreachable!() - }; + let scope = terminator.source_info.scope; + let node = mir.source_scopes[scope] + .local_data + .as_ref() + .assert_crate_local() + .lint_root; if_chain! { if let Some(snip) = snippet_opt(cx, span); diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index a3d1193052e5..00e2441becf8 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -4,6 +4,8 @@ use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::source_map::Spanned; +use if_chain::if_chain; + use crate::utils::SpanlessEq; use crate::utils::{get_parent_expr, is_allowed, match_type, paths, span_lint, span_lint_and_sugg, walk_ptrs_ty}; @@ -146,53 +148,46 @@ declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr) { use crate::utils::{snippet, snippet_with_applicability}; - use syntax::ast::{LitKind, StrStyle}; + use syntax::ast::LitKind; - if let ExprKind::MethodCall(ref path, _, ref args) = e.kind { - if path.ident.name == sym!(as_bytes) { - if let ExprKind::Lit(ref lit) = args[0].kind { - if let LitKind::Str(ref lit_content, style) = lit.node { - let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#); - let expanded = if let StrStyle::Raw(n) = style { - let term = "#".repeat(usize::from(n)); - format!("r{0}\"{1}\"{0}", term, lit_content.as_str()) - } else { - format!("\"{}\"", lit_content.as_str()) - }; - let mut applicability = Applicability::MachineApplicable; - if callsite.starts_with("include_str!") { - span_lint_and_sugg( - cx, - STRING_LIT_AS_BYTES, - e.span, - "calling `as_bytes()` on `include_str!(..)`", - "consider using `include_bytes!(..)` instead", - snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability).replacen( - "include_str", - "include_bytes", - 1, - ), - applicability, - ); - } else if callsite == expanded - && lit_content.as_str().chars().all(|c| c.is_ascii()) - && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT - && !args[0].span.from_expansion() - { - span_lint_and_sugg( - cx, - STRING_LIT_AS_BYTES, - e.span, - "calling `as_bytes()` on a string literal", - "consider using a byte string literal instead", - format!( - "b{}", - snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability) - ), - applicability, - ); - } - } + if_chain! { + if let ExprKind::MethodCall(path, _, args) = &e.kind; + if path.ident.name == sym!(as_bytes); + if let ExprKind::Lit(lit) = &args[0].kind; + if let LitKind::Str(lit_content, _) = &lit.node; + then { + let callsite = snippet(cx, args[0].span.source_callsite(), r#""foo""#); + let mut applicability = Applicability::MachineApplicable; + if callsite.starts_with("include_str!") { + span_lint_and_sugg( + cx, + STRING_LIT_AS_BYTES, + e.span, + "calling `as_bytes()` on `include_str!(..)`", + "consider using `include_bytes!(..)` instead", + snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability).replacen( + "include_str", + "include_bytes", + 1, + ), + applicability, + ); + } else if lit_content.as_str().is_ascii() + && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT + && !args[0].span.from_expansion() + { + span_lint_and_sugg( + cx, + STRING_LIT_AS_BYTES, + e.span, + "calling `as_bytes()` on a string literal", + "consider using a byte string literal instead", + format!( + "b{}", + snippet_with_applicability(cx, args[0].span, r#""foo""#, &mut applicability) + ), + applicability, + ); } } } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 5a048e1ce43b..23d0ab090201 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -43,7 +43,7 @@ declare_clippy_lint! { /// } /// ``` pub USE_SELF, - pedantic, + nursery, "Unnecessary structure name repetition whereas `Self` is applicable" } diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 5bf105582216..ea7ea5818cd3 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -11,8 +11,10 @@ use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintAr use rustc::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; +use syntax::ast; use syntax::ast::{Crate as AstCrate, ItemKind, Name}; use syntax::source_map::Span; +use syntax::visit::FnKind; use syntax_pos::symbol::SymbolStr; declare_clippy_lint! { @@ -99,6 +101,24 @@ declare_clippy_lint! { "using `cx.outer_expn().expn_data()` instead of `cx.outer_expn_data()`" } +declare_clippy_lint! { + /// **What it does:** Not an actual lint. This lint is only meant for testing our customized internal compiler + /// error message by calling `panic`. + /// + /// **Why is this bad?** ICE in large quantities can damage your teeth + /// + /// **Known problems:** None + /// + /// **Example:** + /// Bad: + /// ```rust,ignore + /// 🍦🍦🍦🍦🍦 + /// ``` + pub PRODUCE_ICE, + internal, + "this message should not appear anywhere as we ICE before and don't emit the lint" +} + declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]); impl EarlyLintPass for ClippyLintsInternal { @@ -302,3 +322,22 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnDataPass { } } } + +declare_lint_pass!(ProduceIce => [PRODUCE_ICE]); + +impl EarlyLintPass for ProduceIce { + fn check_fn(&mut self, _: &EarlyContext<'_>, fn_kind: FnKind<'_>, _: &ast::FnDecl, _: Span, _: ast::NodeId) { + if is_trigger_fn(fn_kind) { + panic!("Testing the ICE message"); + } + } +} + +fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool { + match fn_kind { + FnKind::ItemFn(ident, ..) | FnKind::Method(ident, ..) => { + ident.name.as_str() == "it_looks_like_you_are_trying_to_kill_clippy" + }, + FnKind::Closure(..) => false, + } +} diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index 41662099fd3d..089ebafbb7fd 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -1,11 +1,9 @@ use rustc::hir::def::Res; use rustc::hir::*; use rustc::lint::LateContext; -use rustc::middle::expr_use_visitor::*; -use rustc::middle::mem_categorization::cmt_; -use rustc::middle::mem_categorization::Categorization; use rustc::ty; use rustc_data_structures::fx::FxHashSet; +use rustc_typeck::expr_use_visitor::*; /// Returns a set of mutated local variable IDs, or `None` if mutations could not be determined. pub fn mutated_variables<'a, 'tcx>(expr: &'tcx Expr, cx: &'a LateContext<'a, 'tcx>) -> Option> { @@ -14,16 +12,9 @@ pub fn mutated_variables<'a, 'tcx>(expr: &'tcx Expr, cx: &'a LateContext<'a, 'tc skip: false, }; let def_id = def_id::DefId::local(expr.hir_id.owner); - let region_scope_tree = &cx.tcx.region_scope_tree(def_id); - ExprUseVisitor::new( - &mut delegate, - cx.tcx, - def_id, - cx.param_env, - region_scope_tree, - cx.tables, - ) - .walk_expr(expr); + cx.tcx.infer_ctxt().enter(|infcx| { + ExprUseVisitor::new(&mut delegate, &infcx, def_id, cx.param_env, cx.tables).walk_expr(expr); + }); if delegate.skip { return None; @@ -46,33 +37,32 @@ struct MutVarsDelegate { impl<'tcx> MutVarsDelegate { #[allow(clippy::similar_names)] - fn update(&mut self, cat: &'tcx Categorization<'_>) { - match *cat { - Categorization::Local(id) => { + fn update(&mut self, cat: &Place<'tcx>) { + match cat.base { + PlaceBase::Local(id) => { self.used_mutably.insert(id); }, - Categorization::Upvar(_) => { + PlaceBase::Upvar(_) => { //FIXME: This causes false negatives. We can't get the `NodeId` from //`Categorization::Upvar(_)`. So we search for any `Upvar`s in the //`while`-body, not just the ones in the condition. self.skip = true }, - Categorization::Deref(ref cmt, _) | Categorization::Interior(ref cmt, _) => self.update(&cmt.cat), _ => {}, } } } impl<'tcx> Delegate<'tcx> for MutVarsDelegate { - fn consume(&mut self, _: &cmt_<'tcx>, _: ConsumeMode) {} + fn consume(&mut self, _: &Place<'tcx>, _: ConsumeMode) {} - fn borrow(&mut self, cmt: &cmt_<'tcx>, bk: ty::BorrowKind) { + fn borrow(&mut self, cmt: &Place<'tcx>, bk: ty::BorrowKind) { if let ty::BorrowKind::MutBorrow = bk { - self.update(&cmt.cat) + self.update(&cmt) } } - fn mutate(&mut self, cmt: &cmt_<'tcx>) { - self.update(&cmt.cat) + fn mutate(&mut self, cmt: &Place<'tcx>) { + self.update(&cmt) } } diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml index 5d37f9353754..6f0fc5bee8f0 100644 --- a/rustc_tools_util/Cargo.toml +++ b/rustc_tools_util/Cargo.toml @@ -9,4 +9,8 @@ license = "MIT OR Apache-2.0" keywords = ["rustc", "tool", "git", "version", "hash"] categories = ["development-tools"] edition = "2018" + [dependencies] + +[features] +deny-warnings = [] diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index 36b58a398dc4..ff2a7de57257 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "deny-warnings", deny(warnings))] + use std::env; #[macro_export] diff --git a/setup-toolchain.sh b/setup-toolchain.sh index 9110d7dbffc0..88ae90581e56 100755 --- a/setup-toolchain.sh +++ b/setup-toolchain.sh @@ -5,12 +5,11 @@ set -e cd "$(dirname "$0")" -RTIM_PATH=$(command -v rustup-toolchain-install-master) +RTIM_PATH=$(command -v rustup-toolchain-install-master) || INSTALLED=false CARGO_HOME=${CARGO_HOME:-$HOME/.cargo} -# Check if people also install RTIM in other locations beside -# ~/.cargo/bin -if [[ "$RTIM_PATH" == $CARGO_HOME/bin/rustup-toolchain-install-master ]]; then +# Check if RTIM is not installed or installed in other locations not in ~/.cargo/bin +if [[ "$INSTALLED" == false || "$RTIM_PATH" == $CARGO_HOME/bin/rustup-toolchain-install-master ]]; then cargo +nightly install rustup-toolchain-install-master else VERSION=$(rustup-toolchain-install-master -V | grep -o "[0-9.]*") @@ -27,5 +26,11 @@ if rustc +master -Vv 2>/dev/null | grep -q "$RUST_COMMIT"; then exit 0 fi -rustup-toolchain-install-master -f -n master -c rustc-dev -- "$RUST_COMMIT" +if [[ -n "$HOST_TOOLCHAIN" ]]; then + TOOLCHAIN=('--host' "$HOST_TOOLCHAIN") +else + TOOLCHAIN=() +fi + +rustup-toolchain-install-master -f -n master "${TOOLCHAIN[@]}" -c rustc-dev -- "$RUST_COMMIT" rustup override set master diff --git a/src/driver.rs b/src/driver.rs index 2a4448cc0ec4..fda304afcbe1 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -1,16 +1,25 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] +#![feature(result_map_or)] #![feature(rustc_private)] // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) #[allow(unused_extern_crates)] +extern crate rustc; +#[allow(unused_extern_crates)] extern crate rustc_driver; #[allow(unused_extern_crates)] +extern crate rustc_errors; +#[allow(unused_extern_crates)] extern crate rustc_interface; +use rustc::ty::TyCtxt; use rustc_interface::interface; use rustc_tools_util::*; +use lazy_static::lazy_static; +use std::borrow::Cow; +use std::panic; use std::path::{Path, PathBuf}; use std::process::{exit, Command}; @@ -220,9 +229,64 @@ You can use tool lints to allow or deny lints from your code, eg.: ); } +const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rust-clippy/issues/new"; + +lazy_static! { + static ref ICE_HOOK: Box) + Sync + Send + 'static> = { + let hook = panic::take_hook(); + panic::set_hook(Box::new(|info| report_clippy_ice(info, BUG_REPORT_URL))); + hook + }; +} + +fn report_clippy_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { + // Invoke our ICE handler, which prints the actual panic message and optionally a backtrace + (*ICE_HOOK)(info); + + // Separate the output with an empty line + eprintln!(); + + let emitter = Box::new(rustc_errors::emitter::EmitterWriter::stderr( + rustc_errors::ColorConfig::Auto, + None, + false, + false, + None, + false, + )); + let handler = rustc_errors::Handler::with_emitter(true, None, emitter); + + // a .span_bug or .bug call has already printed what + // it wants to print. + if !info.payload().is::() { + let d = rustc_errors::Diagnostic::new(rustc_errors::Level::Bug, "unexpected panic"); + handler.emit_diagnostic(&d); + handler.abort_if_errors_and_should_abort(); + } + + let version_info = rustc_tools_util::get_version_info!(); + + let xs: Vec> = vec![ + "the compiler unexpectedly panicked. this is a bug.".into(), + format!("we would appreciate a bug report: {}", bug_report_url).into(), + format!("Clippy version: {}", version_info).into(), + ]; + + for note in &xs { + handler.note_without_error(¬e); + } + + // If backtraces are enabled, also print the query stack + let backtrace = std::env::var_os("RUST_BACKTRACE").map_or(false, |x| &x != "0"); + + if backtrace { + TyCtxt::try_print_query_stack(&handler); + } +} + pub fn main() { rustc_driver::init_rustc_env_logger(); - rustc_driver::install_ice_hook(); + lazy_static::initialize(&ICE_HOOK); exit( rustc_driver::catch_fatal_errors(move || { use std::env; @@ -317,10 +381,9 @@ pub fn main() { }; // this check ensures that dependencies are built but not linted and the final - // crate is - // linted but not built - let clippy_enabled = env::var("CLIPPY_TESTS").ok().map_or(false, |val| val == "true") - || arg_value(&orig_args, "--emit", |val| val.split(',').any(|e| e == "metadata")).is_some(); + // crate is linted but not built + let clippy_enabled = env::var("CLIPPY_TESTS").map_or(false, |val| val == "true") + || arg_value(&orig_args, "--cap-lints", |val| val == "allow").is_none(); if clippy_enabled { args.extend_from_slice(&["--cfg".to_owned(), r#"feature="cargo-clippy""#.to_owned()]); diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 9b258ffb610a..5b08571c2588 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 337] = [ +pub const ALL_LINTS: [Lint; 338] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -28,6 +28,13 @@ pub const ALL_LINTS: [Lint; 337] = [ deprecation: None, module: "approx_const", }, + Lint { + name: "as_conversions", + group: "restriction", + desc: "using a potentially dangerous silent `as` conversion", + deprecation: None, + module: "as_conversions", + }, Lint { name: "assertions_on_constants", group: "style", @@ -1697,7 +1704,7 @@ pub const ALL_LINTS: [Lint; 337] = [ Lint { name: "result_map_unwrap_or_else", group: "pedantic", - desc: "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.ok().map_or_else(g, f)`", + desc: "using `Result.map(f).unwrap_or_else(g)`, which is more succinctly expressed as `.map_or_else(g, f)`", deprecation: None, module: "methods", }, @@ -2186,7 +2193,7 @@ pub const ALL_LINTS: [Lint; 337] = [ }, Lint { name: "use_self", - group: "pedantic", + group: "nursery", desc: "Unnecessary structure name repetition whereas `Self` is applicable", deprecation: None, module: "use_self", diff --git a/tests/fmt.rs b/tests/fmt.rs index bc37be84b433..ba35abbfbbb7 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -19,9 +19,11 @@ fn fmt() { let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); let dev_dir = root_dir.join("clippy_dev"); + let target_dir = root_dir.join("target"); + let target_dir = target_dir.to_str().unwrap(); let output = Command::new("cargo") .current_dir(dev_dir) - .args(&["+nightly", "run", "--", "fmt", "--check"]) + .args(&["+nightly", "run", "--target-dir", target_dir, "--", "fmt", "--check"]) .output() .unwrap(); diff --git a/tests/integration.rs b/tests/integration.rs new file mode 100644 index 000000000000..455965436d63 --- /dev/null +++ b/tests/integration.rs @@ -0,0 +1,75 @@ +#![cfg(feature = "integration")] + +use git2::Repository; +use tempfile; + +use std::env; +use std::process::Command; + +#[cfg_attr(feature = "integration", test)] +fn integration_test() { + let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set"); + let repo_url = format!("https://github.com/{}", repo_name); + let crate_name = repo_name + .split('/') + .nth(1) + .expect("repo name should have format `/`"); + + let repo_dir = tempfile::tempdir() + .expect("couldn't create temp dir") + .path() + .join(crate_name); + + Repository::clone(&repo_url, &repo_dir).expect("clone of repo failed"); + + let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let target_dir = std::path::Path::new(&root_dir).join("target"); + let clippy_binary = target_dir.join(env!("PROFILE")).join("cargo-clippy"); + + let output = Command::new(clippy_binary) + .current_dir(repo_dir) + .env("RUST_BACKTRACE", "full") + .env("CARGO_TARGET_DIR", target_dir) + .args(&[ + "clippy", + "--all-targets", + "--all-features", + "--", + "--cap-lints", + "warn", + "-Wclippy::pedantic", + "-Wclippy::nursery", + ]) + .output() + .expect("unable to run clippy"); + + let stderr = String::from_utf8_lossy(&output.stderr); + if stderr.contains("internal compiler error") { + let backtrace_start = stderr + .find("thread 'rustc' panicked at") + .expect("start of backtrace not found"); + let backtrace_end = stderr + .rfind("error: internal compiler error") + .expect("end of backtrace not found"); + + panic!( + "internal compiler error\nBacktrace:\n\n{}", + &stderr[backtrace_start..backtrace_end] + ); + } else if stderr.contains("query stack during panic") { + panic!("query stack during panic in the output"); + } else if stderr.contains("E0463") { + panic!("error: E0463"); + } + + match output.status.code() { + Some(code) => { + if code == 0 { + println!("Compilation successful"); + } else { + eprintln!("Compilation failed. Exit code: {}", code); + } + }, + None => panic!("Process terminated by signal"), + } +} diff --git a/tests/ui/arithmetic.rs b/tests/ui/arithmetic.rs index efcb9b15c9d9..dc11cbd98deb 100644 --- a/tests/ui/arithmetic.rs +++ b/tests/ui/arithmetic.rs @@ -55,6 +55,10 @@ fn main() { f *= 2.0; f /= 2.0; + // no error, overflows are checked by `overflowing_literals` + -1.; + -(-1.); + // No errors for the following items because they are constant expressions enum Foo { Bar = -2, diff --git a/tests/ui/as_conversions.rs b/tests/ui/as_conversions.rs new file mode 100644 index 000000000000..e01ba0c64df3 --- /dev/null +++ b/tests/ui/as_conversions.rs @@ -0,0 +1,7 @@ +#[warn(clippy::as_conversions)] + +fn main() { + let i = 0u32 as u64; + + let j = &i as *const u64 as *mut u64; +} diff --git a/tests/ui/as_conversions.stderr b/tests/ui/as_conversions.stderr new file mode 100644 index 000000000000..312d3a7460eb --- /dev/null +++ b/tests/ui/as_conversions.stderr @@ -0,0 +1,27 @@ +error: using a potentially dangerous silent `as` conversion + --> $DIR/as_conversions.rs:4:13 + | +LL | let i = 0u32 as u64; + | ^^^^^^^^^^^ + | + = note: `-D clippy::as-conversions` implied by `-D warnings` + = help: consider using a safe wrapper for this conversion + +error: using a potentially dangerous silent `as` conversion + --> $DIR/as_conversions.rs:6:13 + | +LL | let j = &i as *const u64 as *mut u64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using a safe wrapper for this conversion + +error: using a potentially dangerous silent `as` conversion + --> $DIR/as_conversions.rs:6:13 + | +LL | let j = &i as *const u64 as *mut u64; + | ^^^^^^^^^^^^^^^^ + | + = help: consider using a safe wrapper for this conversion + +error: aborting due to 3 previous errors + diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs index 611e5a855723..595109be46bb 100644 --- a/tests/ui/cast_size.rs +++ b/tests/ui/cast_size.rs @@ -1,3 +1,4 @@ +// ignore-32bit #[warn( clippy::cast_precision_loss, clippy::cast_possible_truncation, diff --git a/tests/ui/cast_size.stderr b/tests/ui/cast_size.stderr index 735e522b40d9..ec7ed6aec94e 100644 --- a/tests/ui/cast_size.stderr +++ b/tests/ui/cast_size.stderr @@ -1,5 +1,5 @@ error: casting isize to i8 may truncate the value - --> $DIR/cast_size.rs:11:5 + --> $DIR/cast_size.rs:12:5 | LL | 1isize as i8; | ^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | 1isize as i8; = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:14:5 + --> $DIR/cast_size.rs:15:5 | LL | x0 as f64; | ^^^^^^^^^ @@ -15,49 +15,49 @@ LL | x0 as f64; = note: `-D clippy::cast-precision-loss` implied by `-D warnings` error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:15:5 + --> $DIR/cast_size.rs:16:5 | LL | x1 as f64; | ^^^^^^^^^ error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:16:5 + --> $DIR/cast_size.rs:17:5 | LL | x0 as f32; | ^^^^^^^^^ error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:17:5 + --> $DIR/cast_size.rs:18:5 | LL | x1 as f32; | ^^^^^^^^^ error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:18:5 + --> $DIR/cast_size.rs:19:5 | LL | 1isize as i32; | ^^^^^^^^^^^^^ error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:19:5 + --> $DIR/cast_size.rs:20:5 | LL | 1isize as u32; | ^^^^^^^^^^^^^ error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:20:5 + --> $DIR/cast_size.rs:21:5 | LL | 1usize as u32; | ^^^^^^^^^^^^^ error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:21:5 + --> $DIR/cast_size.rs:22:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:21:5 + --> $DIR/cast_size.rs:22:5 | LL | 1usize as i32; | ^^^^^^^^^^^^^ @@ -65,49 +65,49 @@ LL | 1usize as i32; = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:23:5 + --> $DIR/cast_size.rs:24:5 | LL | 1i64 as isize; | ^^^^^^^^^^^^^ error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:24:5 + --> $DIR/cast_size.rs:25:5 | LL | 1i64 as usize; | ^^^^^^^^^^^^^ error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:25:5 + --> $DIR/cast_size.rs:26:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers - --> $DIR/cast_size.rs:25:5 + --> $DIR/cast_size.rs:26:5 | LL | 1u64 as isize; | ^^^^^^^^^^^^^ error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:26:5 + --> $DIR/cast_size.rs:27:5 | LL | 1u64 as usize; | ^^^^^^^^^^^^^ error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers - --> $DIR/cast_size.rs:27:5 + --> $DIR/cast_size.rs:28:5 | LL | 1u32 as isize; | ^^^^^^^^^^^^^ error: casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) - --> $DIR/cast_size.rs:32:5 + --> $DIR/cast_size.rs:33:5 | LL | 999_999_999 as f32; | ^^^^^^^^^^^^^^^^^^ error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) - --> $DIR/cast_size.rs:33:5 + --> $DIR/cast_size.rs:34:5 | LL | 9_999_999_999_999_999usize as f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast_size_32bit.rs b/tests/ui/cast_size_32bit.rs new file mode 100644 index 000000000000..99aac6deca32 --- /dev/null +++ b/tests/ui/cast_size_32bit.rs @@ -0,0 +1,35 @@ +// ignore-64bit +#[warn( + clippy::cast_precision_loss, + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::cast_possible_wrap, + clippy::cast_lossless +)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] +fn main() { + // Casting from *size + 1isize as i8; + let x0 = 1isize; + let x1 = 1usize; + x0 as f64; + x1 as f64; + x0 as f32; + x1 as f32; + 1isize as i32; + 1isize as u32; + 1usize as u32; + 1usize as i32; + // Casting to *size + 1i64 as isize; + 1i64 as usize; + 1u64 as isize; + 1u64 as usize; + 1u32 as isize; + 1u32 as usize; // Should not trigger any lint + 1i32 as isize; // Neither should this + 1i32 as usize; + // Big integer literal to float + 999_999_999 as f32; + 3_999_999_999usize as f64; +} diff --git a/tests/ui/cast_size_32bit.stderr b/tests/ui/cast_size_32bit.stderr new file mode 100644 index 000000000000..cb89630718ae --- /dev/null +++ b/tests/ui/cast_size_32bit.stderr @@ -0,0 +1,132 @@ +error: casting isize to i8 may truncate the value + --> $DIR/cast_size_32bit.rs:12:5 + | +LL | 1isize as i8; + | ^^^^^^^^^^^^ + | + = note: `-D clippy::cast-possible-truncation` implied by `-D warnings` + +error: casting isize to f64 causes a loss of precision on targets with 64-bit wide pointers (isize is 64 bits wide, but f64's mantissa is only 52 bits wide) + --> $DIR/cast_size_32bit.rs:15:5 + | +LL | x0 as f64; + | ^^^^^^^^^ + | + = note: `-D clippy::cast-precision-loss` implied by `-D warnings` + +error: casting isize to f64 may become silently lossy if you later change the type + --> $DIR/cast_size_32bit.rs:15:5 + | +LL | x0 as f64; + | ^^^^^^^^^ help: try: `f64::from(x0)` + | + = note: `-D clippy::cast-lossless` implied by `-D warnings` + +error: casting usize to f64 causes a loss of precision on targets with 64-bit wide pointers (usize is 64 bits wide, but f64's mantissa is only 52 bits wide) + --> $DIR/cast_size_32bit.rs:16:5 + | +LL | x1 as f64; + | ^^^^^^^^^ + +error: casting usize to f64 may become silently lossy if you later change the type + --> $DIR/cast_size_32bit.rs:16:5 + | +LL | x1 as f64; + | ^^^^^^^^^ help: try: `f64::from(x1)` + +error: casting isize to f32 causes a loss of precision (isize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) + --> $DIR/cast_size_32bit.rs:17:5 + | +LL | x0 as f32; + | ^^^^^^^^^ + +error: casting usize to f32 causes a loss of precision (usize is 32 or 64 bits wide, but f32's mantissa is only 23 bits wide) + --> $DIR/cast_size_32bit.rs:18:5 + | +LL | x1 as f32; + | ^^^^^^^^^ + +error: casting isize to i32 may truncate the value on targets with 64-bit wide pointers + --> $DIR/cast_size_32bit.rs:19:5 + | +LL | 1isize as i32; + | ^^^^^^^^^^^^^ + +error: casting isize to u32 may truncate the value on targets with 64-bit wide pointers + --> $DIR/cast_size_32bit.rs:20:5 + | +LL | 1isize as u32; + | ^^^^^^^^^^^^^ + +error: casting usize to u32 may truncate the value on targets with 64-bit wide pointers + --> $DIR/cast_size_32bit.rs:21:5 + | +LL | 1usize as u32; + | ^^^^^^^^^^^^^ + +error: casting usize to i32 may truncate the value on targets with 64-bit wide pointers + --> $DIR/cast_size_32bit.rs:22:5 + | +LL | 1usize as i32; + | ^^^^^^^^^^^^^ + +error: casting usize to i32 may wrap around the value on targets with 32-bit wide pointers + --> $DIR/cast_size_32bit.rs:22:5 + | +LL | 1usize as i32; + | ^^^^^^^^^^^^^ + | + = note: `-D clippy::cast-possible-wrap` implied by `-D warnings` + +error: casting i64 to isize may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast_size_32bit.rs:24:5 + | +LL | 1i64 as isize; + | ^^^^^^^^^^^^^ + +error: casting i64 to usize may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast_size_32bit.rs:25:5 + | +LL | 1i64 as usize; + | ^^^^^^^^^^^^^ + +error: casting u64 to isize may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast_size_32bit.rs:26:5 + | +LL | 1u64 as isize; + | ^^^^^^^^^^^^^ + +error: casting u64 to isize may wrap around the value on targets with 64-bit wide pointers + --> $DIR/cast_size_32bit.rs:26:5 + | +LL | 1u64 as isize; + | ^^^^^^^^^^^^^ + +error: casting u64 to usize may truncate the value on targets with 32-bit wide pointers + --> $DIR/cast_size_32bit.rs:27:5 + | +LL | 1u64 as usize; + | ^^^^^^^^^^^^^ + +error: casting u32 to isize may wrap around the value on targets with 32-bit wide pointers + --> $DIR/cast_size_32bit.rs:28:5 + | +LL | 1u32 as isize; + | ^^^^^^^^^^^^^ + +error: casting i32 to f32 causes a loss of precision (i32 is 32 bits wide, but f32's mantissa is only 23 bits wide) + --> $DIR/cast_size_32bit.rs:33:5 + | +LL | 999_999_999 as f32; + | ^^^^^^^^^^^^^^^^^^ + +error: casting integer literal to f64 is unnecessary + --> $DIR/cast_size_32bit.rs:34:5 + | +LL | 3_999_999_999usize as f64; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `3999999999_f64` + | + = note: `-D clippy::unnecessary-cast` implied by `-D warnings` + +error: aborting due to 20 previous errors + diff --git a/tests/ui/comparison_chain.rs b/tests/ui/comparison_chain.rs index b697413b6e03..9c2128469de9 100644 --- a/tests/ui/comparison_chain.rs +++ b/tests/ui/comparison_chain.rs @@ -76,4 +76,65 @@ fn f(x: u8, y: u8, z: u8) { } } +#[allow(clippy::float_cmp)] +fn g(x: f64, y: f64, z: f64) { + // Ignored: f64 doesn't implement Ord + if x > y { + a() + } else if x < y { + b() + } + + // Ignored: f64 doesn't implement Ord + if x > y { + a() + } else if x < y { + b() + } else { + c() + } + + // Ignored: f64 doesn't implement Ord + if x > y { + a() + } else if y > x { + b() + } else { + c() + } + + // Ignored: f64 doesn't implement Ord + if x > 1.0 { + a() + } else if x < 1.0 { + b() + } else if x == 1.0 { + c() + } +} + +fn h(x: T, y: T, z: T) { + if x > y { + a() + } else if x < y { + b() + } + + if x > y { + a() + } else if x < y { + b() + } else { + c() + } + + if x > y { + a() + } else if y > x { + b() + } else { + c() + } +} + fn main() {} diff --git a/tests/ui/comparison_chain.stderr b/tests/ui/comparison_chain.stderr index 575181dd7194..69db88b03b5b 100644 --- a/tests/ui/comparison_chain.stderr +++ b/tests/ui/comparison_chain.stderr @@ -53,5 +53,45 @@ LL | | } | = help: Consider rewriting the `if` chain to use `cmp` and `match`. -error: aborting due to 4 previous errors +error: `if` chain can be rewritten with `match` + --> $DIR/comparison_chain.rs:117:5 + | +LL | / if x > y { +LL | | a() +LL | | } else if x < y { +LL | | b() +LL | | } + | |_____^ + | + = help: Consider rewriting the `if` chain to use `cmp` and `match`. + +error: `if` chain can be rewritten with `match` + --> $DIR/comparison_chain.rs:123:5 + | +LL | / if x > y { +LL | | a() +LL | | } else if x < y { +LL | | b() +LL | | } else { +LL | | c() +LL | | } + | |_____^ + | + = help: Consider rewriting the `if` chain to use `cmp` and `match`. + +error: `if` chain can be rewritten with `match` + --> $DIR/comparison_chain.rs:131:5 + | +LL | / if x > y { +LL | | a() +LL | | } else if y > x { +LL | | b() +LL | | } else { +LL | | c() +LL | | } + | |_____^ + | + = help: Consider rewriting the `if` chain to use `cmp` and `match`. + +error: aborting due to 7 previous errors diff --git a/tests/ui/custom_ice_message.rs b/tests/ui/custom_ice_message.rs new file mode 100644 index 000000000000..5b30c9d5721c --- /dev/null +++ b/tests/ui/custom_ice_message.rs @@ -0,0 +1,10 @@ +// rustc-env:RUST_BACKTRACE=0 +// normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo" +// normalize-stderr-test: "internal_lints.rs:\d*:\d*" -> "internal_lints.rs" +// normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints" + +#![deny(clippy::internal)] + +fn it_looks_like_you_are_trying_to_kill_clippy() {} + +fn main() {} diff --git a/tests/ui/custom_ice_message.stderr b/tests/ui/custom_ice_message.stderr new file mode 100644 index 000000000000..817e48724337 --- /dev/null +++ b/tests/ui/custom_ice_message.stderr @@ -0,0 +1,11 @@ +thread 'rustc' panicked at 'Testing the ICE message', clippy_lints/src/utils/internal_lints.rs +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. + +error: internal compiler error: unexpected panic + +note: the compiler unexpectedly panicked. this is a bug. + +note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new + +note: Clippy version: foo + diff --git a/tests/ui/fn_to_numeric_cast.rs b/tests/ui/fn_to_numeric_cast.rs index 21573af870a8..a456c085c876 100644 --- a/tests/ui/fn_to_numeric_cast.rs +++ b/tests/ui/fn_to_numeric_cast.rs @@ -1,4 +1,4 @@ -// only-64bit +// ignore-32bit #![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] diff --git a/tests/ui/fn_to_numeric_cast_32bit.rs b/tests/ui/fn_to_numeric_cast_32bit.rs new file mode 100644 index 000000000000..04ee985c0863 --- /dev/null +++ b/tests/ui/fn_to_numeric_cast_32bit.rs @@ -0,0 +1,55 @@ +// ignore-64bit + +#![warn(clippy::fn_to_numeric_cast, clippy::fn_to_numeric_cast_with_truncation)] + +fn foo() -> String { + String::new() +} + +fn test_function_to_numeric_cast() { + let _ = foo as i8; + let _ = foo as i16; + let _ = foo as i32; + let _ = foo as i64; + let _ = foo as i128; + let _ = foo as isize; + + let _ = foo as u8; + let _ = foo as u16; + let _ = foo as u32; + let _ = foo as u64; + let _ = foo as u128; + + // Casting to usize is OK and should not warn + let _ = foo as usize; + + // Cast `f` (a `FnDef`) to `fn()` should not warn + fn f() {} + let _ = f as fn(); +} + +fn test_function_var_to_numeric_cast() { + let abc: fn() -> String = foo; + + let _ = abc as i8; + let _ = abc as i16; + let _ = abc as i32; + let _ = abc as i64; + let _ = abc as i128; + let _ = abc as isize; + + let _ = abc as u8; + let _ = abc as u16; + let _ = abc as u32; + let _ = abc as u64; + let _ = abc as u128; + + // Casting to usize is OK and should not warn + let _ = abc as usize; +} + +fn fn_with_fn_args(f: fn(i32) -> i32) -> i32 { + f as i32 +} + +fn main() {} diff --git a/tests/ui/fn_to_numeric_cast_32bit.stderr b/tests/ui/fn_to_numeric_cast_32bit.stderr new file mode 100644 index 000000000000..08dd611d6752 --- /dev/null +++ b/tests/ui/fn_to_numeric_cast_32bit.stderr @@ -0,0 +1,144 @@ +error: casting function pointer `foo` to `i8`, which truncates the value + --> $DIR/fn_to_numeric_cast_32bit.rs:10:13 + | +LL | let _ = foo as i8; + | ^^^^^^^^^ help: try: `foo as usize` + | + = note: `-D clippy::fn-to-numeric-cast-with-truncation` implied by `-D warnings` + +error: casting function pointer `foo` to `i16`, which truncates the value + --> $DIR/fn_to_numeric_cast_32bit.rs:11:13 + | +LL | let _ = foo as i16; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `i32` + --> $DIR/fn_to_numeric_cast_32bit.rs:12:13 + | +LL | let _ = foo as i32; + | ^^^^^^^^^^ help: try: `foo as usize` + | + = note: `-D clippy::fn-to-numeric-cast` implied by `-D warnings` + +error: casting function pointer `foo` to `i64` + --> $DIR/fn_to_numeric_cast_32bit.rs:13:13 + | +LL | let _ = foo as i64; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `i128` + --> $DIR/fn_to_numeric_cast_32bit.rs:14:13 + | +LL | let _ = foo as i128; + | ^^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `isize` + --> $DIR/fn_to_numeric_cast_32bit.rs:15:13 + | +LL | let _ = foo as isize; + | ^^^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u8`, which truncates the value + --> $DIR/fn_to_numeric_cast_32bit.rs:17:13 + | +LL | let _ = foo as u8; + | ^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u16`, which truncates the value + --> $DIR/fn_to_numeric_cast_32bit.rs:18:13 + | +LL | let _ = foo as u16; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u32` + --> $DIR/fn_to_numeric_cast_32bit.rs:19:13 + | +LL | let _ = foo as u32; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u64` + --> $DIR/fn_to_numeric_cast_32bit.rs:20:13 + | +LL | let _ = foo as u64; + | ^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `foo` to `u128` + --> $DIR/fn_to_numeric_cast_32bit.rs:21:13 + | +LL | let _ = foo as u128; + | ^^^^^^^^^^^ help: try: `foo as usize` + +error: casting function pointer `abc` to `i8`, which truncates the value + --> $DIR/fn_to_numeric_cast_32bit.rs:34:13 + | +LL | let _ = abc as i8; + | ^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `i16`, which truncates the value + --> $DIR/fn_to_numeric_cast_32bit.rs:35:13 + | +LL | let _ = abc as i16; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `i32` + --> $DIR/fn_to_numeric_cast_32bit.rs:36:13 + | +LL | let _ = abc as i32; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `i64` + --> $DIR/fn_to_numeric_cast_32bit.rs:37:13 + | +LL | let _ = abc as i64; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `i128` + --> $DIR/fn_to_numeric_cast_32bit.rs:38:13 + | +LL | let _ = abc as i128; + | ^^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `isize` + --> $DIR/fn_to_numeric_cast_32bit.rs:39:13 + | +LL | let _ = abc as isize; + | ^^^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u8`, which truncates the value + --> $DIR/fn_to_numeric_cast_32bit.rs:41:13 + | +LL | let _ = abc as u8; + | ^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u16`, which truncates the value + --> $DIR/fn_to_numeric_cast_32bit.rs:42:13 + | +LL | let _ = abc as u16; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u32` + --> $DIR/fn_to_numeric_cast_32bit.rs:43:13 + | +LL | let _ = abc as u32; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u64` + --> $DIR/fn_to_numeric_cast_32bit.rs:44:13 + | +LL | let _ = abc as u64; + | ^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `abc` to `u128` + --> $DIR/fn_to_numeric_cast_32bit.rs:45:13 + | +LL | let _ = abc as u128; + | ^^^^^^^^^^^ help: try: `abc as usize` + +error: casting function pointer `f` to `i32` + --> $DIR/fn_to_numeric_cast_32bit.rs:52:5 + | +LL | f as i32 + | ^^^^^^^^ help: try: `f as usize` + +error: aborting due to 23 previous errors + diff --git a/tests/ui/large_digit_groups.fixed b/tests/ui/large_digit_groups.fixed index 02daa22bb36e..859fad2f54d9 100644 --- a/tests/ui/large_digit_groups.fixed +++ b/tests/ui/large_digit_groups.fixed @@ -1,6 +1,6 @@ // run-rustfix -#[warn(clippy::large_digit_groups)] -#[allow(unused_variables)] +#![warn(clippy::large_digit_groups)] + fn main() { macro_rules! mac { () => { @@ -8,7 +8,7 @@ fn main() { }; } - let good = ( + let _good = ( 0b1011_i64, 0o1_234_u32, 0x1_234_567, @@ -18,15 +18,14 @@ fn main() { 1_234.123_f32, 1.123_4_f32, ); - let bad = ( + let _bad = ( 0b11_0110_i64, - 0x0123_4567_8901_usize, + 0xdead_beef_usize, 123_456_f32, 123_456.12_f32, 123_456.123_45_f64, 123_456.123_456_f64, ); - // Ignore literals in macros let _ = mac!(); } diff --git a/tests/ui/large_digit_groups.rs b/tests/ui/large_digit_groups.rs index c1bb78c9d832..ac116d5dbda1 100644 --- a/tests/ui/large_digit_groups.rs +++ b/tests/ui/large_digit_groups.rs @@ -1,6 +1,6 @@ // run-rustfix -#[warn(clippy::large_digit_groups)] -#[allow(unused_variables)] +#![warn(clippy::large_digit_groups)] + fn main() { macro_rules! mac { () => { @@ -8,7 +8,7 @@ fn main() { }; } - let good = ( + let _good = ( 0b1011_i64, 0o1_234_u32, 0x1_234_567, @@ -18,15 +18,14 @@ fn main() { 1_234.123_f32, 1.123_4_f32, ); - let bad = ( + let _bad = ( 0b1_10110_i64, - 0x1_23456_78901_usize, + 0xd_e_adbee_f_usize, 1_23456_f32, 1_23456.12_f32, 1_23456.12345_f64, 1_23456.12345_6_f64, ); - // Ignore literals in macros let _ = mac!(); } diff --git a/tests/ui/large_digit_groups.stderr b/tests/ui/large_digit_groups.stderr index ba8ea6b53e7f..b6d9672a78e2 100644 --- a/tests/ui/large_digit_groups.stderr +++ b/tests/ui/large_digit_groups.stderr @@ -6,11 +6,13 @@ LL | 0b1_10110_i64, | = note: `-D clippy::large-digit-groups` implied by `-D warnings` -error: digit groups should be smaller +error: digits grouped inconsistently by underscores --> $DIR/large_digit_groups.rs:23:9 | -LL | 0x1_23456_78901_usize, - | ^^^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` +LL | 0xd_e_adbee_f_usize, + | ^^^^^^^^^^^^^^^^^^^ help: consider: `0xdead_beef_usize` + | + = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: digit groups should be smaller --> $DIR/large_digit_groups.rs:24:9 diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs index 2b2ea6c94c26..b73b24b8e0a3 100644 --- a/tests/ui/missing_inline.rs +++ b/tests/ui/missing_inline.rs @@ -60,3 +60,7 @@ impl Foo { impl PubFoo { pub fn PubFooImpl() {} // missing #[inline] } + +// do not lint this since users cannot control the external code +#[derive(Debug)] +pub struct S {} diff --git a/tests/ui/my_lint.rs b/tests/ui/my_lint.rs deleted file mode 100644 index c27fd5be1345..000000000000 --- a/tests/ui/my_lint.rs +++ /dev/null @@ -1,7 +0,0 @@ -#[clippy::author] -#[cfg(any(target_arch = "x86"))] -pub struct Foo { - x: u32, -} - -fn main() {} diff --git a/tests/ui/needless_doc_main.rs b/tests/ui/needless_doc_main.rs new file mode 100644 index 000000000000..d2a3857b554f --- /dev/null +++ b/tests/ui/needless_doc_main.rs @@ -0,0 +1,33 @@ +/// This is a test for needless `fn main()` in doctests. +/// +/// # Examples +/// +/// This should lint +/// ``` +/// fn main() { +/// unimplemented!(); +/// } +/// ``` +fn bad_doctest() {} + +/// # Examples +/// +/// This shouldn't lint, because the `main` is empty: +/// ``` +/// fn main(){} +/// ``` +/// +/// This shouldn't lint either, because there's a `static`: +/// ``` +/// static ANSWER: i32 = 42; +/// +/// fn main() { +/// assert_eq!(42, ANSWER); +/// } +/// ``` +fn no_false_positives() {} + +fn main() { + bad_doctest(); + no_false_positives(); +} diff --git a/tests/ui/needless_doc_main.stderr b/tests/ui/needless_doc_main.stderr new file mode 100644 index 000000000000..22d145aad585 --- /dev/null +++ b/tests/ui/needless_doc_main.stderr @@ -0,0 +1,10 @@ +error: needless `fn main` in doctest + --> $DIR/needless_doc_main.rs:7:4 + | +LL | /// fn main() { + | ^^^^^^^^^^^^ + | + = note: `-D clippy::needless-doctest-main` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/result_map_unwrap_or_else.stderr b/tests/ui/result_map_unwrap_or_else.stderr index 7674b91c1288..2b014e9ebb1a 100644 --- a/tests/ui/result_map_unwrap_or_else.stderr +++ b/tests/ui/result_map_unwrap_or_else.stderr @@ -1,27 +1,27 @@ -error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `.map_or_else(g, f)` instead --> $DIR/result_map_unwrap_or_else.rs:15:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` - = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` -error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `.map_or_else(g, f)` instead --> $DIR/result_map_unwrap_or_else.rs:17:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` -error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `.map_or_else(g, f)` instead --> $DIR/result_map_unwrap_or_else.rs:18:13 | LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `map_or_else(|e| 0, |x| x + 1)` error: aborting due to 3 previous errors diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index c8d1479f1206..7ad272ade5f9 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -15,6 +15,8 @@ fn str_lit_as_bytes() { let strify = stringify!(foobar).as_bytes(); let includestr = include_bytes!("entry_unfixable.rs"); + + let _ = b"string with newline\t\n"; } fn main() {} diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index f0066d5d177b..1bf4538b7c94 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -15,6 +15,8 @@ fn str_lit_as_bytes() { let strify = stringify!(foobar).as_bytes(); let includestr = include_str!("entry_unfixable.rs").as_bytes(); + + let _ = "string with newline\t\n".as_bytes(); } fn main() {} diff --git a/tests/ui/string_lit_as_bytes.stderr b/tests/ui/string_lit_as_bytes.stderr index d6c6c52709f8..ff6e3346dfc7 100644 --- a/tests/ui/string_lit_as_bytes.stderr +++ b/tests/ui/string_lit_as_bytes.stderr @@ -18,5 +18,11 @@ error: calling `as_bytes()` on `include_str!(..)` LL | let includestr = include_str!("entry_unfixable.rs").as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry_unfixable.rs")` -error: aborting due to 3 previous errors +error: calling `as_bytes()` on a string literal + --> $DIR/string_lit_as_bytes.rs:19:13 + | +LL | let _ = "string with newline/t/n".as_bytes(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"string with newline/t/n"` + +error: aborting due to 4 previous errors diff --git a/tests/ui/transmute_32bit.rs b/tests/ui/transmute_32bit.rs index 1b50133d3918..ffe22b12f551 100644 --- a/tests/ui/transmute_32bit.rs +++ b/tests/ui/transmute_32bit.rs @@ -1,6 +1,6 @@ -//ignore-x86_64 +// ignore-64bit -#[warn(wrong_transmute)] +#[warn(clippy::wrong_transmute)] fn main() { unsafe { let _: *const usize = std::mem::transmute(6.0f32); diff --git a/tests/ui/transmute_32bit.stderr b/tests/ui/transmute_32bit.stderr new file mode 100644 index 000000000000..040519564b94 --- /dev/null +++ b/tests/ui/transmute_32bit.stderr @@ -0,0 +1,28 @@ +error: transmute from a `f32` to a pointer + --> $DIR/transmute_32bit.rs:6:31 + | +LL | let _: *const usize = std::mem::transmute(6.0f32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::wrong-transmute` implied by `-D warnings` + +error: transmute from a `f32` to a pointer + --> $DIR/transmute_32bit.rs:8:29 + | +LL | let _: *mut usize = std::mem::transmute(6.0f32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: transmute from a `char` to a pointer + --> $DIR/transmute_32bit.rs:10:31 + | +LL | let _: *const usize = std::mem::transmute('x'); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: transmute from a `char` to a pointer + --> $DIR/transmute_32bit.rs:12:29 + | +LL | let _: *mut usize = std::mem::transmute('x'); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/transmute_64bit.rs b/tests/ui/transmute_64bit.rs index aee5152d6472..00dc0b2c3608 100644 --- a/tests/ui/transmute_64bit.rs +++ b/tests/ui/transmute_64bit.rs @@ -1,5 +1,4 @@ -//ignore-x86 -//no-ignore-x86_64 +// ignore-32bit #[warn(clippy::wrong_transmute)] fn main() { diff --git a/tests/ui/transmute_64bit.stderr b/tests/ui/transmute_64bit.stderr index 457050ec504b..d1854c009ef5 100644 --- a/tests/ui/transmute_64bit.stderr +++ b/tests/ui/transmute_64bit.stderr @@ -1,5 +1,5 @@ error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:7:31 + --> $DIR/transmute_64bit.rs:6:31 | LL | let _: *const usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let _: *const usize = std::mem::transmute(6.0f64); = note: `-D clippy::wrong-transmute` implied by `-D warnings` error: transmute from a `f64` to a pointer - --> $DIR/transmute_64bit.rs:9:29 + --> $DIR/transmute_64bit.rs:8:29 | LL | let _: *mut usize = std::mem::transmute(6.0f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/types.fixed b/tests/ui/types.fixed index b1622e45f3b3..417da42edf17 100644 --- a/tests/ui/types.fixed +++ b/tests/ui/types.fixed @@ -1,7 +1,7 @@ // run-rustfix #![allow(dead_code, unused_variables)] -#![warn(clippy::all, clippy::pedantic)] +#![warn(clippy::cast_lossless)] // should not warn on lossy casting in constant types // because not supported yet diff --git a/tests/ui/types.rs b/tests/ui/types.rs index 30463f9e2a17..b16e9e538b10 100644 --- a/tests/ui/types.rs +++ b/tests/ui/types.rs @@ -1,7 +1,7 @@ // run-rustfix #![allow(dead_code, unused_variables)] -#![warn(clippy::all, clippy::pedantic)] +#![warn(clippy::cast_lossless)] // should not warn on lossy casting in constant types // because not supported yet diff --git a/tests/ui/unreadable_literal.fixed b/tests/ui/unreadable_literal.fixed index 679b962756ca..3f358d9ecaa0 100644 --- a/tests/ui/unreadable_literal.fixed +++ b/tests/ui/unreadable_literal.fixed @@ -1,5 +1,7 @@ // run-rustfix +#![warn(clippy::unreadable_literal)] + struct Foo(u64); macro_rules! foo { @@ -8,10 +10,8 @@ macro_rules! foo { }; } -#[warn(clippy::unreadable_literal)] -#[allow(unused_variables)] fn main() { - let good = ( + let _good = ( 0b1011_i64, 0o1_234_u32, 0x1_234_567, @@ -22,14 +22,14 @@ fn main() { 1_234.123_f32, 1.123_4_f32, ); - 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 _bad = (0b11_0110_i64, 0xcafe_babe_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; + let _fail9 = 0x00ab_cdef; + let _fail10: u32 = 0xBAFE_BAFE; + let _fail11 = 0x0abc_deff; + let _fail12: i128 = 0x00ab_cabc_abca_bcab_cabc; let _ = foo!(); } diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index 9922f01aa00f..e658a5f28c90 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -1,5 +1,7 @@ // run-rustfix +#![warn(clippy::unreadable_literal)] + struct Foo(u64); macro_rules! foo { @@ -8,10 +10,8 @@ macro_rules! foo { }; } -#[warn(clippy::unreadable_literal)] -#[allow(unused_variables)] fn main() { - let good = ( + let _good = ( 0b1011_i64, 0o1_234_u32, 0x1_234_567, @@ -22,14 +22,14 @@ fn main() { 1_234.123_f32, 1.123_4_f32, ); - let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - let good_sci = 1.1234e1; - let bad_sci = 1.123456e1; + let _bad = (0b110110_i64, 0xcafebabe_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; + let _fail9 = 0xabcdef; + let _fail10: u32 = 0xBAFEBAFE; + let _fail11 = 0xabcdeff; + let _fail12: i128 = 0xabcabcabcabcabcabc; let _ = foo!(); } diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index a31ff75955ca..1b2ff6bff048 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -1,58 +1,58 @@ error: long literal lacking separators - --> $DIR/unreadable_literal.rs:25:16 + --> $DIR/unreadable_literal.rs:25:17 | -LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` +LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` | = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:25:30 + --> $DIR/unreadable_literal.rs:25:31 | -LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` +LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^^^^^^^ help: consider: `0xcafe_babe_usize` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:25:51 + --> $DIR/unreadable_literal.rs:25:49 | -LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - | ^^^^^^^^^^ help: consider: `123_456_f32` +LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^ help: consider: `123_456_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:25:63 + --> $DIR/unreadable_literal.rs:25:61 | -LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); - | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` +LL | let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32); + | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:27:19 + --> $DIR/unreadable_literal.rs:27:20 | -LL | let bad_sci = 1.123456e1; - | ^^^^^^^^^^ help: consider: `1.123_456e1` +LL | let _bad_sci = 1.123456e1; + | ^^^^^^^^^^ help: consider: `1.123_456e1` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:29:17 + --> $DIR/unreadable_literal.rs:29:18 | -LL | let fail9 = 0xabcdef; - | ^^^^^^^^ help: consider: `0x00ab_cdef` +LL | let _fail9 = 0xabcdef; + | ^^^^^^^^ help: consider: `0x00ab_cdef` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:30:23 + --> $DIR/unreadable_literal.rs:30:24 | -LL | let fail10: u32 = 0xBAFEBAFE; - | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` +LL | let _fail10: u32 = 0xBAFEBAFE; + | ^^^^^^^^^^ help: consider: `0xBAFE_BAFE` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:31:18 + --> $DIR/unreadable_literal.rs:31:19 | -LL | let fail11 = 0xabcdeff; - | ^^^^^^^^^ help: consider: `0x0abc_deff` +LL | let _fail11 = 0xabcdeff; + | ^^^^^^^^^ help: consider: `0x0abc_deff` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:32:24 + --> $DIR/unreadable_literal.rs:32:25 | -LL | let fail12: i128 = 0xabcabcabcabcabcabc; - | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` +LL | let _fail12: i128 = 0xabcabcabcabcabcabc; + | ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc` error: aborting due to 9 previous errors