Merge branch 'master' into issue_2741

This commit is contained in:
Michael Wright 2018-06-26 07:46:56 +02:00
commit 4827bdcc1c
54 changed files with 1605 additions and 758 deletions

View File

@ -48,7 +48,6 @@ matrix:
- env: INTEGRATION=serde-rs/serde
- env: INTEGRATION=Geal/nom
- env: INTEGRATION=hyperium/hyper
allow_failures:
- env: INTEGRATION=rust-lang/cargo
- env: INTEGRATION=rust-lang-nursery/rls

View File

@ -1,6 +1,12 @@
# Change Log
All notable changes to this project will be documented in this file.
## 0.0.210
* Rustup to *rustc 1.28.0-nightly (01cc982e9 2018-06-24)*
## 0.0.209
* Rustup to *rustc 1.28.0-nightly (523097979 2018-06-18)*
## 0.0.208
* Rustup to *rustc 1.28.0-nightly (86a8f1a63 2018-06-17)*
@ -635,6 +641,7 @@ All notable changes to this project will be documented in this file.
[`crosspointer_transmute`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#crosspointer_transmute
[`cyclomatic_complexity`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#cyclomatic_complexity
[`decimal_literal_representation`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#decimal_literal_representation
[`default_trait_access`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#default_trait_access
[`deprecated_semver`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deprecated_semver
[`deref_addrof`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#deref_addrof
[`derive_hash_xor_eq`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
@ -775,6 +782,7 @@ All notable changes to this project will be documented in this file.
[`out_of_bounds_indexing`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#out_of_bounds_indexing
[`overflow_check_conditional`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#overflow_check_conditional
[`panic_params`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#panic_params
[`panicking_unwrap`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#panicking_unwrap
[`partialeq_ne_impl`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#partialeq_ne_impl
[`possible_missing_comma`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#possible_missing_comma
[`precedence`]: https://rust-lang-nursery.github.io/rust-clippy/master/index.html#precedence

View File

@ -2,7 +2,7 @@ cargo-features = ["edition"]
[package]
name = "clippy"
version = "0.0.208"
version = "0.0.210"
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",
"Andre Bogus <bogusandre@gmail.com>",
@ -40,7 +40,7 @@ path = "src/driver.rs"
[dependencies]
# begin automatic update
clippy_lints = { version = "0.0.208", path = "clippy_lints" }
clippy_lints = { version = "0.0.210", path = "clippy_lints" }
# end automatic update
regex = "1"
semver = "0.9"

View File

@ -1,13 +1,15 @@
We are currently in the process of discussing Clippy 1.0 via the RFC process in https://github.com/rust-lang/rfcs/pull/2476 . The RFC's goal is to clarify policies around lint categorizations and the policy around which lints should be in the compiler and which lints should be in clippy. Please leave your thoughts on the RFC PR.
# rust-clippy
[![Build Status](https://travis-ci.org/rust-lang-nursery/rust-clippy.svg?branch=master)](https://travis-ci.org/rust-lang-nursery/rust-clippy)
[![Windows build status](https://ci.appveyor.com/api/projects/status/github/rust-lang-nursery/rust-clippy?svg=true)](https://ci.appveyor.com/project/rust-lang-nursery/rust-clippy)
[![Windows Build status](https://ci.appveyor.com/api/projects/status/id677xpw1dguo7iw?svg=true)](https://ci.appveyor.com/project/rust-lang-libs/rust-clippy)
[![Current Version](https://meritbadge.herokuapp.com/clippy)](https://crates.io/crates/clippy)
[![License: MPL-2.0](https://img.shields.io/crates/l/clippy.svg)](#license)
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
[There are 268 lints included in this crate!](https://rust-lang-nursery.github.io/rust-clippy/master/index.html)
[There are 270 lints included in this crate!](https://rust-lang-nursery.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:

View File

@ -3,7 +3,7 @@ cargo-features = ["edition"]
[package]
name = "clippy_lints"
# begin automatic update
version = "0.0.208"
version = "0.0.210"
# end automatic update
authors = [
"Manish Goregaokar <manishsmail@gmail.com>",

View File

@ -1,123 +0,0 @@
use crate::consts::{constant, Constant};
use crate::utils::higher::Range;
use crate::utils::{self, higher};
use rustc::hir;
use rustc::lint::*;
use rustc::ty;
use syntax::ast::RangeLimits;
/// **What it does:** Checks for out of bounds array indexing with a constant
/// index.
///
/// **Why is this bad?** This will always panic at runtime.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
/// ```rust
/// let x = [1,2,3,4];
/// ...
/// x[9];
/// &x[2..9];
/// ```
declare_clippy_lint! {
pub OUT_OF_BOUNDS_INDEXING,
correctness,
"out of bounds constant indexing"
}
/// **What it does:** Checks for usage of indexing or slicing.
///
/// **Why is this bad?** Usually, this can be safely allowed. However, in some
/// domains such as kernel development, a panic can cause the whole operating
/// system to crash.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
/// ```rust
/// ...
/// x[2];
/// &x[0..2];
/// ```
declare_clippy_lint! {
pub INDEXING_SLICING,
restriction,
"indexing/slicing usage"
}
#[derive(Copy, Clone)]
pub struct ArrayIndexing;
impl LintPass for ArrayIndexing {
fn get_lints(&self) -> LintArray {
lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING)
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ArrayIndexing {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
if let hir::ExprIndex(ref array, ref index) = e.node {
// Array with known size can be checked statically
let ty = cx.tables.expr_ty(array);
if let ty::TyArray(_, size) = ty.sty {
let size = size.assert_usize(cx.tcx).unwrap().into();
// Index is a constant uint
if let Some((Constant::Int(const_index), _)) = constant(cx, cx.tables, index) {
if size <= const_index {
utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "const index is out of bounds");
}
return;
}
// Index is a constant range
if let Some(range) = higher::range(cx, index) {
if let Some((start, end)) = to_const_range(cx, range, size) {
if start > size || end > size {
utils::span_lint(cx, OUT_OF_BOUNDS_INDEXING, e.span, "range is out of bounds");
}
return;
}
}
}
if let Some(range) = higher::range(cx, index) {
// Full ranges are always valid
if range.start.is_none() && range.end.is_none() {
return;
}
// Impossible to know if indexing or slicing is correct
utils::span_lint(cx, INDEXING_SLICING, e.span, "slicing may panic");
} else {
utils::span_lint(cx, INDEXING_SLICING, e.span, "indexing may panic");
}
}
}
}
/// Returns an option containing a tuple with the start and end (exclusive) of
/// the range.
fn to_const_range<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, range: Range, array_size: u128) -> Option<(u128, u128)> {
let s = range.start.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c));
let start = match s {
Some(Some(Constant::Int(x))) => x,
Some(_) => return None,
None => 0,
};
let e = range.end.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c));
let end = match e {
Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed {
x + 1
} else {
x
},
Some(_) => return None,
None => array_size,
};
Some((start, end))
}

View File

@ -207,7 +207,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AttrPass {
}
fn is_relevant_item(tcx: TyCtxt, item: &Item) -> bool {
if let ItemFn(_, _, _, _, _, eid) = item.node {
if let ItemFn(_, _, _, eid) = item.node {
is_relevant_expr(tcx, tcx.body_tables(eid), &tcx.hir.body(eid).value)
} else {
true

View File

@ -0,0 +1,68 @@
use rustc::hir::*;
use rustc::lint::*;
use rustc::ty::TypeVariants;
use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg};
/// **What it does:** Checks for literal calls to `Default::default()`.
///
/// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
/// being gotten than the generic `Default`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// // Bad
/// let s: String = Default::default();
///
/// // Good
/// let s = String::default();
/// ```
declare_clippy_lint! {
pub DEFAULT_TRAIT_ACCESS,
style,
"checks for literal calls to Default::default()"
}
#[derive(Copy, Clone)]
pub struct DefaultTraitAccess;
impl LintPass for DefaultTraitAccess {
fn get_lints(&self) -> LintArray {
lint_array!(DEFAULT_TRAIT_ACCESS)
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
if let ExprCall(ref path, ..) = expr.node;
if !any_parent_is_automatically_derived(cx.tcx, expr.id);
if let ExprPath(ref qpath) = path.node;
if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id));
if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD);
then {
match qpath {
QPath::Resolved(..) => {
// TODO: Work out a way to put "whatever the imported way of referencing
// this type in this file" rather than a fully-qualified type.
let expr_ty = cx.tables.expr_ty(expr);
if let TypeVariants::TyAdt(..) = expr_ty.sty {
let replacement = format!("{}::default()", expr_ty);
span_lint_and_sugg(
cx,
DEFAULT_TRAIT_ACCESS,
expr.span,
&format!("Calling {} is more clear than this expression", replacement),
"try",
replacement);
}
},
QPath::TypeRelative(..) => {},
}
}
}
}
}

View File

@ -124,7 +124,7 @@ impl<'a, 'tcx> DivergenceVisitor<'a, 'tcx> {
impl<'a, 'tcx> Visitor<'tcx> for DivergenceVisitor<'a, 'tcx> {
fn visit_expr(&mut self, e: &'tcx Expr) {
match e.node {
ExprAgain(_) | ExprBreak(_, _) | ExprRet(_) => self.report_diverging_sub_expr(e),
ExprContinue(_) | ExprBreak(_, _) | ExprRet(_) => self.report_diverging_sub_expr(e),
ExprCall(ref func, _) => {
let typ = self.cx.tables.expr_ty(func);
match typ.sty {

View File

@ -92,8 +92,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
};
let unsafety = match kind {
hir::intravisit::FnKind::ItemFn(_, _, unsafety, _, _, _, _) => unsafety,
hir::intravisit::FnKind::Method(_, sig, _, _) => sig.unsafety,
hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { unsafety, .. }, _, _) => unsafety,
hir::intravisit::FnKind::Method(_, sig, _, _) => sig.header.unsafety,
hir::intravisit::FnKind::Closure(_) => return,
};
@ -101,8 +101,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
if !is_impl {
// don't lint extern functions decls, it's not their fault either
match kind {
hir::intravisit::FnKind::Method(_, &hir::MethodSig { abi: Abi::Rust, .. }, _, _) |
hir::intravisit::FnKind::ItemFn(_, _, _, _, Abi::Rust, _, _) => self.check_arg_number(cx, decl, span),
hir::intravisit::FnKind::Method(_, &hir::MethodSig { header: hir::FnHeader { abi: Abi::Rust, .. }, .. }, _, _) |
hir::intravisit::FnKind::ItemFn(_, _, hir::FnHeader { abi: Abi::Rust, .. }, _, _) => self.check_arg_number(cx, decl, span),
_ => {},
}
}
@ -113,13 +113,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Functions {
fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::TraitItem) {
if let hir::TraitItemKind::Method(ref sig, ref eid) = item.node {
// don't lint extern functions decls, it's not their fault
if sig.abi == Abi::Rust {
if sig.header.abi == Abi::Rust {
self.check_arg_number(cx, &sig.decl, item.span);
}
if let hir::TraitMethod::Provided(eid) = *eid {
let body = cx.tcx.hir.body(eid);
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, body, item.id);
self.check_raw_ptr(cx, sig.header.unsafety, &sig.decl, body, item.id);
}
}
}

View File

@ -0,0 +1,183 @@
//! lint on indexing and slicing operations
use crate::consts::{constant, Constant};
use crate::utils;
use crate::utils::higher;
use crate::utils::higher::Range;
use rustc::hir::*;
use rustc::lint::*;
use rustc::ty;
use syntax::ast::RangeLimits;
/// **What it does:** Checks for out of bounds array indexing with a constant
/// index.
///
/// **Why is this bad?** This will always panic at runtime.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
/// ```rust
/// let x = [1,2,3,4];
///
/// // Bad
/// x[9];
/// &x[2..9];
///
/// // Good
/// x[0];
/// x[3];
/// ```
declare_clippy_lint! {
pub OUT_OF_BOUNDS_INDEXING,
correctness,
"out of bounds constant indexing"
}
/// **What it does:** Checks for usage of indexing or slicing. Arrays are special cased, this lint
/// does report on arrays if we can tell that slicing operations are in bounds and does not
/// lint on constant `usize` indexing on arrays because that is handled by rustc's `const_err` lint.
///
/// **Why is this bad?** Indexing and slicing can panic at runtime and there are
/// safe alternatives.
///
/// **Known problems:** Hopefully none.
///
/// **Example:**
/// ```rust
/// // Vector
/// let x = vec![0; 5];
///
/// // Bad
/// x[2];
/// &x[2..100];
/// &x[2..];
/// &x[..100];
///
/// // Good
/// x.get(2);
/// x.get(2..100);
/// x.get(2..);
/// x.get(..100);
///
/// // Array
/// let y = [0, 1, 2, 3];
///
/// // Bad
/// &y[10..100];
/// &y[10..];
/// &y[..100];
///
/// // Good
/// &y[2..];
/// &y[..2];
/// &y[0..3];
/// y.get(10);
/// y.get(10..100);
/// y.get(10..);
/// y.get(..100);
/// ```
declare_clippy_lint! {
pub INDEXING_SLICING,
pedantic,
"indexing/slicing usage"
}
#[derive(Copy, Clone)]
pub struct IndexingSlicing;
impl LintPass for IndexingSlicing {
fn get_lints(&self) -> LintArray {
lint_array!(INDEXING_SLICING, OUT_OF_BOUNDS_INDEXING)
}
}
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if let ExprIndex(ref array, ref index) = &expr.node {
let ty = cx.tables.expr_ty(array);
if let Some(range) = higher::range(cx, index) {
// Ranged indexes, i.e. &x[n..m], &x[n..], &x[..n] and &x[..]
if let ty::TyArray(_, s) = ty.sty {
let size: u128 = s.assert_usize(cx.tcx).unwrap().into();
// Index is a constant range.
if let Some((start, end)) = to_const_range(cx, range, size) {
if start > size || end > size {
utils::span_lint(
cx,
OUT_OF_BOUNDS_INDEXING,
expr.span,
"range is out of bounds",
);
}
return;
}
}
let help_msg = match (range.start, range.end) {
(None, Some(_)) => "Consider using `.get(..n)`or `.get_mut(..n)` instead",
(Some(_), None) => "Consider using `.get(n..)` or .get_mut(n..)` instead",
(Some(_), Some(_)) => "Consider using `.get(n..m)` or `.get_mut(n..m)` instead",
(None, None) => return, // [..] is ok.
};
utils::span_help_and_lint(
cx,
INDEXING_SLICING,
expr.span,
"slicing may panic.",
help_msg,
);
} else {
// Catchall non-range index, i.e. [n] or [n << m]
if let ty::TyArray(..) = ty.sty {
// Index is a constant uint.
if let Some(..) = constant(cx, cx.tables, index) {
// Let rustc's `const_err` lint handle constant `usize` indexing on arrays.
return;
}
}
utils::span_help_and_lint(
cx,
INDEXING_SLICING,
expr.span,
"indexing may panic.",
"Consider using `.get(n)` or `.get_mut(n)` instead",
);
}
}
}
}
/// Returns an option containing a tuple with the start and end (exclusive) of
/// the range.
fn to_const_range<'a, 'tcx>(
cx: &LateContext<'a, 'tcx>,
range: Range,
array_size: u128,
) -> Option<(u128, u128)> {
let s = range
.start
.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c));
let start = match s {
Some(Some(Constant::Int(x))) => x,
Some(_) => return None,
None => 0,
};
let e = range
.end
.map(|expr| constant(cx, cx.tables, expr).map(|(c, _)| c));
let end = match e {
Some(Some(Constant::Int(x))) => if range.limits == RangeLimits::Closed {
x + 1
} else {
x
},
Some(_) => return None,
None => array_size,
};
Some((start, end))
}

View File

@ -6,7 +6,7 @@
#![feature(stmt_expr_attributes)]
#![feature(range_contains)]
#![feature(macro_vis_matcher)]
#![allow(unknown_lints, indexing_slicing, shadow_reuse, missing_docs_in_private_items)]
#![allow(unknown_lints, shadow_reuse, missing_docs_in_private_items)]
#![recursion_limit = "256"]
#![allow(stable_features)]
#![feature(iterator_find_map)]
@ -99,7 +99,6 @@ pub mod utils;
// begin lints modules, do not remove this comment, its used in `update_lints`
pub mod approx_const;
pub mod arithmetic;
pub mod array_indexing;
pub mod assign_ops;
pub mod attrs;
pub mod bit_mask;
@ -111,6 +110,7 @@ pub mod collapsible_if;
pub mod const_static_lifetime;
pub mod copies;
pub mod cyclomatic_complexity;
pub mod default_trait_access;
pub mod derive;
pub mod doc;
pub mod double_comparison;
@ -138,6 +138,7 @@ pub mod identity_conversion;
pub mod identity_op;
pub mod if_let_redundant_pattern_matching;
pub mod if_not_else;
pub mod indexing_slicing;
pub mod infallible_destructuring_match;
pub mod infinite_iter;
pub mod inherent_impl;
@ -354,7 +355,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
);
reg.register_late_lint_pass(box escape::Pass{too_large_for_stack: conf.too_large_for_stack});
reg.register_early_lint_pass(box misc_early::MiscEarly);
reg.register_late_lint_pass(box array_indexing::ArrayIndexing);
reg.register_late_lint_pass(box panic_unimplemented::Pass);
reg.register_late_lint_pass(box strings::StringLitAsBytes);
reg.register_late_lint_pass(box derive::Derive);
@ -430,12 +430,12 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_late_lint_pass(box neg_cmp_op_on_partial_ord::NoNegCompOpForPartialOrd);
reg.register_late_lint_pass(box unwrap::Pass);
reg.register_late_lint_pass(box duration_subsec::DurationSubsec);
reg.register_late_lint_pass(box default_trait_access::DefaultTraitAccess);
reg.register_late_lint_pass(box indexing_slicing::IndexingSlicing);
reg.register_lint_group("clippy_restriction", vec![
arithmetic::FLOAT_ARITHMETIC,
arithmetic::INTEGER_ARITHMETIC,
array_indexing::INDEXING_SLICING,
assign_ops::ASSIGN_OPS,
else_if_without_else::ELSE_IF_WITHOUT_ELSE,
inherent_impl::MULTIPLE_INHERENT_IMPL,
@ -466,6 +466,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
enum_variants::PUB_ENUM_VARIANT_NAMES,
enum_variants::STUTTER,
if_not_else::IF_NOT_ELSE,
indexing_slicing::INDEXING_SLICING,
infinite_iter::MAYBE_INFINITE_ITER,
items_after_statements::ITEMS_AFTER_STATEMENTS,
matches::SINGLE_MATCH_ELSE,
@ -498,7 +499,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_lint_group("clippy", vec![
approx_const::APPROX_CONSTANT,
array_indexing::OUT_OF_BOUNDS_INDEXING,
assign_ops::ASSIGN_OP_PATTERN,
assign_ops::MISREFACTORED_ASSIGN_OP,
attrs::DEPRECATED_SEMVER,
@ -517,6 +517,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
copies::IF_SAME_THEN_ELSE,
copies::IFS_SAME_COND,
cyclomatic_complexity::CYCLOMATIC_COMPLEXITY,
default_trait_access::DEFAULT_TRAIT_ACCESS,
derive::DERIVE_HASH_XOR_EQ,
double_comparison::DOUBLE_COMPARISONS,
double_parens::DOUBLE_PARENS,
@ -547,6 +548,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
identity_conversion::IDENTITY_CONVERSION,
identity_op::IDENTITY_OP,
if_let_redundant_pattern_matching::IF_LET_REDUNDANT_PATTERN_MATCHING,
indexing_slicing::OUT_OF_BOUNDS_INDEXING,
infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH,
infinite_iter::INFINITE_ITER,
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
@ -715,6 +717,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
block_in_if_condition::BLOCK_IN_IF_CONDITION_STMT,
collapsible_if::COLLAPSIBLE_IF,
const_static_lifetime::CONST_STATIC_LIFETIME,
default_trait_access::DEFAULT_TRAIT_ACCESS,
enum_variants::ENUM_VARIANT_NAMES,
enum_variants::MODULE_INCEPTION,
eq_op::OP_REF,
@ -859,7 +862,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_lint_group("clippy_correctness", vec![
approx_const::APPROX_CONSTANT,
array_indexing::OUT_OF_BOUNDS_INDEXING,
attrs::DEPRECATED_SEMVER,
attrs::USELESS_ATTRIBUTE,
bit_mask::BAD_BIT_MASK,
@ -877,6 +879,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
erasing_op::ERASING_OP,
formatting::POSSIBLE_MISSING_COMMA,
functions::NOT_UNSAFE_PTR_ARG_DEREF,
indexing_slicing::OUT_OF_BOUNDS_INDEXING,
infinite_iter::INFINITE_ITER,
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
invalid_ref::INVALID_REF,
@ -937,6 +940,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
mutex_atomic::MUTEX_INTEGER,
needless_borrow::NEEDLESS_BORROW,
ranges::RANGE_PLUS_ONE,
unwrap::PANICKING_UNWRAP,
unwrap::UNNECESSARY_UNWRAP,
]);
}

View File

@ -59,7 +59,7 @@ impl LintPass for LifetimePass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LifetimePass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(ref decl, _, _, _, ref generics, id) = item.node {
if let ItemFn(ref decl, _, ref generics, id) = item.node {
check_fn_inner(cx, decl, Some(id), generics, item.span);
}
}
@ -101,18 +101,31 @@ fn check_fn_inner<'a, 'tcx>(
}
let mut bounds_lts = Vec::new();
for typ in generics.ty_params() {
let types = generics.params.iter().filter_map(|param| match param.kind {
GenericParamKind::Type { .. } => Some(param),
GenericParamKind::Lifetime { .. } => None,
});
for typ in types {
for bound in &typ.bounds {
if let TraitTyParamBound(ref trait_ref, _) = *bound {
let mut visitor = RefVisitor::new(cx);
walk_param_bound(&mut visitor, bound);
if visitor.lts.iter().any(|lt| matches!(lt, RefLt::Named(_))) {
return;
}
if let GenericBound::Trait(ref trait_ref, _) = *bound {
let params = &trait_ref
.trait_ref
.path
.segments
.last()
.expect("a path must have at least one segment")
.parameters;
.args;
if let Some(ref params) = *params {
for bound in &params.lifetimes {
let lifetimes = params.args.iter().filter_map(|arg| match arg {
GenericArg::Lifetime(lt) => Some(lt),
GenericArg::Type(_) => None,
});
for bound in lifetimes {
if bound.name.name() != "'static" && !bound.is_elided() {
return;
}
@ -225,9 +238,9 @@ fn could_use_elision<'a, 'tcx: 'a>(
fn allowed_lts_from(named_generics: &[GenericParam]) -> HashSet<RefLt> {
let mut allowed_lts = HashSet::new();
for par in named_generics.iter() {
if let GenericParam::Lifetime(ref lt) = *par {
if lt.bounds.is_empty() {
allowed_lts.insert(RefLt::Named(lt.lifetime.name.name()));
if let GenericParamKind::Lifetime { .. } = par.kind {
if par.bounds.is_empty() {
allowed_lts.insert(RefLt::Named(par.name.name()));
}
}
}
@ -290,8 +303,12 @@ impl<'v, 't> RefVisitor<'v, 't> {
}
fn collect_anonymous_lifetimes(&mut self, qpath: &QPath, ty: &Ty) {
if let Some(ref last_path_segment) = last_path_segment(qpath).parameters {
if !last_path_segment.parenthesized && last_path_segment.lifetimes.is_empty() {
if let Some(ref last_path_segment) = last_path_segment(qpath).args {
if !last_path_segment.parenthesized
&& !last_path_segment.args.iter().any(|arg| match arg {
GenericArg::Lifetime(_) => true,
GenericArg::Type(_) => false,
}) {
let hir_id = self.cx.tcx.hir.node_to_hir_id(ty.id);
match self.cx.tables.qpath_def(qpath, hir_id) {
Def::TyAlias(def_id) | Def::Struct(def_id) => {
@ -327,10 +344,12 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> {
TyPath(ref path) => {
self.collect_anonymous_lifetimes(path, ty);
},
TyImplTraitExistential(ref exist_ty, _) => {
for bound in &exist_ty.bounds {
if let RegionTyParamBound(_) = *bound {
self.record(&None);
TyImplTraitExistential(exist_ty_id, _, _) => {
if let ItemExistential(ref exist_ty) = self.cx.tcx.hir.expect_item(exist_ty_id.id).node {
for bound in &exist_ty.bounds {
if let GenericBound::Outlives(_) = *bound {
self.record(&None);
}
}
}
}
@ -370,7 +389,7 @@ fn has_where_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, where_clause: &
let allowed_lts = allowed_lts_from(&pred.bound_generic_params);
// now walk the bounds
for bound in pred.bounds.iter() {
walk_ty_param_bound(&mut visitor, bound);
walk_param_bound(&mut visitor, bound);
}
// and check that all lifetimes are allowed
match visitor.into_vec() {
@ -411,7 +430,7 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
// don't want to spuriously remove them
// `'b` in `'a: 'b` is useless unless used elsewhere in
// a non-lifetime bound
if param.is_type_param() {
if let GenericParamKind::Type { .. } = param.kind {
walk_generic_param(self, param)
}
}
@ -421,9 +440,11 @@ impl<'tcx> Visitor<'tcx> for LifetimeChecker {
}
fn report_extra_lifetimes<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, func: &'tcx FnDecl, generics: &'tcx Generics) {
let hs = generics
.lifetimes()
.map(|lt| (lt.lifetime.name.name(), lt.lifetime.span))
let hs = generics.params.iter()
.filter_map(|par| match par.kind {
GenericParamKind::Lifetime { .. } => Some((par.name.name(), par.span)),
_ => None,
})
.collect();
let mut checker = LifetimeChecker { map: hs };

View File

@ -640,7 +640,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: NodeId) -> NeverLoopResult {
}
},
ExprBlock(ref b, _) => never_loop_block(b, main_loop_id),
ExprAgain(d) => {
ExprContinue(d) => {
let id = d.target_id
.expect("target id can only be missing in the presence of compilation errors");
if id == main_loop_id {

View File

@ -36,7 +36,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
ExprClosure(_, ref decl, closure_eid, _, _) => {
let body = cx.tcx.hir.body(closure_eid);
let closure_expr = remove_blocks(&body.value);
let ty = cx.tables.pat_ty(&body.arguments[0].pat);
if_chain! {
// nothing special in the argument, besides reference bindings
// (e.g. .map(|&x| x) )
@ -45,6 +44,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
// the method is being called on a known type (option or iterator)
if let Some(type_name) = get_type_name(cx, expr, &args[0]);
then {
// We know that body.arguments is not empty at this point
let ty = cx.tables.pat_ty(&body.arguments[0].pat);
// look for derefs, for .map(|x| *x)
if only_derefs(cx, &*closure_expr, arg_ident) &&
// .cloned() only removes one level of indirection, don't lint on more
@ -103,7 +104,7 @@ fn expr_eq_name(expr: &Expr, id: ast::Name) -> bool {
let arg_segment = [
PathSegment {
name: id,
parameters: None,
args: None,
infer_types: true,
},
];

View File

@ -7,7 +7,7 @@ use std::fmt;
use std::iter;
use syntax::ast;
use syntax::codemap::{Span, BytePos};
use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self,
use crate::utils::{get_arg_name, get_trait_def_id, implements_trait, in_external_macro, in_macro, is_copy, is_expn_of, is_self,
is_self_ty, iter_input_pats, last_path_segment, match_def_path, match_path, match_qpath, match_trait_method,
match_type, method_chain_args, match_var, return_ty, remove_blocks, same_tys, single_segment_path, snippet,
span_lint, span_lint_and_sugg, span_lint_and_then, span_note_and_lint, walk_ptrs_ty, walk_ptrs_ty_depth};
@ -336,7 +336,7 @@ declare_clippy_lint! {
///
/// **Known problems:** If the function has side-effects, not calling it will
/// change the semantic of the program, but you shouldn't rely on that anyway.
///
///
/// **Example:**
/// ```rust
/// foo.expect(&format("Err {}: {}", err_code, err_msg))
@ -1020,7 +1020,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
}
}
};
snippet(cx, a.span, "..").into_owned()
}
@ -1077,7 +1077,7 @@ fn lint_expect_fun_call(cx: &LateContext, expr: &hir::Expr, method_span: Span, n
}
let sugg: Cow<_> = snippet(cx, arg.span, "..");
span_lint_and_sugg(
cx,
EXPECT_FUN_CALL,
@ -2091,26 +2091,35 @@ impl SelfKind {
fn is_as_ref_or_mut_trait(ty: &hir::Ty, self_ty: &hir::Ty, generics: &hir::Generics, name: &[&str]) -> bool {
single_segment_ty(ty).map_or(false, |seg| {
generics.ty_params().any(|param| {
param.name == seg.name && param.bounds.iter().any(|bound| {
if let hir::TyParamBound::TraitTyParamBound(ref ptr, ..) = *bound {
let path = &ptr.trait_ref.path;
match_path(path, name) && path.segments.last().map_or(false, |s| {
if let Some(ref params) = s.parameters {
if params.parenthesized {
false
generics.params.iter().any(|param| match param.kind {
hir::GenericParamKind::Type { .. } => {
param.name.name() == seg.name && param.bounds.iter().any(|bound| {
if let hir::GenericBound::Trait(ref ptr, ..) = *bound {
let path = &ptr.trait_ref.path;
match_path(path, name) && path.segments.last().map_or(false, |s| {
if let Some(ref params) = s.args {
if params.parenthesized {
false
} else {
// FIXME(flip1995): messy, improve if there is a better option
// in the compiler
let types: Vec<_> = params.args.iter().filter_map(|arg| match arg {
hir::GenericArg::Type(ty) => Some(ty),
_ => None,
}).collect();
types.len() == 1
&& (is_self_ty(&types[0]) || is_ty(&*types[0], self_ty))
}
} else {
params.types.len() == 1
&& (is_self_ty(&params.types[0]) || is_ty(&*params.types[0], self_ty))
false
}
} else {
false
}
})
} else {
false
}
})
})
} else {
false
}
})
},
_ => false,
})
})
}

View File

@ -558,7 +558,7 @@ fn in_attributes_expansion(expr: &Expr) -> bool {
.ctxt()
.outer()
.expn_info()
.map_or(false, |info| matches!(info.callee.format, ExpnFormat::MacroAttribute(_)))
.map_or(false, |info| matches!(info.format, ExpnFormat::MacroAttribute(_)))
}
/// Test whether `def` is a variable defined outside a macro.

View File

@ -189,13 +189,13 @@ impl LintPass for MiscEarly {
impl EarlyLintPass for MiscEarly {
fn check_generics(&mut self, cx: &EarlyContext, gen: &Generics) {
for param in &gen.params {
if let GenericParam::Type(ref ty) = *param {
let name = ty.ident.name.as_str();
if let GenericParamKind::Type { .. } = param.kind {
let name = param.ident.name.as_str();
if constants::BUILTIN_TYPES.contains(&&*name) {
span_lint(
cx,
BUILTIN_TYPE_SHADOW,
ty.ident.span,
param.ident.span,
&format!("This generic shadows the built-in type `{}`", name),
);
}
@ -296,7 +296,7 @@ impl EarlyLintPass for MiscEarly {
}
match expr.node {
ExprKind::Call(ref paren, _) => if let ExprKind::Paren(ref closure) = paren.node {
if let ExprKind::Closure(_, _, ref decl, ref block, _) = closure.node {
if let ExprKind::Closure(_, _, _, ref decl, ref block, _) = closure.node {
span_lint_and_then(
cx,
REDUNDANT_CLOSURE_CALL,
@ -327,7 +327,7 @@ impl EarlyLintPass for MiscEarly {
if_chain! {
if let StmtKind::Local(ref local) = w[0].node;
if let Option::Some(ref t) = local.init;
if let ExprKind::Closure(_, _, _, _, _) = t.node;
if let ExprKind::Closure(..) = t.node;
if let PatKind::Ident(_, ident, _) = local.pat.node;
if let StmtKind::Semi(ref second) = w[1].node;
if let ExprKind::Assign(_, ref call) = second.node;

View File

@ -143,6 +143,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
hir::ItemGlobalAsm(..) => "an assembly blob",
hir::ItemTy(..) => "a type alias",
hir::ItemUnion(..) => "a union",
hir::ItemExistential(..) => "an existential type",
hir::ItemExternCrate(..) |
hir::ItemForeignMod(..) |
hir::ItemImpl(..) |

View File

@ -72,8 +72,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
}
match kind {
FnKind::ItemFn(.., abi, _, attrs) => {
if abi != Abi::Rust {
FnKind::ItemFn(.., header, _, attrs) => {
if header.abi != Abi::Rust {
return;
}
for a in attrs {
@ -218,8 +218,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue {
if let TyPath(QPath::Resolved(_, ref path)) = input.node;
if let Some(elem_ty) = path.segments.iter()
.find(|seg| seg.name == "Vec")
.and_then(|ps| ps.parameters.as_ref())
.map(|params| &params.types[0]);
.and_then(|ps| ps.args.as_ref())
.map(|params| params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
}).unwrap());
then {
let slice_ty = format!("&[{}]", snippet(cx, elem_ty.span, "_"));
db.span_suggestion(input.span,

View File

@ -1,7 +1,7 @@
use rustc::hir::*;
use rustc::lint::*;
use crate::utils::{self, paths};
use crate::utils::{self, paths, span_lint, in_external_macro};
/// **What it does:**
/// Checks for the usage of negated comparision operators on types which only implement
@ -53,6 +53,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd {
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
if_chain! {
if !in_external_macro(cx, expr.span);
if let Expr_::ExprUnary(UnOp::UnNot, ref inner) = expr.node;
if let Expr_::ExprBinary(ref op, ref left, _) = inner.node;
if let BinOp_::BiLe | BinOp_::BiGe | BinOp_::BiLt | BinOp_::BiGt = op.node;
@ -78,7 +79,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NoNegCompOpForPartialOrd {
};
if implements_partial_ord && !implements_ord {
cx.span_lint(
span_lint(
cx,
NEG_CMP_OP_ON_PARTIAL_ORD,
expr.span,
"The use of negated comparision operators on partially orded \

View File

@ -99,11 +99,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
let name = impl_item.name;
let id = impl_item.id;
if sig.constness == hir::Constness::Const {
if sig.header.constness == hir::Constness::Const {
// can't be implemented by default
return;
}
if impl_item.generics.params.iter().any(|gen| gen.is_type_param()) {
if impl_item.generics.params.iter().any(|gen| match gen.kind {
hir::GenericParamKind::Type { .. } => true,
_ => false
}) {
// when the result of `new()` depends on a type parameter we should not require
// an
// impl of `Default`

View File

@ -312,7 +312,7 @@ impl<'a, 'tcx> Visitor<'tcx> for SimilarNamesLocalVisitor<'a, 'tcx> {
impl EarlyLintPass for NonExpressiveNames {
fn check_item(&mut self, cx: &EarlyContext, item: &Item) {
if let ItemKind::Fn(ref decl, _, _, _, _, ref blk) = item.node {
if let ItemKind::Fn(ref decl, _, _, ref blk) = item.node {
do_check(self, cx, &item.attrs, decl, blk);
}
}

View File

@ -103,7 +103,7 @@ impl LintPass for PointerPass {
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PointerPass {
fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
if let ItemFn(ref decl, _, _, _, _, body_id) = item.node {
if let ItemFn(ref decl, _, _, body_id) = item.node {
check_fn(cx, decl, item.id, Some(body_id));
}
}
@ -160,10 +160,15 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<
let mut ty_snippet = None;
if_chain! {
if let TyPath(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).node;
if let Some(&PathSegment{parameters: Some(ref parameters), ..}) = path.segments.last();
if parameters.types.len() == 1;
if let Some(&PathSegment{args: Some(ref parameters), ..}) = path.segments.last();
then {
ty_snippet = snippet_opt(cx, parameters.types[0].span);
let types: Vec<_> = parameters.args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
_ => None,
}).collect();
if types.len() == 1 {
ty_snippet = snippet_opt(cx, types[0].span);
}
}
};
if let Some(spans) = get_spans(cx, opt_body_id, idx, &[("clone", ".to_owned()")]) {
@ -218,9 +223,12 @@ fn check_fn(cx: &LateContext, decl: &FnDecl, fn_id: NodeId, opt_body_id: Option<
if let TyPath(ref path) = ty.node;
if let QPath::Resolved(None, ref pp) = *path;
if let [ref bx] = *pp.segments;
if let Some(ref params) = bx.parameters;
if let Some(ref params) = bx.args;
if !params.parenthesized;
if let [ref inner] = *params.types;
if let Some(inner) = params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
});
then {
let replacement = snippet_opt(cx, inner.span);
if let Some(r) = replacement {

View File

@ -455,9 +455,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
fn get_type_snippet(cx: &LateContext, path: &QPath, to_ref_ty: Ty) -> String {
let seg = last_path_segment(path);
if_chain! {
if let Some(ref params) = seg.parameters;
if let Some(ref params) = seg.args;
if !params.parenthesized;
if let Some(to_ty) = params.types.get(1);
if let Some(to_ty) = params.args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
}).nth(1);
if let TyRptr(_, ref to_ty) = to_ty.node;
then {
return snippet(cx, to_ty.ty.span, &to_ref_ty.to_string()).to_string();

View File

@ -84,8 +84,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TriviallyCopyPassByRef {
}
match kind {
FnKind::ItemFn(.., abi, _, attrs) => {
if abi != Abi::Rust {
FnKind::ItemFn(.., header, _, attrs) => {
if header.abi != Abi::Rust {
return;
}
for a in attrs {

View File

@ -180,9 +180,12 @@ fn check_fn_decl(cx: &LateContext, decl: &FnDecl) {
fn match_type_parameter(cx: &LateContext, qpath: &QPath, path: &[&str]) -> bool {
let last = last_path_segment(qpath);
if_chain! {
if let Some(ref params) = last.parameters;
if let Some(ref params) = last.args;
if !params.parenthesized;
if let Some(ty) = params.types.get(0);
if let Some(ty) = params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
});
if let TyPath(ref qpath) = ty.node;
if let Some(did) = opt_def_id(cx.tables.qpath_def(qpath, cx.tcx.hir.node_to_hir_id(ty.id)));
if match_def_path(cx.tcx, did, path);
@ -244,24 +247,35 @@ fn check_ty(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool) {
QPath::Resolved(Some(ref ty), ref p) => {
check_ty(cx, ty, is_local);
for ty in p.segments.iter().flat_map(|seg| {
seg.parameters
seg.args
.as_ref()
.map_or_else(|| [].iter(), |params| params.types.iter())
.map_or_else(|| [].iter(), |params| params.args.iter())
.filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
})
}) {
check_ty(cx, ty, is_local);
}
},
QPath::Resolved(None, ref p) => for ty in p.segments.iter().flat_map(|seg| {
seg.parameters
seg.args
.as_ref()
.map_or_else(|| [].iter(), |params| params.types.iter())
.map_or_else(|| [].iter(), |params| params.args.iter())
.filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
})
}) {
check_ty(cx, ty, is_local);
},
QPath::TypeRelative(ref ty, ref seg) => {
check_ty(cx, ty, is_local);
if let Some(ref params) = seg.parameters {
for ty in params.types.iter() {
if let Some(ref params) = seg.args {
for ty in params.args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
}) {
check_ty(cx, ty, is_local);
}
}
@ -288,9 +302,12 @@ fn check_ty_rptr(cx: &LateContext, ast_ty: &hir::Ty, is_local: bool, lt: &Lifeti
if Some(def_id) == cx.tcx.lang_items().owned_box();
if let QPath::Resolved(None, ref path) = *qpath;
if let [ref bx] = *path.segments;
if let Some(ref params) = bx.parameters;
if let Some(ref params) = bx.args;
if !params.parenthesized;
if let [ref inner] = *params.types;
if let Some(inner) = params.args.iter().find_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
});
then {
if is_any_trait(inner) {
// Ignore `Box<Any>` types, see #1884 for details.
@ -1208,7 +1225,10 @@ impl<'tcx> Visitor<'tcx> for TypeComplexityVisitor {
TyTraitObject(ref param_bounds, _) => {
let has_lifetime_parameters = param_bounds
.iter()
.any(|bound| bound.bound_generic_params.iter().any(|gen| gen.is_lifetime_param()));
.any(|bound| bound.bound_generic_params.iter().any(|gen| match gen.kind {
GenericParamKind::Lifetime { .. } => true,
_ => false,
}));
if has_lifetime_parameters {
// complex trait bounds like A<'a, 'b>
(50 * self.nest, 1)
@ -1859,7 +1879,11 @@ impl<'tcx> ImplicitHasherType<'tcx> {
/// Checks that `ty` is a target type without a BuildHasher.
fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option<Self> {
if let TyPath(QPath::Resolved(None, ref path)) = hir_ty.node {
let params = &path.segments.last().as_ref()?.parameters.as_ref()?.types;
let params: Vec<_> = path.segments.last().as_ref()?.args.as_ref()?
.args.iter().filter_map(|arg| match arg {
GenericArg::Type(ty) => Some(ty),
GenericArg::Lifetime(_) => None,
}).collect();
let params_len = params.len();
let ty = hir_ty_to_ty(cx.tcx, hir_ty);

View File

@ -69,7 +69,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedLabel {
impl<'a, 'tcx: 'a> Visitor<'tcx> for UnusedLabelVisitor<'a, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr) {
match expr.node {
hir::ExprBreak(destination, _) | hir::ExprAgain(destination) => if let Some(label) = destination.label {
hir::ExprBreak(destination, _) | hir::ExprContinue(destination) => if let Some(label) = destination.label {
self.labels.remove(&label.name.as_str());
},
hir::ExprLoop(_, Some(label), _) | hir::ExprWhile(_, _, Some(label)) => {

View File

@ -32,6 +32,27 @@ declare_clippy_lint! {
"checks for calls of unwrap[_err]() that cannot fail"
}
/// **What it does:** Checks for calls of `unwrap[_err]()` that will always fail.
///
/// **Why is this bad?** If panicking is desired, an explicit `panic!()` should be used.
///
/// **Known problems:** This lint only checks `if` conditions not assignments.
/// So something like `let x: Option<()> = None; x.unwrap();` will not be recognized.
///
/// **Example:**
/// ```rust
/// if option.is_none() {
/// do_something_with(option.unwrap())
/// }
/// ```
///
/// This code will always panic. The if condition should probably be inverted.
declare_clippy_lint! {
pub PANICKING_UNWRAP,
nursery,
"checks for calls of unwrap[_err]() that will always fail"
}
pub struct Pass;
/// Visitor that keeps track of which variables are unwrappable.
@ -124,17 +145,28 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
if ["unwrap", "unwrap_err"].contains(&&*method_name.name.as_str());
let call_to_unwrap = method_name.name == "unwrap";
if let Some(unwrappable) = self.unwrappables.iter()
.find(|u| u.ident.def == path.def && call_to_unwrap == u.safe_to_unwrap);
.find(|u| u.ident.def == path.def);
then {
span_lint_and_then(
self.cx,
UNNECESSARY_UNWRAP,
expr.span,
&format!("You checked before that `{}()` cannot fail. \
Instead of checking and unwrapping, it's better to use `if let` or `match`.",
method_name.name),
|db| { db.span_label(unwrappable.check.span, "the check is happening here"); },
);
if call_to_unwrap == unwrappable.safe_to_unwrap {
span_lint_and_then(
self.cx,
UNNECESSARY_UNWRAP,
expr.span,
&format!("You checked before that `{}()` cannot fail. \
Instead of checking and unwrapping, it's better to use `if let` or `match`.",
method_name.name),
|db| { db.span_label(unwrappable.check.span, "the check is happening here"); },
);
} else {
span_lint_and_then(
self.cx,
PANICKING_UNWRAP,
expr.span,
&format!("This call to `{}()` will always panic.",
method_name.name),
|db| { db.span_label(unwrappable.check.span, "because of this check"); },
);
}
}
}
walk_expr(self, expr);
@ -148,7 +180,7 @@ impl<'a, 'tcx: 'a> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> {
impl<'a> LintPass for Pass {
fn get_lints(&self) -> LintArray {
lint_array!(UNNECESSARY_UNWRAP)
lint_array!(PANICKING_UNWRAP, UNNECESSARY_UNWRAP)
}
}

View File

@ -58,9 +58,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf {
if let ItemImpl(.., ref item_type, ref refs) = item.node;
if let Ty_::TyPath(QPath::Resolved(_, ref item_path)) = item_type.node;
then {
let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).parameters;
let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args;
let should_check = if let Some(ref params) = *parameters {
!params.parenthesized && params.lifetimes.len() == 0
!params.parenthesized && !params.args.iter().any(|arg| match arg {
GenericArg::Lifetime(_) => true,
GenericArg::Type(_) => false,
})
} else {
true
};

View File

@ -432,7 +432,7 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor {
}
// FIXME: implement label printing
},
Expr_::ExprAgain(ref _destination) => {
Expr_::ExprContinue(ref _destination) => {
let destination_pat = self.next("destination");
println!("Again(ref {}) = {};", destination_pat, current);
// FIXME: implement label printing

View File

@ -76,7 +76,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
match (&left.node, &right.node) {
(&ExprAddrOf(l_mut, ref le), &ExprAddrOf(r_mut, ref re)) => l_mut == r_mut && self.eq_expr(le, re),
(&ExprAgain(li), &ExprAgain(ri)) => {
(&ExprContinue(li), &ExprContinue(ri)) => {
both(&li.label, &ri.label, |l, r| l.name.as_str() == r.name.as_str())
},
(&ExprAssign(ref ll, ref lr), &ExprAssign(ref rl, ref rr)) => self.eq_expr(ll, rl) && self.eq_expr(lr, rr),
@ -152,6 +152,14 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
left.ident.name == right.ident.name && self.eq_expr(&left.expr, &right.expr)
}
fn eq_generic_arg(&mut self, left: &GenericArg, right: &GenericArg) -> bool {
match (left, right) {
(GenericArg::Lifetime(l_lt), GenericArg::Lifetime(r_lt)) => self.eq_lifetime(l_lt, r_lt),
(GenericArg::Type(l_ty), GenericArg::Type(r_ty)) => self.eq_ty(l_ty, r_ty),
_ => false,
}
}
fn eq_lifetime(&mut self, left: &Lifetime, right: &Lifetime) -> bool {
left.name == right.name
}
@ -201,10 +209,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
&& over(&left.segments, &right.segments, |l, r| self.eq_path_segment(l, r))
}
fn eq_path_parameters(&mut self, left: &PathParameters, right: &PathParameters) -> bool {
fn eq_path_parameters(&mut self, left: &GenericArgs, right: &GenericArgs) -> bool {
if !(left.parenthesized || right.parenthesized) {
over(&left.lifetimes, &right.lifetimes, |l, r| self.eq_lifetime(l, r))
&& over(&left.types, &right.types, |l, r| self.eq_ty(l, r))
over(&left.args, &right.args, |l, r| self.eq_generic_arg(l, r)) // FIXME(flip1995): may not work
&& over(&left.bindings, &right.bindings, |l, r| self.eq_type_binding(l, r))
} else if left.parenthesized && right.parenthesized {
over(left.inputs(), right.inputs(), |l, r| self.eq_ty(l, r))
@ -224,7 +231,7 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> {
if left.name.as_str() != right.name.as_str() {
return false;
}
match (&left.parameters, &right.parameters) {
match (&left.args, &right.args) {
(&None, &None) => true,
(&Some(ref l), &Some(ref r)) => self.eq_path_parameters(l, r),
_ => false,
@ -345,8 +352,8 @@ impl<'a, 'tcx: 'a> SpanlessHash<'a, 'tcx> {
m.hash(&mut self.s);
self.hash_expr(e);
},
ExprAgain(i) => {
let c: fn(_) -> _ = ExprAgain;
ExprContinue(i) => {
let c: fn(_) -> _ = ExprContinue;
c.hash(&mut self.s);
if let Some(i) = i.label {
self.hash_name(i.name);

View File

@ -300,7 +300,7 @@ fn print_expr(cx: &LateContext, expr: &hir::Expr, indent: usize) {
print_expr(cx, e, indent + 1);
}
},
hir::ExprAgain(_) => println!("{}Again", ind),
hir::ExprContinue(_) => println!("{}Again", ind),
hir::ExprRet(ref e) => {
println!("{}Ret", ind);
if let Some(ref e) = *e {
@ -380,6 +380,9 @@ fn print_item(cx: &LateContext, item: &hir::Item) {
hir::ItemTy(..) => {
println!("type alias for {:?}", cx.tcx.type_of(did));
},
hir::ItemExistential(..) => {
println!("existential type with real type {:?}", cx.tcx.type_of(did));
},
hir::ItemEnum(..) => {
println!("enum definition of type {:?}", cx.tcx.type_of(did));
},

View File

@ -57,7 +57,7 @@ pub fn in_constant(cx: &LateContext, id: NodeId) -> bool {
/// Returns true if this `expn_info` was expanded by any macro.
pub fn in_macro(span: Span) -> bool {
span.ctxt().outer().expn_info().map_or(false, |info| {
match info.callee.format {
match info.format {
// don't treat range expressions desugared to structs as "in_macro"
ExpnFormat::CompilerDesugaring(kind) => kind != CompilerDesugaringKind::DotFill,
_ => true,
@ -68,7 +68,7 @@ pub fn in_macro(span: Span) -> bool {
/// Returns true if `expn_info` was expanded by range expressions.
pub fn is_range_expression(span: Span) -> bool {
span.ctxt().outer().expn_info().map_or(false, |info| {
match info.callee.format {
match info.format {
ExpnFormat::CompilerDesugaring(CompilerDesugaringKind::DotFill) => true,
_ => false,
}
@ -84,12 +84,12 @@ pub fn in_external_macro<'a, T: LintContext<'a>>(cx: &T, span: Span) -> bool {
/// this after other checks have already happened.
fn in_macro_ext<'a, T: LintContext<'a>>(cx: &T, info: &ExpnInfo) -> bool {
// no ExpnInfo = no macro
if let ExpnFormat::MacroAttribute(..) = info.callee.format {
if let ExpnFormat::MacroAttribute(..) = info.format {
// these are all plugins
return true;
}
// no span for the callee = external macro
info.callee.span.map_or(true, |span| {
info.def_site.map_or(true, |span| {
// no snippet = external macro or compiler-builtin expansion
cx.sess()
.codemap()
@ -524,7 +524,7 @@ pub fn get_enclosing_block<'a, 'tcx: 'a>(cx: &LateContext<'a, 'tcx>, node: NodeI
match node {
Node::NodeBlock(block) => Some(block),
Node::NodeItem(&Item {
node: ItemFn(_, _, _, _, _, eid),
node: ItemFn(_, _, _, eid),
..
}) | Node::NodeImplItem(&ImplItem {
node: ImplItemKind::Method(_, eid),
@ -768,7 +768,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option<Span> {
let span_name_span = span.ctxt()
.outer()
.expn_info()
.map(|ei| (ei.callee.name(), ei.call_site));
.map(|ei| (ei.format.name(), ei.call_site));
match span_name_span {
Some((mac_name, new_span)) if mac_name == name => return Some(new_span),
@ -791,7 +791,7 @@ pub fn is_direct_expn_of(span: Span, name: &str) -> Option<Span> {
let span_name_span = span.ctxt()
.outer()
.expn_info()
.map(|ei| (ei.callee.name(), ei.call_site));
.map(|ei| (ei.format.name(), ei.call_site));
match span_name_span {
Some((mac_name, new_span)) if mac_name == name => Some(new_span),
@ -981,6 +981,7 @@ pub fn opt_def_id(def: Def) -> Option<DefId> {
Def::Const(id) |
Def::AssociatedConst(id) |
Def::Macro(id, ..) |
Def::Existential(id) |
Def::GlobalAsm(id) => Some(id),
Def::Upvar(..) | Def::Local(_) | Def::Label(..) | Def::PrimTy(..) | Def::SelfTy(..) | Def::Err => None,
@ -1128,3 +1129,17 @@ pub fn without_block_comments(lines: Vec<&str>) -> Vec<&str> {
without
}
pub fn any_parent_is_automatically_derived(tcx: TyCtxt, node: NodeId) -> bool {
let map = &tcx.hir;
let mut prev_enclosing_node = None;
let mut enclosing_node = node;
while Some(enclosing_node) != prev_enclosing_node {
if is_automatically_derived(map.attrs(enclosing_node)) {
return true;
}
prev_enclosing_node = Some(enclosing_node);
enclosing_node = map.get_parent(enclosing_node);
}
false
}

View File

@ -24,6 +24,7 @@ pub const C_VOID: [&str; 4] = ["std", "os", "raw", "c_void"];
pub const C_VOID_LIBC: [&str; 2] = ["libc", "c_void"];
pub const DEBUG_FMT_METHOD: [&str; 4] = ["core", "fmt", "Debug", "fmt"];
pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
pub const DISPLAY_FMT_METHOD: [&str; 4] = ["core", "fmt", "Display", "fmt"];
pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
pub const DROP: [&str; 3] = ["core", "mem", "drop"];

View File

@ -52,7 +52,7 @@ impl<'a> Sugg<'a> {
hir::ExprIf(..) |
hir::ExprUnary(..) |
hir::ExprMatch(..) => Sugg::MaybeParen(snippet),
hir::ExprAgain(..) |
hir::ExprContinue(..) |
hir::ExprYield(..) |
hir::ExprArray(..) |
hir::ExprBlock(..) |
@ -100,6 +100,7 @@ impl<'a> Sugg<'a> {
ast::ExprKind::ObsoleteInPlace(..) |
ast::ExprKind::Unary(..) |
ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
ast::ExprKind::Async(..) |
ast::ExprKind::Block(..) |
ast::ExprKind::Break(..) |
ast::ExprKind::Call(..) |

View File

@ -1,7 +1,7 @@
rustc 1.28.0-nightly (86a8f1a63 2018-06-17)
rustc 1.28.0-nightly (01cc982e9 2018-06-24)
binary: rustc
commit-hash: 86a8f1a6374dd558ebdafe061e61720a73ae732c
commit-date: 2018-06-17
commit-hash: 01cc982e936120acb0424e41de14e42ba2d88c6f
commit-date: 2018-06-24
host: x86_64-unknown-linux-gnu
release: 1.28.0-nightly
LLVM version: 6.0

View File

@ -13,7 +13,7 @@ extern crate rustc_plugin;
extern crate syntax;
use rustc_driver::{driver::CompileController, Compilation};
use std::process::Command;
use std::process::{exit, Command};
#[allow(print_stdout)]
fn show_version() {
@ -133,5 +133,10 @@ pub fn main() {
}
controller.compilation_done.stop = Compilation::Stop;
rustc_driver::run_compiler(&args, Box::new(controller), None, None);
if rustc_driver::run_compiler(&args, Box::new(controller), None, None)
.0
.is_err()
{
exit(101);
}
}

View File

@ -0,0 +1,14 @@
pub trait FooMap {
fn map<B, F: Fn() -> B>(&self, f: F) -> B;
}
impl FooMap for bool {
fn map<B, F: Fn() -> B>(&self, f: F) -> B {
f()
}
}
fn main() {
let a = true;
a.map(|| false);
}

View File

@ -1,45 +0,0 @@
#![feature(plugin)]
#![warn(indexing_slicing)]
#![warn(out_of_bounds_indexing)]
#![allow(no_effect, unnecessary_operation)]
fn main() {
let x = [1,2,3,4];
x[0];
x[3];
x[4];
x[1 << 3];
&x[1..5];
&x[0..3];
&x[0..=4];
&x[..=4];
&x[..];
&x[1..];
&x[4..];
&x[5..];
&x[..4];
&x[..5];
let y = &x;
y[0];
&y[1..2];
&y[..];
&y[0..=4];
&y[..=4];
let empty: [i8; 0] = [];
empty[0];
&empty[1..5];
&empty[0..=4];
&empty[..=4];
&empty[..];
&empty[0..];
&empty[0..0];
&empty[0..=0];
&empty[..=0];
&empty[..0];
&empty[1..];
&empty[..4];
}

View File

@ -1,120 +0,0 @@
error: const index is out of bounds
--> $DIR/array_indexing.rs:12:5
|
12 | x[4];
| ^^^^
|
= note: `-D out-of-bounds-indexing` implied by `-D warnings`
error: const index is out of bounds
--> $DIR/array_indexing.rs:13:5
|
13 | x[1 << 3];
| ^^^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:14:6
|
14 | &x[1..5];
| ^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:16:6
|
16 | &x[0..=4];
| ^^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:17:6
|
17 | &x[..=4];
| ^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:21:6
|
21 | &x[5..];
| ^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:23:6
|
23 | &x[..5];
| ^^^^^^
error: indexing may panic
--> $DIR/array_indexing.rs:26:5
|
26 | y[0];
| ^^^^
|
= note: `-D indexing-slicing` implied by `-D warnings`
error: slicing may panic
--> $DIR/array_indexing.rs:27:6
|
27 | &y[1..2];
| ^^^^^^^
error: slicing may panic
--> $DIR/array_indexing.rs:29:6
|
29 | &y[0..=4];
| ^^^^^^^^
error: slicing may panic
--> $DIR/array_indexing.rs:30:6
|
30 | &y[..=4];
| ^^^^^^^
error: const index is out of bounds
--> $DIR/array_indexing.rs:33:5
|
33 | empty[0];
| ^^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:34:6
|
34 | &empty[1..5];
| ^^^^^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:35:6
|
35 | &empty[0..=4];
| ^^^^^^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:36:6
|
36 | &empty[..=4];
| ^^^^^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:40:6
|
40 | &empty[0..=0];
| ^^^^^^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:41:6
|
41 | &empty[..=0];
| ^^^^^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:43:6
|
43 | &empty[1..];
| ^^^^^^^^^^
error: range is out of bounds
--> $DIR/array_indexing.rs:44:6
|
44 | &empty[..4];
| ^^^^^^^^^^
error: aborting due to 19 previous errors

View File

@ -1,32 +1,41 @@
#![deny(unnecessary_unwrap)]
#![deny(panicking_unwrap, unnecessary_unwrap)]
#![allow(if_same_then_else)]
fn main() {
let x = Some(());
if x.is_some() {
x.unwrap();
x.unwrap(); // unnecessary
} else {
x.unwrap(); // will panic
}
if x.is_none() {
// nothing to do here
x.unwrap(); // will panic
} else {
x.unwrap();
x.unwrap(); // unnecessary
}
let mut x: Result<(), ()> = Ok(());
if x.is_ok() {
x.unwrap();
x.unwrap(); // unnecessary
x.unwrap_err(); // will panic
} else {
x.unwrap_err();
x.unwrap(); // will panic
x.unwrap_err(); // unnecessary
}
if x.is_err() {
x.unwrap_err();
x.unwrap(); // will panic
x.unwrap_err(); // unnecessary
} else {
x.unwrap();
x.unwrap(); // unnecessary
x.unwrap_err(); // will panic
}
if x.is_ok() {
x = Err(());
x.unwrap();
x.unwrap(); // not unnecessary because of mutation of x
// it will always panic but the lint is not smart enoguh to see this (it only checks if conditions).
} else {
x = Ok(());
x.unwrap_err();
x.unwrap_err(); // not unnecessary because of mutation of x
// it will always panic but the lint is not smart enoguh to see this (it only checks if conditions).
}
}
@ -34,34 +43,49 @@ fn test_complex_conditions() {
let x: Result<(), ()> = Ok(());
let y: Result<(), ()> = Ok(());
if x.is_ok() && y.is_err() {
x.unwrap();
y.unwrap_err();
x.unwrap(); // unnecessary
x.unwrap_err(); // will panic
y.unwrap(); // will panic
y.unwrap_err(); // unnecessary
} else {
// not clear whether unwrappable:
// not statically determinable whether any of the following will always succeed or always fail:
x.unwrap();
x.unwrap_err();
y.unwrap();
y.unwrap_err();
}
if x.is_ok() || y.is_ok() {
// not clear whether unwrappable:
// not statically determinable whether any of the following will always succeed or always fail:
x.unwrap();
y.unwrap();
} else {
x.unwrap_err();
y.unwrap_err();
x.unwrap(); // will panic
x.unwrap_err(); // unnecessary
y.unwrap(); // will panic
y.unwrap_err(); // unnecessary
}
let z: Result<(), ()> = Ok(());
if x.is_ok() && !(y.is_ok() || z.is_err()) {
x.unwrap();
y.unwrap_err();
z.unwrap();
x.unwrap(); // unnecessary
x.unwrap_err(); // will panic
y.unwrap(); // will panic
y.unwrap_err(); // unnecessary
z.unwrap(); // unnecessary
z.unwrap_err(); // will panic
}
if x.is_ok() || !(y.is_ok() && z.is_err()) {
// not clear what's unwrappable
} else {
x.unwrap_err();
// not statically determinable whether any of the following will always succeed or always fail:
x.unwrap();
y.unwrap();
z.unwrap_err();
z.unwrap();
} else {
x.unwrap(); // will panic
x.unwrap_err(); // unnecessary
y.unwrap(); // unnecessary
y.unwrap_err(); // will panic
z.unwrap(); // will panic
z.unwrap_err(); // unnecessary
}
}
@ -69,7 +93,9 @@ fn test_nested() {
fn nested() {
let x = Some(());
if x.is_some() {
x.unwrap();
x.unwrap(); // unnecessary
} else {
x.unwrap(); // will panic
}
}
}

View File

@ -1,155 +1,313 @@
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:6:9
--> $DIR/checked_unwrap.rs:7:9
|
5 | if x.is_some() {
6 | if x.is_some() {
| ----------- the check is happening here
6 | x.unwrap();
7 | x.unwrap(); // unnecessary
| ^^^^^^^^^^
|
note: lint level defined here
--> $DIR/checked_unwrap.rs:1:27
|
1 | #![deny(panicking_unwrap, unnecessary_unwrap)]
| ^^^^^^^^^^^^^^^^^^
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:9:9
|
6 | if x.is_some() {
| ----------- because of this check
...
9 | x.unwrap(); // will panic
| ^^^^^^^^^^
|
note: lint level defined here
--> $DIR/checked_unwrap.rs:1:9
|
1 | #![deny(unnecessary_unwrap)]
| ^^^^^^^^^^^^^^^^^^
1 | #![deny(panicking_unwrap, unnecessary_unwrap)]
| ^^^^^^^^^^^^^^^^
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:12:9
|
11 | if x.is_none() {
| ----------- because of this check
12 | x.unwrap(); // will panic
| ^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:11:9
--> $DIR/checked_unwrap.rs:14:9
|
8 | if x.is_none() {
11 | if x.is_none() {
| ----------- the check is happening here
...
11 | x.unwrap();
14 | x.unwrap(); // unnecessary
| ^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:15:9
--> $DIR/checked_unwrap.rs:18:9
|
14 | if x.is_ok() {
17 | if x.is_ok() {
| --------- the check is happening here
15 | x.unwrap();
18 | x.unwrap(); // unnecessary
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:17:9
error: This call to `unwrap_err()` will always panic.
--> $DIR/checked_unwrap.rs:19:9
|
14 | if x.is_ok() {
| --------- the check is happening here
17 | if x.is_ok() {
| --------- because of this check
18 | x.unwrap(); // unnecessary
19 | x.unwrap_err(); // will panic
| ^^^^^^^^^^^^^^
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:21:9
|
17 | if x.is_ok() {
| --------- because of this check
...
17 | x.unwrap_err();
| ^^^^^^^^^^^^^^
21 | x.unwrap(); // will panic
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:20:9
|
19 | if x.is_err() {
| ---------- the check is happening here
20 | x.unwrap_err();
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:22:9
|
19 | if x.is_err() {
17 | if x.is_ok() {
| --------- the check is happening here
...
22 | x.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:25:9
|
24 | if x.is_err() {
| ---------- because of this check
25 | x.unwrap(); // will panic
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:26:9
|
24 | if x.is_err() {
| ---------- the check is happening here
25 | x.unwrap(); // will panic
26 | x.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:28:9
|
24 | if x.is_err() {
| ---------- the check is happening here
...
22 | x.unwrap();
28 | x.unwrap(); // unnecessary
| ^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:37:9
error: This call to `unwrap_err()` will always panic.
--> $DIR/checked_unwrap.rs:29:9
|
36 | if x.is_ok() && y.is_err() {
24 | if x.is_err() {
| ---------- because of this check
...
29 | x.unwrap_err(); // will panic
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:46:9
|
45 | if x.is_ok() && y.is_err() {
| --------- the check is happening here
37 | x.unwrap();
46 | x.unwrap(); // unnecessary
| ^^^^^^^^^^
error: This call to `unwrap_err()` will always panic.
--> $DIR/checked_unwrap.rs:47:9
|
45 | if x.is_ok() && y.is_err() {
| --------- because of this check
46 | x.unwrap(); // unnecessary
47 | x.unwrap_err(); // will panic
| ^^^^^^^^^^^^^^
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:48:9
|
45 | if x.is_ok() && y.is_err() {
| ---------- because of this check
...
48 | y.unwrap(); // will panic
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:38:9
--> $DIR/checked_unwrap.rs:49:9
|
36 | if x.is_ok() && y.is_err() {
45 | if x.is_ok() && y.is_err() {
| ---------- the check is happening here
37 | x.unwrap();
38 | y.unwrap_err();
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:50:9
|
45 | if x.is_ok() || y.is_ok() {
| --------- the check is happening here
...
50 | x.unwrap_err();
49 | y.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:51:9
|
45 | if x.is_ok() || y.is_ok() {
| --------- the check is happening here
...
51 | y.unwrap_err();
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:55:9
|
54 | if x.is_ok() && !(y.is_ok() || z.is_err()) {
| --------- the check is happening here
55 | x.unwrap();
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:56:9
|
54 | if x.is_ok() && !(y.is_ok() || z.is_err()) {
| --------- the check is happening here
55 | x.unwrap();
56 | y.unwrap_err();
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:57:9
|
54 | if x.is_ok() && !(y.is_ok() || z.is_err()) {
| ---------- the check is happening here
...
57 | z.unwrap();
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:62:9
|
59 | if x.is_ok() || !(y.is_ok() && z.is_err()) {
| --------- the check is happening here
...
62 | x.unwrap_err();
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:63:9
|
59 | if x.is_ok() || !(y.is_ok() && z.is_err()) {
| --------- the check is happening here
58 | if x.is_ok() || y.is_ok() {
| --------- because of this check
...
63 | y.unwrap();
63 | x.unwrap(); // will panic
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:64:9
|
59 | if x.is_ok() || !(y.is_ok() && z.is_err()) {
| ---------- the check is happening here
58 | if x.is_ok() || y.is_ok() {
| --------- the check is happening here
...
64 | z.unwrap_err();
64 | x.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:65:9
|
58 | if x.is_ok() || y.is_ok() {
| --------- because of this check
...
65 | y.unwrap(); // will panic
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:66:9
|
58 | if x.is_ok() || y.is_ok() {
| --------- the check is happening here
...
66 | y.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:72:13
--> $DIR/checked_unwrap.rs:70:9
|
71 | if x.is_some() {
69 | if x.is_ok() && !(y.is_ok() || z.is_err()) {
| --------- the check is happening here
70 | x.unwrap(); // unnecessary
| ^^^^^^^^^^
error: This call to `unwrap_err()` will always panic.
--> $DIR/checked_unwrap.rs:71:9
|
69 | if x.is_ok() && !(y.is_ok() || z.is_err()) {
| --------- because of this check
70 | x.unwrap(); // unnecessary
71 | x.unwrap_err(); // will panic
| ^^^^^^^^^^^^^^
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:72:9
|
69 | if x.is_ok() && !(y.is_ok() || z.is_err()) {
| --------- because of this check
...
72 | y.unwrap(); // will panic
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:73:9
|
69 | if x.is_ok() && !(y.is_ok() || z.is_err()) {
| --------- the check is happening here
...
73 | y.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:74:9
|
69 | if x.is_ok() && !(y.is_ok() || z.is_err()) {
| ---------- the check is happening here
...
74 | z.unwrap(); // unnecessary
| ^^^^^^^^^^
error: This call to `unwrap_err()` will always panic.
--> $DIR/checked_unwrap.rs:75:9
|
69 | if x.is_ok() && !(y.is_ok() || z.is_err()) {
| ---------- because of this check
...
75 | z.unwrap_err(); // will panic
| ^^^^^^^^^^^^^^
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:83:9
|
77 | if x.is_ok() || !(y.is_ok() && z.is_err()) {
| --------- because of this check
...
83 | x.unwrap(); // will panic
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:84:9
|
77 | if x.is_ok() || !(y.is_ok() && z.is_err()) {
| --------- the check is happening here
...
84 | x.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:85:9
|
77 | if x.is_ok() || !(y.is_ok() && z.is_err()) {
| --------- the check is happening here
...
85 | y.unwrap(); // unnecessary
| ^^^^^^^^^^
error: This call to `unwrap_err()` will always panic.
--> $DIR/checked_unwrap.rs:86:9
|
77 | if x.is_ok() || !(y.is_ok() && z.is_err()) {
| --------- because of this check
...
86 | y.unwrap_err(); // will panic
| ^^^^^^^^^^^^^^
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:87:9
|
77 | if x.is_ok() || !(y.is_ok() && z.is_err()) {
| ---------- because of this check
...
87 | z.unwrap(); // will panic
| ^^^^^^^^^^
error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:88:9
|
77 | if x.is_ok() || !(y.is_ok() && z.is_err()) {
| ---------- the check is happening here
...
88 | z.unwrap_err(); // unnecessary
| ^^^^^^^^^^^^^^
error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`.
--> $DIR/checked_unwrap.rs:96:13
|
95 | if x.is_some() {
| ----------- the check is happening here
72 | x.unwrap();
96 | x.unwrap(); // unnecessary
| ^^^^^^^^^^
error: aborting due to 17 previous errors
error: This call to `unwrap()` will always panic.
--> $DIR/checked_unwrap.rs:98:13
|
95 | if x.is_some() {
| ----------- because of this check
...
98 | x.unwrap(); // will panic
| ^^^^^^^^^^
error: aborting due to 34 previous errors

View File

@ -0,0 +1,100 @@
#![warn(default_trait_access)]
use std::default::Default as D2;
use std::string;
use std::default;
fn main() {
let s1: String = Default::default();
let s2 = String::default();
let s3: String = D2::default();
let s4: String = std::default::Default::default();
let s5 = string::String::default();
let s6: String = default::Default::default();
let s7 = std::string::String::default();
let s8: String = DefaultFactory::make_t_badly();
let s9: String = DefaultFactory::make_t_nicely();
let s10 = DerivedDefault::default();
let s11: GenericDerivedDefault<String> = Default::default();
let s12 = GenericDerivedDefault::<String>::default();
let s13 = TupleDerivedDefault::default();
let s14: TupleDerivedDefault = Default::default();
let s15: ArrayDerivedDefault = Default::default();
let s16 = ArrayDerivedDefault::default();
let s17: TupleStructDerivedDefault = Default::default();
let s18 = TupleStructDerivedDefault::default();
println!(
"[{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}] [{:?}]",
s1,
s2,
s3,
s4,
s5,
s6,
s7,
s8,
s9,
s10,
s11,
s12,
s13,
s14,
s15,
s16,
s17,
s18,
);
}
struct DefaultFactory;
impl DefaultFactory {
pub fn make_t_badly<T: Default>() -> T {
Default::default()
}
pub fn make_t_nicely<T: Default>() -> T {
T::default()
}
}
#[derive(Debug, Default)]
struct DerivedDefault {
pub s: String,
}
#[derive(Debug, Default)]
struct GenericDerivedDefault<T: Default + std::fmt::Debug> {
pub s: T,
}
#[derive(Debug, Default)]
struct TupleDerivedDefault {
pub s: (String, String),
}
#[derive(Debug, Default)]
struct ArrayDerivedDefault {
pub s: [String; 10],
}
#[derive(Debug, Default)]
struct TupleStructDerivedDefault(String);

View File

@ -0,0 +1,52 @@
error: Calling std::string::String::default() is more clear than this expression
--> $DIR/default_trait_access.rs:8:22
|
8 | let s1: String = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
|
= note: `-D default-trait-access` implied by `-D warnings`
error: Calling std::string::String::default() is more clear than this expression
--> $DIR/default_trait_access.rs:12:22
|
12 | let s3: String = D2::default();
| ^^^^^^^^^^^^^ help: try: `std::string::String::default()`
error: Calling std::string::String::default() is more clear than this expression
--> $DIR/default_trait_access.rs:14:22
|
14 | let s4: String = std::default::Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
error: Calling std::string::String::default() is more clear than this expression
--> $DIR/default_trait_access.rs:18:22
|
18 | let s6: String = default::Default::default();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::string::String::default()`
error: Calling GenericDerivedDefault<std::string::String>::default() is more clear than this expression
--> $DIR/default_trait_access.rs:28:46
|
28 | let s11: GenericDerivedDefault<String> = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `GenericDerivedDefault<std::string::String>::default()`
error: Calling TupleDerivedDefault::default() is more clear than this expression
--> $DIR/default_trait_access.rs:34:36
|
34 | let s14: TupleDerivedDefault = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `TupleDerivedDefault::default()`
error: Calling ArrayDerivedDefault::default() is more clear than this expression
--> $DIR/default_trait_access.rs:36:36
|
36 | let s15: ArrayDerivedDefault = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `ArrayDerivedDefault::default()`
error: Calling TupleStructDerivedDefault::default() is more clear than this expression
--> $DIR/default_trait_access.rs:40:42
|
40 | let s17: TupleStructDerivedDefault = Default::default();
| ^^^^^^^^^^^^^^^^^^ help: try: `TupleStructDerivedDefault::default()`
error: aborting due to 8 previous errors

View File

View File

@ -30,12 +30,12 @@ impl Foo<i16> for HashMap<String, String> {
impl<K: Hash + Eq, V, S: BuildHasher + Default> Foo<i32> for HashMap<K, V, S> {
fn make() -> (Self, Self) {
(HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default()))
(HashMap::default(), HashMap::with_capacity_and_hasher(10, S::default()))
}
}
impl<S: BuildHasher + Default> Foo<i64> for HashMap<String, String, S> {
fn make() -> (Self, Self) {
(HashMap::default(), HashMap::with_capacity_and_hasher(10, Default::default()))
(HashMap::default(), HashMap::with_capacity_and_hasher(10, S::default()))
}
}
@ -53,12 +53,12 @@ impl Foo<i16> for HashSet<String> {
impl<T: Hash + Eq, S: BuildHasher + Default> Foo<i32> for HashSet<T, S> {
fn make() -> (Self, Self) {
(HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default()))
(HashSet::default(), HashSet::with_capacity_and_hasher(10, S::default()))
}
}
impl<S: BuildHasher + Default> Foo<i64> for HashSet<String, S> {
fn make() -> (Self, Self) {
(HashSet::default(), HashSet::with_capacity_and_hasher(10, Default::default()))
(HashSet::default(), HashSet::with_capacity_and_hasher(10, S::default()))
}
}

View File

@ -0,0 +1,82 @@
#![feature(plugin)]
#![warn(indexing_slicing)]
#![warn(out_of_bounds_indexing)]
#![allow(no_effect, unnecessary_operation)]
fn main() {
let x = [1, 2, 3, 4];
let index: usize = 1;
let index_from: usize = 2;
let index_to: usize = 3;
x[index];
&x[index..];
&x[..index];
&x[index_from..index_to];
&x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to].
x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays.
x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays.
&x[..=4];
&x[1..5];
&x[5..][..10]; // Two lint reports, one for [5..] and another for [..10].
&x[5..];
&x[..5];
&x[5..].iter().map(|x| 2 * x).collect::<Vec<i32>>();
&x[0..=4];
&x[0..][..3];
&x[1..][..5];
&x[4..]; // Ok, should not produce stderr.
&x[..4]; // Ok, should not produce stderr.
&x[..]; // Ok, should not produce stderr.
&x[1..]; // Ok, should not produce stderr.
&x[2..].iter().map(|x| 2 * x).collect::<Vec<i32>>(); // Ok, should not produce stderr.
&x[0..].get(..3); // Ok, should not produce stderr.
x[0]; // Ok, should not produce stderr.
x[3]; // Ok, should not produce stderr.
&x[0..3]; // Ok, should not produce stderr.
let y = &x;
y[0];
&y[1..2];
&y[0..=4];
&y[..=4];
&y[..]; // Ok, should not produce stderr.
let empty: [i8; 0] = [];
empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays.
&empty[1..5];
&empty[0..=4];
&empty[..=4];
&empty[1..];
&empty[..4];
&empty[0..=0];
&empty[..=0];
&empty[0..]; // Ok, should not produce stderr.
&empty[0..0]; // Ok, should not produce stderr.
&empty[..0]; // Ok, should not produce stderr.
&empty[..]; // Ok, should not produce stderr.
let v = vec![0; 5];
v[0];
v[10];
v[1 << 3];
&v[10..100];
&x[10..][..100]; // Two lint reports, one for [10..] and another for [..100].
&v[10..];
&v[..100];
&v[..]; // Ok, should not produce stderr.
//
// Continue tests at end function to minimize the changes to this file's corresponding stderr.
//
const N: usize = 15; // Out of bounds
const M: usize = 3; // In bounds
x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays.
x[M]; // Ok, should not produce stderr.
v[N];
v[M];
}

View File

@ -0,0 +1,271 @@
error: indexing may panic.
--> $DIR/indexing_slicing.rs:11:5
|
11 | x[index];
| ^^^^^^^^
|
= note: `-D indexing-slicing` implied by `-D warnings`
= help: Consider using `.get(n)` or `.get_mut(n)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:12:6
|
12 | &x[index..];
| ^^^^^^^^^^
|
= help: Consider using `.get(n..)` or .get_mut(n..)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:13:6
|
13 | &x[..index];
| ^^^^^^^^^^
|
= help: Consider using `.get(..n)`or `.get_mut(..n)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:14:6
|
14 | &x[index_from..index_to];
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:15:6
|
15 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to].
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: Consider using `.get(..n)`or `.get_mut(..n)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:15:6
|
15 | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to].
| ^^^^^^^^^^^^^^^
|
= help: Consider using `.get(n..)` or .get_mut(n..)` instead
error: range is out of bounds
--> $DIR/indexing_slicing.rs:18:6
|
18 | &x[..=4];
| ^^^^^^^
|
= note: `-D out-of-bounds-indexing` implied by `-D warnings`
error: range is out of bounds
--> $DIR/indexing_slicing.rs:19:6
|
19 | &x[1..5];
| ^^^^^^^
error: slicing may panic.
--> $DIR/indexing_slicing.rs:20:6
|
20 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10].
| ^^^^^^^^^^^^
|
= help: Consider using `.get(..n)`or `.get_mut(..n)` instead
error: range is out of bounds
--> $DIR/indexing_slicing.rs:20:6
|
20 | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10].
| ^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:21:6
|
21 | &x[5..];
| ^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:22:6
|
22 | &x[..5];
| ^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:23:6
|
23 | &x[5..].iter().map(|x| 2 * x).collect::<Vec<i32>>();
| ^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:24:6
|
24 | &x[0..=4];
| ^^^^^^^^
error: slicing may panic.
--> $DIR/indexing_slicing.rs:25:6
|
25 | &x[0..][..3];
| ^^^^^^^^^^^
|
= help: Consider using `.get(..n)`or `.get_mut(..n)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:26:6
|
26 | &x[1..][..5];
| ^^^^^^^^^^^
|
= help: Consider using `.get(..n)`or `.get_mut(..n)` instead
error: indexing may panic.
--> $DIR/indexing_slicing.rs:39:5
|
39 | y[0];
| ^^^^
|
= help: Consider using `.get(n)` or `.get_mut(n)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:40:6
|
40 | &y[1..2];
| ^^^^^^^
|
= help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:41:6
|
41 | &y[0..=4];
| ^^^^^^^^
|
= help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:42:6
|
42 | &y[..=4];
| ^^^^^^^
|
= help: Consider using `.get(..n)`or `.get_mut(..n)` instead
error: range is out of bounds
--> $DIR/indexing_slicing.rs:48:6
|
48 | &empty[1..5];
| ^^^^^^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:49:6
|
49 | &empty[0..=4];
| ^^^^^^^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:50:6
|
50 | &empty[..=4];
| ^^^^^^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:51:6
|
51 | &empty[1..];
| ^^^^^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:52:6
|
52 | &empty[..4];
| ^^^^^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:53:6
|
53 | &empty[0..=0];
| ^^^^^^^^^^^^
error: range is out of bounds
--> $DIR/indexing_slicing.rs:54:6
|
54 | &empty[..=0];
| ^^^^^^^^^^^
error: indexing may panic.
--> $DIR/indexing_slicing.rs:62:5
|
62 | v[0];
| ^^^^
|
= help: Consider using `.get(n)` or `.get_mut(n)` instead
error: indexing may panic.
--> $DIR/indexing_slicing.rs:63:5
|
63 | v[10];
| ^^^^^
|
= help: Consider using `.get(n)` or `.get_mut(n)` instead
error: indexing may panic.
--> $DIR/indexing_slicing.rs:64:5
|
64 | v[1 << 3];
| ^^^^^^^^^
|
= help: Consider using `.get(n)` or `.get_mut(n)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:65:6
|
65 | &v[10..100];
| ^^^^^^^^^^
|
= help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:66:6
|
66 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100].
| ^^^^^^^^^^^^^^
|
= help: Consider using `.get(..n)`or `.get_mut(..n)` instead
error: range is out of bounds
--> $DIR/indexing_slicing.rs:66:6
|
66 | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100].
| ^^^^^^^
error: slicing may panic.
--> $DIR/indexing_slicing.rs:67:6
|
67 | &v[10..];
| ^^^^^^^
|
= help: Consider using `.get(n..)` or .get_mut(n..)` instead
error: slicing may panic.
--> $DIR/indexing_slicing.rs:68:6
|
68 | &v[..100];
| ^^^^^^^^
|
= help: Consider using `.get(..n)`or `.get_mut(..n)` instead
error: indexing may panic.
--> $DIR/indexing_slicing.rs:80:5
|
80 | v[N];
| ^^^^
|
= help: Consider using `.get(n)` or `.get_mut(n)` instead
error: indexing may panic.
--> $DIR/indexing_slicing.rs:81:5
|
81 | v[M];
| ^^^^
|
= help: Consider using `.get(n)` or `.get_mut(n)` instead
error: aborting due to 37 previous errors

View File

@ -53,6 +53,22 @@ fn fn_bound_2<'a, F, I>(_m: Lt<'a, I>, _f: F) -> Lt<'a, I>
where for<'x> F: Fn(Lt<'x, I>) -> Lt<'x, I>
{ unreachable!() }
fn fn_bound_3<'a, F: FnOnce(&'a i32)>(x: &'a i32, f: F) { // no error, see below
f(x);
}
fn fn_bound_3_cannot_elide() {
let x = 42;
let p = &x;
let mut q = &x;
fn_bound_3(p, |y| q = y); // this will fail if we elides lifetimes of `fn_bound_3`
}
// no error, multiple input refs
fn fn_bound_4<'a, F: FnOnce() -> &'a ()>(cond: bool, x: &'a (), f: F) -> &'a () {
if cond { x } else { f() }
}
struct X {
x: u8,
}

View File

@ -45,45 +45,45 @@ error: explicit lifetimes given in parameter types where they could be elided
| |__________________^
error: explicit lifetimes given in parameter types where they could be elided
--> $DIR/lifetimes.rs:61:5
--> $DIR/lifetimes.rs:77:5
|
61 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x }
77 | fn self_and_out<'s>(&'s self) -> &'s u8 { &self.x }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided
--> $DIR/lifetimes.rs:65:5
--> $DIR/lifetimes.rs:81:5
|
65 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { }
81 | fn distinct_self_and_in<'s, 't>(&'s self, _x: &'t u8) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided
--> $DIR/lifetimes.rs:81:1
--> $DIR/lifetimes.rs:97:1
|
81 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() }
97 | fn struct_with_lt<'a>(_foo: Foo<'a>) -> &'a str { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided
--> $DIR/lifetimes.rs:101:1
--> $DIR/lifetimes.rs:117:1
|
101 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() }
117 | fn trait_obj_elided2<'a>(_arg: &'a Drop) -> &'a str { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided
--> $DIR/lifetimes.rs:105:1
--> $DIR/lifetimes.rs:121:1
|
105 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() }
121 | fn alias_with_lt<'a>(_foo: FooAlias<'a>) -> &'a str { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided
--> $DIR/lifetimes.rs:116:1
--> $DIR/lifetimes.rs:132:1
|
116 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() }
132 | fn named_input_elided_output<'a>(_arg: &'a str) -> &str { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: explicit lifetimes given in parameter types where they could be elided
--> $DIR/lifetimes.rs:120:1
--> $DIR/lifetimes.rs:136:1
|
120 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() }
136 | fn trait_bound_ok<'a, T: WithLifetime<'static>>(_: &'a u8, _: T) { unimplemented!() }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 14 previous errors

View File

@ -3,7 +3,8 @@
#![warn(clippy, clippy_pedantic, option_unwrap_used)]
#![allow(blacklisted_name, unused, print_stdout, non_ascii_literal, new_without_default,
new_without_default_derive, missing_docs_in_private_items, needless_pass_by_value)]
new_without_default_derive, missing_docs_in_private_items, needless_pass_by_value,
default_trait_access)]
use std::collections::BTreeMap;
use std::collections::HashMap;

View File

@ -1,528 +1,528 @@
error: unnecessary structure name repetition
--> $DIR/methods.rs:20:29
--> $DIR/methods.rs:21:29
|
20 | pub fn add(self, other: T) -> T { self }
21 | pub fn add(self, other: T) -> T { self }
| ^ help: use the applicable keyword: `Self`
|
= note: `-D use-self` implied by `-D warnings`
error: unnecessary structure name repetition
--> $DIR/methods.rs:20:35
--> $DIR/methods.rs:21:35
|
20 | pub fn add(self, other: T) -> T { self }
21 | pub fn add(self, other: T) -> T { self }
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:24:25
--> $DIR/methods.rs:25:25
|
24 | fn eq(&self, other: T) -> bool { true } // no error, private function
25 | fn eq(&self, other: T) -> bool { true } // no error, private function
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:26:26
--> $DIR/methods.rs:27:26
|
26 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref
27 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:26:33
--> $DIR/methods.rs:27:33
|
26 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref
27 | fn sub(&self, other: T) -> &T { self } // no error, self is a ref
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:27:21
--> $DIR/methods.rs:28:21
|
27 | fn div(self) -> T { self } // no error, different #arguments
28 | fn div(self) -> T { self } // no error, different #arguments
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:28:25
--> $DIR/methods.rs:29:25
|
28 | fn rem(self, other: T) { } // no error, wrong return type
29 | fn rem(self, other: T) { } // no error, wrong return type
| ^ help: use the applicable keyword: `Self`
error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name
--> $DIR/methods.rs:20:5
--> $DIR/methods.rs:21:5
|
20 | pub fn add(self, other: T) -> T { self }
21 | pub fn add(self, other: T) -> T { self }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D should-implement-trait` implied by `-D warnings`
error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name
--> $DIR/methods.rs:31:17
--> $DIR/methods.rs:32:17
|
31 | fn into_u16(&self) -> u16 { 0 }
32 | fn into_u16(&self) -> u16 { 0 }
| ^^^^^
|
= note: `-D wrong-self-convention` implied by `-D warnings`
error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name
--> $DIR/methods.rs:33:21
--> $DIR/methods.rs:34:21
|
33 | fn to_something(self) -> u32 { 0 }
34 | fn to_something(self) -> u32 { 0 }
| ^^^^
error: methods called `new` usually take no self; consider choosing a less ambiguous name
--> $DIR/methods.rs:35:12
--> $DIR/methods.rs:36:12
|
35 | fn new(self) {}
36 | fn new(self) {}
| ^^^^
error: methods called `new` usually return `Self`
--> $DIR/methods.rs:35:5
--> $DIR/methods.rs:36:5
|
35 | fn new(self) {}
36 | fn new(self) {}
| ^^^^^^^^^^^^^^^
|
= note: `-D new-ret-no-self` implied by `-D warnings`
error: unnecessary structure name repetition
--> $DIR/methods.rs:79:24
--> $DIR/methods.rs:80:24
|
79 | fn new() -> Option<V<T>> { None }
80 | fn new() -> Option<V<T>> { None }
| ^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:83:19
--> $DIR/methods.rs:84:19
|
83 | type Output = T;
84 | type Output = T;
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:84:25
--> $DIR/methods.rs:85:25
|
84 | fn mul(self, other: T) -> T { self } // no error, obviously
85 | fn mul(self, other: T) -> T { self } // no error, obviously
| ^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:84:31
--> $DIR/methods.rs:85:31
|
84 | fn mul(self, other: T) -> T { self } // no error, obviously
85 | fn mul(self, other: T) -> T { self } // no error, obviously
| ^ help: use the applicable keyword: `Self`
error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead
--> $DIR/methods.rs:103:13
--> $DIR/methods.rs:104:13
|
103 | let _ = opt.map(|x| x + 1)
104 | let _ = opt.map(|x| x + 1)
| _____________^
104 | |
105 | | .unwrap_or(0); // should lint even though this call is on a separate line
105 | |
106 | | .unwrap_or(0); // should lint even though this call is on a separate line
| |____________________________^
|
= note: `-D option-map-unwrap-or` implied by `-D warnings`
= note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)`
error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead
--> $DIR/methods.rs:107:13
--> $DIR/methods.rs:108:13
|
107 | let _ = opt.map(|x| {
108 | let _ = opt.map(|x| {
| _____________^
108 | | x + 1
109 | | }
110 | | ).unwrap_or(0);
109 | | x + 1
110 | | }
111 | | ).unwrap_or(0);
| |____________________________^
error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead
--> $DIR/methods.rs:111:13
--> $DIR/methods.rs:112:13
|
111 | let _ = opt.map(|x| x + 1)
112 | let _ = opt.map(|x| x + 1)
| _____________^
112 | | .unwrap_or({
113 | | 0
114 | | });
113 | | .unwrap_or({
114 | | 0
115 | | });
| |__________________^
error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead
--> $DIR/methods.rs:116:13
--> $DIR/methods.rs:117:13
|
116 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
117 | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))`
error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead
--> $DIR/methods.rs:118:13
--> $DIR/methods.rs:119:13
|
118 | let _ = opt.map(|x| {
119 | let _ = opt.map(|x| {
| _____________^
119 | | Some(x + 1)
120 | | }
121 | | ).unwrap_or(None);
120 | | Some(x + 1)
121 | | }
122 | | ).unwrap_or(None);
| |_____________________^
error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead
--> $DIR/methods.rs:122:13
--> $DIR/methods.rs:123:13
|
122 | let _ = opt
123 | let _ = opt
| _____________^
123 | | .map(|x| Some(x + 1))
124 | | .unwrap_or(None);
124 | | .map(|x| Some(x + 1))
125 | | .unwrap_or(None);
| |________________________^
|
= note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))`
error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead
--> $DIR/methods.rs:130:13
--> $DIR/methods.rs:131:13
|
130 | let _ = opt.map(|x| x + 1)
131 | let _ = opt.map(|x| x + 1)
| _____________^
131 | |
132 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line
132 | |
133 | | .unwrap_or_else(|| 0); // should lint even though this call is on a separate line
| |____________________________________^
|
= note: `-D option-map-unwrap-or-else` implied by `-D warnings`
= note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)`
error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead
--> $DIR/methods.rs:134:13
--> $DIR/methods.rs:135:13
|
134 | let _ = opt.map(|x| {
135 | let _ = opt.map(|x| {
| _____________^
135 | | x + 1
136 | | }
137 | | ).unwrap_or_else(|| 0);
136 | | x + 1
137 | | }
138 | | ).unwrap_or_else(|| 0);
| |____________________________________^
error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead
--> $DIR/methods.rs:138:13
--> $DIR/methods.rs:139:13
|
138 | let _ = opt.map(|x| x + 1)
139 | let _ = opt.map(|x| x + 1)
| _____________^
139 | | .unwrap_or_else(||
140 | | 0
141 | | );
140 | | .unwrap_or_else(||
141 | | 0
142 | | );
| |_________________^
error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead
--> $DIR/methods.rs:147:13
--> $DIR/methods.rs:148:13
|
147 | let _ = opt.map_or(None, |x| Some(x + 1));
148 | let _ = opt.map_or(None, |x| Some(x + 1));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using and_then instead: `opt.and_then(|x| Some(x + 1))`
|
= note: `-D option-map-or-none` implied by `-D warnings`
error: called `map_or(None, f)` on an Option value. This can be done more directly by calling `and_then(f)` instead
--> $DIR/methods.rs:149:13
--> $DIR/methods.rs:150:13
|
149 | let _ = opt.map_or(None, |x| {
150 | let _ = opt.map_or(None, |x| {
| _____________^
150 | | Some(x + 1)
151 | | }
152 | | );
151 | | Some(x + 1)
152 | | }
153 | | );
| |_________________^
help: try using and_then instead
|
149 | let _ = opt.and_then(|x| {
150 | Some(x + 1)
151 | });
150 | let _ = opt.and_then(|x| {
151 | Some(x + 1)
152 | });
|
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
--> $DIR/methods.rs:162:13
--> $DIR/methods.rs:163:13
|
162 | let _ = res.map(|x| x + 1)
163 | let _ = res.map(|x| x + 1)
| _____________^
163 | |
164 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line
164 | |
165 | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line
| |_____________________________________^
|
= note: `-D 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)`
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
--> $DIR/methods.rs:166:13
--> $DIR/methods.rs:167:13
|
166 | let _ = res.map(|x| {
167 | let _ = res.map(|x| {
| _____________^
167 | | x + 1
168 | | }
169 | | ).unwrap_or_else(|e| 0);
168 | | x + 1
169 | | }
170 | | ).unwrap_or_else(|e| 0);
| |_____________________________________^
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
--> $DIR/methods.rs:170:13
--> $DIR/methods.rs:171:13
|
170 | let _ = res.map(|x| x + 1)
171 | let _ = res.map(|x| x + 1)
| _____________^
171 | | .unwrap_or_else(|e|
172 | | 0
173 | | );
172 | | .unwrap_or_else(|e|
173 | | 0
174 | | );
| |_________________^
error: unnecessary structure name repetition
--> $DIR/methods.rs:199:24
--> $DIR/methods.rs:200:24
|
199 | fn filter(self) -> IteratorFalsePositives {
200 | fn filter(self) -> IteratorFalsePositives {
| ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:203:22
--> $DIR/methods.rs:204:22
|
203 | fn next(self) -> IteratorFalsePositives {
204 | fn next(self) -> IteratorFalsePositives {
| ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
error: unnecessary structure name repetition
--> $DIR/methods.rs:223:32
--> $DIR/methods.rs:224:32
|
223 | fn skip(self, _: usize) -> IteratorFalsePositives {
224 | fn skip(self, _: usize) -> IteratorFalsePositives {
| ^^^^^^^^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self`
error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
--> $DIR/methods.rs:233:13
--> $DIR/methods.rs:234:13
|
233 | let _ = v.iter().filter(|&x| *x < 0).next();
234 | let _ = v.iter().filter(|&x| *x < 0).next();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D filter-next` implied by `-D warnings`
= note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)`
error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead.
--> $DIR/methods.rs:236:13
--> $DIR/methods.rs:237:13
|
236 | let _ = v.iter().filter(|&x| {
237 | let _ = v.iter().filter(|&x| {
| _____________^
237 | | *x < 0
238 | | }
239 | | ).next();
238 | | *x < 0
239 | | }
240 | | ).next();
| |___________________________^
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
--> $DIR/methods.rs:251:13
--> $DIR/methods.rs:252:13
|
251 | let _ = v.iter().find(|&x| *x < 0).is_some();
252 | let _ = v.iter().find(|&x| *x < 0).is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D search-is-some` implied by `-D warnings`
= note: replace `find(|&x| *x < 0).is_some()` with `any(|&x| *x < 0)`
error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`.
--> $DIR/methods.rs:254:13
--> $DIR/methods.rs:255:13
|
254 | let _ = v.iter().find(|&x| {
255 | let _ = v.iter().find(|&x| {
| _____________^
255 | | *x < 0
256 | | }
257 | | ).is_some();
256 | | *x < 0
257 | | }
258 | | ).is_some();
| |______________________________^
error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
--> $DIR/methods.rs:260:13
--> $DIR/methods.rs:261:13
|
260 | let _ = v.iter().position(|&x| x < 0).is_some();
261 | let _ = v.iter().position(|&x| x < 0).is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: replace `position(|&x| x < 0).is_some()` with `any(|&x| x < 0)`
error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`.
--> $DIR/methods.rs:263:13
--> $DIR/methods.rs:264:13
|
263 | let _ = v.iter().position(|&x| {
264 | let _ = v.iter().position(|&x| {
| _____________^
264 | | x < 0
265 | | }
266 | | ).is_some();
265 | | x < 0
266 | | }
267 | | ).is_some();
| |______________________________^
error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
--> $DIR/methods.rs:269:13
--> $DIR/methods.rs:270:13
|
269 | let _ = v.iter().rposition(|&x| x < 0).is_some();
270 | let _ = v.iter().rposition(|&x| x < 0).is_some();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: replace `rposition(|&x| x < 0).is_some()` with `any(|&x| x < 0)`
error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`.
--> $DIR/methods.rs:272:13
--> $DIR/methods.rs:273:13
|
272 | let _ = v.iter().rposition(|&x| {
273 | let _ = v.iter().rposition(|&x| {
| _____________^
273 | | x < 0
274 | | }
275 | | ).is_some();
274 | | x < 0
275 | | }
276 | | ).is_some();
| |______________________________^
error: unnecessary structure name repetition
--> $DIR/methods.rs:289:21
--> $DIR/methods.rs:290:21
|
289 | fn new() -> Foo { Foo }
290 | fn new() -> Foo { Foo }
| ^^^ help: use the applicable keyword: `Self`
error: use of `unwrap_or` followed by a function call
--> $DIR/methods.rs:307:22
--> $DIR/methods.rs:308:22
|
307 | with_constructor.unwrap_or(make());
308 | with_constructor.unwrap_or(make());
| ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)`
|
= note: `-D or-fun-call` implied by `-D warnings`
error: use of `unwrap_or` followed by a call to `new`
--> $DIR/methods.rs:310:5
--> $DIR/methods.rs:311:5
|
310 | with_new.unwrap_or(Vec::new());
311 | with_new.unwrap_or(Vec::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()`
error: use of `unwrap_or` followed by a function call
--> $DIR/methods.rs:313:21
--> $DIR/methods.rs:314:21
|
313 | with_const_args.unwrap_or(Vec::with_capacity(12));
314 | with_const_args.unwrap_or(Vec::with_capacity(12));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))`
error: use of `unwrap_or` followed by a function call
--> $DIR/methods.rs:316:14
--> $DIR/methods.rs:317:14
|
316 | with_err.unwrap_or(make());
317 | with_err.unwrap_or(make());
| ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())`
error: use of `unwrap_or` followed by a function call
--> $DIR/methods.rs:319:19
--> $DIR/methods.rs:320:19
|
319 | with_err_args.unwrap_or(Vec::with_capacity(12));
320 | with_err_args.unwrap_or(Vec::with_capacity(12));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))`
error: use of `unwrap_or` followed by a call to `default`
--> $DIR/methods.rs:322:5
--> $DIR/methods.rs:323:5
|
322 | with_default_trait.unwrap_or(Default::default());
323 | with_default_trait.unwrap_or(Default::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()`
error: use of `unwrap_or` followed by a call to `default`
--> $DIR/methods.rs:325:5
--> $DIR/methods.rs:326:5
|
325 | with_default_type.unwrap_or(u64::default());
326 | with_default_type.unwrap_or(u64::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()`
error: use of `unwrap_or` followed by a function call
--> $DIR/methods.rs:328:14
--> $DIR/methods.rs:329:14
|
328 | with_vec.unwrap_or(vec![]);
329 | with_vec.unwrap_or(vec![]);
| ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| < [ _ ] > :: into_vec ( box [ $ ( $ x ) , * ] ))`
error: use of `unwrap_or` followed by a function call
--> $DIR/methods.rs:333:21
--> $DIR/methods.rs:334:21
|
333 | without_default.unwrap_or(Foo::new());
334 | without_default.unwrap_or(Foo::new());
| ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)`
error: use of `or_insert` followed by a function call
--> $DIR/methods.rs:336:19
--> $DIR/methods.rs:337:19
|
336 | map.entry(42).or_insert(String::new());
337 | map.entry(42).or_insert(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
error: use of `or_insert` followed by a function call
--> $DIR/methods.rs:339:21
--> $DIR/methods.rs:340:21
|
339 | btree.entry(42).or_insert(String::new());
340 | btree.entry(42).or_insert(String::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
error: use of `unwrap_or` followed by a function call
--> $DIR/methods.rs:342:21
--> $DIR/methods.rs:343:21
|
342 | let _ = stringy.unwrap_or("".to_owned());
343 | let _ = stringy.unwrap_or("".to_owned());
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())`
error: use of `expect` followed by a function call
--> $DIR/methods.rs:365:26
--> $DIR/methods.rs:366:26
|
365 | with_none_and_format.expect(&format!("Error {}: fake error", error_code));
366 | with_none_and_format.expect(&format!("Error {}: fake error", error_code));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("Error {}: fake error", error_code))`
|
= note: `-D expect-fun-call` implied by `-D warnings`
error: use of `expect` followed by a function call
--> $DIR/methods.rs:368:26
--> $DIR/methods.rs:369:26
|
368 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
369 | with_none_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!(format!("Error {}: fake error", error_code).as_str()))`
error: use of `expect` followed by a function call
--> $DIR/methods.rs:378:25
--> $DIR/methods.rs:379:25
|
378 | with_err_and_format.expect(&format!("Error {}: fake error", error_code));
379 | with_err_and_format.expect(&format!("Error {}: fake error", error_code));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!("Error {}: fake error", error_code))`
error: use of `expect` followed by a function call
--> $DIR/methods.rs:381:25
--> $DIR/methods.rs:382:25
|
381 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
382 | with_err_and_as_str.expect(format!("Error {}: fake error", error_code).as_str());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| panic!(format!("Error {}: fake error", error_code).as_str()))`
error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable
--> $DIR/methods.rs:401:23
--> $DIR/methods.rs:402:23
|
401 | let bad_vec = some_vec.iter().nth(3);
402 | let bad_vec = some_vec.iter().nth(3);
| ^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D iter-nth` implied by `-D warnings`
error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable
--> $DIR/methods.rs:402:26
--> $DIR/methods.rs:403:26
|
402 | let bad_slice = &some_vec[..].iter().nth(3);
403 | let bad_slice = &some_vec[..].iter().nth(3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable
--> $DIR/methods.rs:403:31
--> $DIR/methods.rs:404:31
|
403 | let bad_boxed_slice = boxed_slice.iter().nth(3);
404 | let bad_boxed_slice = boxed_slice.iter().nth(3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable
--> $DIR/methods.rs:404:29
--> $DIR/methods.rs:405:29
|
404 | let bad_vec_deque = some_vec_deque.iter().nth(3);
405 | let bad_vec_deque = some_vec_deque.iter().nth(3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable
--> $DIR/methods.rs:409:23
--> $DIR/methods.rs:410:23
|
409 | let bad_vec = some_vec.iter_mut().nth(3);
410 | let bad_vec = some_vec.iter_mut().nth(3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable
--> $DIR/methods.rs:412:26
--> $DIR/methods.rs:413:26
|
412 | let bad_slice = &some_vec[..].iter_mut().nth(3);
413 | let bad_slice = &some_vec[..].iter_mut().nth(3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable
--> $DIR/methods.rs:415:29
--> $DIR/methods.rs:416:29
|
415 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3);
416 | let bad_vec_deque = some_vec_deque.iter_mut().nth(3);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)`
--> $DIR/methods.rs:427:13
--> $DIR/methods.rs:428:13
|
427 | let _ = some_vec.iter().skip(42).next();
428 | let _ = some_vec.iter().skip(42).next();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D iter-skip-next` implied by `-D warnings`
error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)`
--> $DIR/methods.rs:428:13
--> $DIR/methods.rs:429:13
|
428 | let _ = some_vec.iter().cycle().skip(42).next();
429 | let _ = some_vec.iter().cycle().skip(42).next();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)`
--> $DIR/methods.rs:429:13
--> $DIR/methods.rs:430:13
|
429 | let _ = (1..10).skip(10).next();
430 | let _ = (1..10).skip(10).next();
| ^^^^^^^^^^^^^^^^^^^^^^^
error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)`
--> $DIR/methods.rs:430:14
--> $DIR/methods.rs:431:14
|
430 | let _ = &some_vec[..].iter().skip(3).next();
431 | let _ = &some_vec[..].iter().skip(3).next();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message
--> $DIR/methods.rs:439:13
--> $DIR/methods.rs:440:13
|
439 | let _ = opt.unwrap();
440 | let _ = opt.unwrap();
| ^^^^^^^^^^^^
|
= note: `-D option-unwrap-used` implied by `-D warnings`

View File

@ -1,6 +1,6 @@
/// This test case utilizes `f64` an easy example for `PartialOrd` only types
/// but the lint itself actually validates any expression where the left
/// operand implements `PartialOrd` but not `Ord`.
//! This test case utilizes `f64` an easy example for `PartialOrd` only types
//! but the lint itself actually validates any expression where the left
//! operand implements `PartialOrd` but not `Ord`.
use std::cmp::Ordering;
@ -54,5 +54,14 @@ fn main() {
let _ = a_value <= another_value;
let _ = a_value > another_value;
let _ = a_value >= another_value;
}
// --- regression tests ---
// Issue 2856: False positive on assert!()
//
// The macro always negates the result of the given comparision in its
// internal check which automatically triggered the lint. As it's an
// external macro there was no chance to do anything about it which lead
// to a whitelisting of all external macros.
assert!(a_value < another_value);
}