mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-28 01:34:21 +00:00
Merge branch 'master' into issue_2741
This commit is contained in:
commit
4827bdcc1c
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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:
|
||||
|
||||
|
@ -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>",
|
||||
|
@ -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))
|
||||
}
|
@ -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
|
||||
|
68
clippy_lints/src/default_trait_access.rs
Normal file
68
clippy_lints/src/default_trait_access.rs
Normal 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(..) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
183
clippy_lints/src/indexing_slicing.rs
Normal file
183
clippy_lints/src/indexing_slicing.rs
Normal 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))
|
||||
}
|
@ -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, it’s 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,
|
||||
]);
|
||||
}
|
||||
|
@ -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 ¶ms.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 };
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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,
|
||||
},
|
||||
];
|
||||
|
@ -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(¶ms.types[0]) || is_ty(&*params.types[0], self_ty))
|
||||
false
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
})
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
},
|
||||
_ => false,
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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(..) |
|
||||
|
@ -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| ¶ms.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,
|
||||
|
@ -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 \
|
||||
|
@ -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`
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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)) => {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
},
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"];
|
||||
|
@ -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(..) |
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
14
tests/run-pass/issue-2862.rs
Normal file
14
tests/run-pass/issue-2862.rs
Normal 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);
|
||||
}
|
@ -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];
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
100
tests/ui/default_trait_access.rs
Normal file
100
tests/ui/default_trait_access.rs
Normal 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);
|
52
tests/ui/default_trait_access.stderr
Normal file
52
tests/ui/default_trait_access.stderr
Normal 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
|
||||
|
0
tests/ui/default_trait_access.stdout
Normal file
0
tests/ui/default_trait_access.stdout
Normal 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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
82
tests/ui/indexing_slicing.rs
Normal file
82
tests/ui/indexing_slicing.rs
Normal 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];
|
||||
}
|
271
tests/ui/indexing_slicing.stderr
Normal file
271
tests/ui/indexing_slicing.stderr
Normal 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
|
||||
|
@ -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,
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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`
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user