1
Fork 0

Merge commit '3e4179766b' into sync-from-clippy

This commit is contained in:
Manish Goregaokar 2021-02-02 20:43:30 -08:00
parent b56b751055
commit c8cb90abbd
35 changed files with 526 additions and 134 deletions

View file

@ -2079,6 +2079,7 @@ Released 2018-09-13
[`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items [`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
[`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc [`missing_errors_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_errors_doc
[`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items [`missing_inline_in_public_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_inline_in_public_items
[`missing_panics_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_panics_doc
[`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc [`missing_safety_doc`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_safety_doc
[`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes [`mistyped_literal_suffixes`]: https://rust-lang.github.io/rust-clippy/master/index.html#mistyped_literal_suffixes
[`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals [`mixed_case_hex_literals`]: https://rust-lang.github.io/rust-clippy/master/index.html#mixed_case_hex_literals

View file

@ -46,11 +46,12 @@ first read the [Basics docs](doc/basics.md).**
### Finding something to fix/improve ### Finding something to fix/improve
All issues on Clippy are mentored, if you want help with a bug just ask All issues on Clippy are mentored, if you want help simply ask @Manishearth, @flip1995, @phansch
@Manishearth, @flip1995, @phansch or @yaahc. or @llogiq directly by mentioning them in the issue or over on [Zulip]. This list may be out of date.
All currently active mentors can be found [here](https://github.com/rust-lang/highfive/blob/master/highfive/configs/rust-lang/rust-clippy.json#L3)
Some issues are easier than others. The [`good-first-issue`] label can be used to find the easy issues. Some issues are easier than others. The [`good-first-issue`] label can be used to find the easy
If you want to work on an issue, please leave a comment so that we can assign it to you! issues. You can use `@rustbot claim` to assign the issue to yourself.
There are also some abandoned PRs, marked with [`S-inactive-closed`]. There are also some abandoned PRs, marked with [`S-inactive-closed`].
Pretty often these PRs are nearly completed and just need some extra steps Pretty often these PRs are nearly completed and just need some extra steps

View file

@ -24,6 +24,9 @@ static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> = SyncLazy::ne
fs::metadata(path).ok()?.modified().ok() fs::metadata(path).ok()?.modified().ok()
}); });
/// # Panics
///
/// Panics if the path to a test file is broken
pub fn bless(ignore_timestamp: bool) { pub fn bless(ignore_timestamp: bool) {
let test_suite_dirs = [ let test_suite_dirs = [
clippy_project_root().join("tests").join("ui"), clippy_project_root().join("tests").join("ui"),

View file

@ -8,7 +8,7 @@ use walkdir::WalkDir;
#[derive(Debug)] #[derive(Debug)]
pub enum CliError { pub enum CliError {
CommandFailed(String), CommandFailed(String, String),
IoError(io::Error), IoError(io::Error),
RustfmtNotInstalled, RustfmtNotInstalled,
WalkDirError(walkdir::Error), WalkDirError(walkdir::Error),
@ -75,8 +75,8 @@ pub fn run(check: bool, verbose: bool) {
fn output_err(err: CliError) { fn output_err(err: CliError) {
match err { match err {
CliError::CommandFailed(command) => { CliError::CommandFailed(command, stderr) => {
eprintln!("error: A command failed! `{}`", command); eprintln!("error: A command failed! `{}`\nstderr: {}", command, stderr);
}, },
CliError::IoError(err) => { CliError::IoError(err) => {
eprintln!("error: {}", err); eprintln!("error: {}", err);
@ -136,12 +136,16 @@ fn exec(
println!("{}", format_command(&program, &dir, args)); println!("{}", format_command(&program, &dir, args));
} }
let mut child = Command::new(&program).current_dir(&dir).args(args.iter()).spawn()?; let child = Command::new(&program).current_dir(&dir).args(args.iter()).spawn()?;
let code = child.wait()?; let output = child.wait_with_output()?;
let success = code.success(); let success = output.status.success();
if !context.check && !success { if !context.check && !success {
return Err(CliError::CommandFailed(format_command(&program, &dir, args))); let stderr = std::str::from_utf8(&output.stderr).unwrap_or("");
return Err(CliError::CommandFailed(
format_command(&program, &dir, args),
String::from(stderr),
));
} }
Ok(success) Ok(success)
@ -177,7 +181,10 @@ fn rustfmt_test(context: &FmtContext) -> Result<(), CliError> {
{ {
Err(CliError::RustfmtNotInstalled) Err(CliError::RustfmtNotInstalled)
} else { } else {
Err(CliError::CommandFailed(format_command(&program, &dir, args))) Err(CliError::CommandFailed(
format_command(&program, &dir, args),
std::str::from_utf8(&output.stderr).unwrap_or("").to_string(),
))
} }
} }

View file

@ -236,6 +236,10 @@ pub struct FileChange {
/// `path` is the relative path to the file on which you want to perform the replacement. /// `path` is the relative path to the file on which you want to perform the replacement.
/// ///
/// See `replace_region_in_text` for documentation of the other options. /// See `replace_region_in_text` for documentation of the other options.
///
/// # Panics
///
/// Panics if the path could not read or then written
pub fn replace_region_in_file<F>( pub fn replace_region_in_file<F>(
path: &Path, path: &Path,
start: &str, start: &str,
@ -283,6 +287,10 @@ where
/// .new_lines; /// .new_lines;
/// assert_eq!("replace_start\na different\ntext\nreplace_end", result); /// assert_eq!("replace_start\na different\ntext\nreplace_end", result);
/// ``` /// ```
///
/// # Panics
///
/// Panics if start or end is not valid regex
pub fn replace_region_in_text<F>(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange pub fn replace_region_in_text<F>(text: &str, start: &str, end: &str, replace_start: bool, replacements: F) -> FileChange
where where
F: FnOnce() -> Vec<String>, F: FnOnce() -> Vec<String>,
@ -329,6 +337,11 @@ where
} }
/// Returns the path to the Clippy project directory /// Returns the path to the Clippy project directory
///
/// # Panics
///
/// Panics if the current directory could not be retrieved, there was an error reading any of the
/// Cargo.toml files or ancestor directory is the clippy root directory
#[must_use] #[must_use]
pub fn clippy_project_root() -> PathBuf { pub fn clippy_project_root() -> PathBuf {
let current_dir = std::env::current_dir().unwrap(); let current_dir = std::env::current_dir().unwrap();

View file

@ -8,6 +8,9 @@ use std::path::{Path, PathBuf};
// This allows rust analyzer to analyze rustc internals and show proper information inside clippy // This allows rust analyzer to analyze rustc internals and show proper information inside clippy
// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details // code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details
/// # Panics
///
/// Panics if `rustc_path` does not lead to a rustc repo or the files could not be read
pub fn run(rustc_path: Option<&str>) { pub fn run(rustc_path: Option<&str>) {
// we can unwrap here because the arg is required by clap // we can unwrap here because the arg is required by clap
let rustc_path = PathBuf::from(rustc_path.unwrap()); let rustc_path = PathBuf::from(rustc_path.unwrap());

View file

@ -4,6 +4,9 @@ use std::process::Command;
use std::thread; use std::thread;
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
/// # Panics
///
/// Panics if the python commands could not be spawned
pub fn run(port: u16, lint: Option<&str>) -> ! { pub fn run(port: u16, lint: Option<&str>) -> ! {
let mut url = Some(match lint { let mut url = Some(match lint {
None => format!("http://localhost:{}", port), None => format!("http://localhost:{}", port),

View file

@ -1,4 +1,7 @@
use crate::utils::{implements_trait, is_entrypoint_fn, is_type_diagnostic_item, return_ty, span_lint}; use crate::utils::{
implements_trait, is_entrypoint_fn, is_type_diagnostic_item, match_panic_def_id, method_chain_args, return_ty,
span_lint, span_lint_and_note,
};
use if_chain::if_chain; use if_chain::if_chain;
use itertools::Itertools; use itertools::Itertools;
use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind}; use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind};
@ -8,7 +11,10 @@ use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::EmitterWriter; use rustc_errors::emitter::EmitterWriter;
use rustc_errors::Handler; use rustc_errors::Handler;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty; use rustc_middle::ty;
use rustc_parse::maybe_new_parser_from_source_str; use rustc_parse::maybe_new_parser_from_source_str;
@ -122,6 +128,37 @@ declare_clippy_lint! {
"`pub fn` returns `Result` without `# Errors` in doc comment" "`pub fn` returns `Result` without `# Errors` in doc comment"
} }
declare_clippy_lint! {
/// **What it does:** Checks the doc comments of publicly visible functions that
/// may panic and warns if there is no `# Panics` section.
///
/// **Why is this bad?** Documenting the scenarios in which panicking occurs
/// can help callers who do not want to panic to avoid those situations.
///
/// **Known problems:** None.
///
/// **Examples:**
///
/// Since the following function may panic it has a `# Panics` section in
/// its doc comment:
///
/// ```rust
/// /// # Panics
/// ///
/// /// Will panic if y is 0
/// pub fn divide_by(x: i32, y: i32) -> i32 {
/// if y == 0 {
/// panic!("Cannot divide by 0")
/// } else {
/// x / y
/// }
/// }
/// ```
pub MISSING_PANICS_DOC,
pedantic,
"`pub fn` may panic without `# Panics` in doc comment"
}
declare_clippy_lint! { declare_clippy_lint! {
/// **What it does:** Checks for `fn main() { .. }` in doctests /// **What it does:** Checks for `fn main() { .. }` in doctests
/// ///
@ -166,7 +203,9 @@ impl DocMarkdown {
} }
} }
impl_lint_pass!(DocMarkdown => [DOC_MARKDOWN, MISSING_SAFETY_DOC, MISSING_ERRORS_DOC, NEEDLESS_DOCTEST_MAIN]); impl_lint_pass!(DocMarkdown =>
[DOC_MARKDOWN, MISSING_SAFETY_DOC, MISSING_ERRORS_DOC, MISSING_PANICS_DOC, NEEDLESS_DOCTEST_MAIN]
);
impl<'tcx> LateLintPass<'tcx> for DocMarkdown { impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) { fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) {
@ -180,7 +219,15 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
if !(is_entrypoint_fn(cx, cx.tcx.hir().local_def_id(item.hir_id).to_def_id()) if !(is_entrypoint_fn(cx, cx.tcx.hir().local_def_id(item.hir_id).to_def_id())
|| in_external_macro(cx.tcx.sess, item.span)) || in_external_macro(cx.tcx.sess, item.span))
{ {
lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id)); let body = cx.tcx.hir().body(body_id);
let impl_item_def_id = cx.tcx.hir().local_def_id(item.hir_id);
let mut fpu = FindPanicUnwrap {
cx,
typeck_results: cx.tcx.typeck(impl_item_def_id),
panic_span: None,
};
fpu.visit_expr(&body.value);
lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
} }
}, },
hir::ItemKind::Impl(ref impl_) => { hir::ItemKind::Impl(ref impl_) => {
@ -200,7 +247,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
let headers = check_attrs(cx, &self.valid_idents, &item.attrs); let headers = check_attrs(cx, &self.valid_idents, &item.attrs);
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind { if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
if !in_external_macro(cx.tcx.sess, item.span) { if !in_external_macro(cx.tcx.sess, item.span) {
lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, None); lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, None, None);
} }
} }
} }
@ -211,7 +258,15 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
return; return;
} }
if let hir::ImplItemKind::Fn(ref sig, body_id) = item.kind { if let hir::ImplItemKind::Fn(ref sig, body_id) = item.kind {
lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id)); let body = cx.tcx.hir().body(body_id);
let impl_item_def_id = cx.tcx.hir().local_def_id(item.hir_id);
let mut fpu = FindPanicUnwrap {
cx,
typeck_results: cx.tcx.typeck(impl_item_def_id),
panic_span: None,
};
fpu.visit_expr(&body.value);
lint_for_missing_headers(cx, item.hir_id, item.span, sig, headers, Some(body_id), fpu.panic_span);
} }
} }
} }
@ -223,6 +278,7 @@ fn lint_for_missing_headers<'tcx>(
sig: &hir::FnSig<'_>, sig: &hir::FnSig<'_>,
headers: DocHeaders, headers: DocHeaders,
body_id: Option<hir::BodyId>, body_id: Option<hir::BodyId>,
panic_span: Option<Span>,
) { ) {
if !cx.access_levels.is_exported(hir_id) { if !cx.access_levels.is_exported(hir_id) {
return; // Private functions do not require doc comments return; // Private functions do not require doc comments
@ -235,6 +291,16 @@ fn lint_for_missing_headers<'tcx>(
"unsafe function's docs miss `# Safety` section", "unsafe function's docs miss `# Safety` section",
); );
} }
if !headers.panics && panic_span.is_some() {
span_lint_and_note(
cx,
MISSING_PANICS_DOC,
span,
"docs for function which may panic missing `# Panics` section",
panic_span,
"first possible panic found here",
);
}
if !headers.errors { if !headers.errors {
if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::result_type) { if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::result_type) {
span_lint( span_lint(
@ -321,6 +387,7 @@ pub fn strip_doc_comment_decoration(doc: &str, comment_kind: CommentKind, span:
struct DocHeaders { struct DocHeaders {
safety: bool, safety: bool,
errors: bool, errors: bool,
panics: bool,
} }
fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [Attribute]) -> DocHeaders { fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [Attribute]) -> DocHeaders {
@ -338,6 +405,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
return DocHeaders { return DocHeaders {
safety: true, safety: true,
errors: true, errors: true,
panics: true,
}; };
} }
} }
@ -353,6 +421,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
return DocHeaders { return DocHeaders {
safety: false, safety: false,
errors: false, errors: false,
panics: false,
}; };
} }
@ -394,6 +463,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
let mut headers = DocHeaders { let mut headers = DocHeaders {
safety: false, safety: false,
errors: false, errors: false,
panics: false,
}; };
let mut in_code = false; let mut in_code = false;
let mut in_link = None; let mut in_link = None;
@ -439,6 +509,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
} }
headers.safety |= in_heading && text.trim() == "Safety"; headers.safety |= in_heading && text.trim() == "Safety";
headers.errors |= in_heading && text.trim() == "Errors"; headers.errors |= in_heading && text.trim() == "Errors";
headers.panics |= in_heading && text.trim() == "Panics";
let index = match spans.binary_search_by(|c| c.0.cmp(&range.start)) { let index = match spans.binary_search_by(|c| c.0.cmp(&range.start)) {
Ok(o) => o, Ok(o) => o,
Err(e) => e - 1, Err(e) => e - 1,
@ -609,3 +680,47 @@ fn check_word(cx: &LateContext<'_>, word: &str, span: Span) {
); );
} }
} }
struct FindPanicUnwrap<'a, 'tcx> {
cx: &'a LateContext<'tcx>,
panic_span: Option<Span>,
typeck_results: &'tcx ty::TypeckResults<'tcx>,
}
impl<'a, 'tcx> Visitor<'tcx> for FindPanicUnwrap<'a, 'tcx> {
type Map = Map<'tcx>;
fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
if self.panic_span.is_some() {
return;
}
// check for `begin_panic`
if_chain! {
if let ExprKind::Call(ref func_expr, _) = expr.kind;
if let ExprKind::Path(QPath::Resolved(_, ref path)) = func_expr.kind;
if let Some(path_def_id) = path.res.opt_def_id();
if match_panic_def_id(self.cx, path_def_id);
then {
self.panic_span = Some(expr.span);
}
}
// check for `unwrap`
if let Some(arglists) = method_chain_args(expr, &["unwrap"]) {
let reciever_ty = self.typeck_results.expr_ty(&arglists[0][0]).peel_refs();
if is_type_diagnostic_item(self.cx, reciever_ty, sym::option_type)
|| is_type_diagnostic_item(self.cx, reciever_ty, sym::result_type)
{
self.panic_span = Some(expr.span);
}
}
// and check sub-expressions
intravisit::walk_expr(self, expr);
}
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
}
}

View file

@ -160,15 +160,17 @@ impl EarlyLintPass for ExcessiveBools {
"consider using a state machine or refactoring bools into two-variant enums", "consider using a state machine or refactoring bools into two-variant enums",
); );
} }
} },
ItemKind::Impl(box ImplKind { of_trait: None, items, .. }) ItemKind::Impl(box ImplKind {
of_trait: None, items, ..
})
| ItemKind::Trait(box TraitKind(.., items)) => { | ItemKind::Trait(box TraitKind(.., items)) => {
for item in items { for item in items {
if let AssocItemKind::Fn(box FnKind(_, fn_sig, _, _)) = &item.kind { if let AssocItemKind::Fn(box FnKind(_, fn_sig, _, _)) = &item.kind {
self.check_fn_sig(cx, fn_sig, item.span); self.check_fn_sig(cx, fn_sig, item.span);
} }
} }
} },
ItemKind::Fn(box FnKind(_, fn_sig, _, _)) => self.check_fn_sig(cx, fn_sig, item.span), ItemKind::Fn(box FnKind(_, fn_sig, _, _)) => self.check_fn_sig(cx, fn_sig, item.span),
_ => (), _ => (),
} }

View file

@ -75,10 +75,14 @@ impl LateLintPass<'_> for ExhaustiveItems {
if cx.access_levels.is_exported(item.hir_id); if cx.access_levels.is_exported(item.hir_id);
if !item.attrs.iter().any(|a| a.has_name(sym::non_exhaustive)); if !item.attrs.iter().any(|a| a.has_name(sym::non_exhaustive));
then { then {
let (lint, msg) = if let ItemKind::Enum(..) = item.kind { let (lint, msg) = if let ItemKind::Struct(ref v, ..) = item.kind {
(EXHAUSTIVE_ENUMS, "exported enums should not be exhaustive") if v.fields().iter().any(|f| !f.vis.node.is_pub()) {
} else { // skip structs with private fields
return;
}
(EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive") (EXHAUSTIVE_STRUCTS, "exported structs should not be exhaustive")
} else {
(EXHAUSTIVE_ENUMS, "exported enums should not be exhaustive")
}; };
let suggestion_span = item.span.shrink_to_lo(); let suggestion_span = item.span.shrink_to_lo();
let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0)); let indent = " ".repeat(indent_of(cx, item.span).unwrap_or(0));

View file

@ -592,6 +592,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&disallowed_method::DISALLOWED_METHOD, &disallowed_method::DISALLOWED_METHOD,
&doc::DOC_MARKDOWN, &doc::DOC_MARKDOWN,
&doc::MISSING_ERRORS_DOC, &doc::MISSING_ERRORS_DOC,
&doc::MISSING_PANICS_DOC,
&doc::MISSING_SAFETY_DOC, &doc::MISSING_SAFETY_DOC,
&doc::NEEDLESS_DOCTEST_MAIN, &doc::NEEDLESS_DOCTEST_MAIN,
&double_comparison::DOUBLE_COMPARISONS, &double_comparison::DOUBLE_COMPARISONS,
@ -1317,6 +1318,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE), LintId::of(&derive::UNSAFE_DERIVE_DESERIALIZE),
LintId::of(&doc::DOC_MARKDOWN), LintId::of(&doc::DOC_MARKDOWN),
LintId::of(&doc::MISSING_ERRORS_DOC), LintId::of(&doc::MISSING_ERRORS_DOC),
LintId::of(&doc::MISSING_PANICS_DOC),
LintId::of(&empty_enum::EMPTY_ENUM), LintId::of(&empty_enum::EMPTY_ENUM),
LintId::of(&enum_variants::MODULE_NAME_REPETITIONS), LintId::of(&enum_variants::MODULE_NAME_REPETITIONS),
LintId::of(&enum_variants::PUB_ENUM_VARIANT_NAMES), LintId::of(&enum_variants::PUB_ENUM_VARIANT_NAMES),

View file

@ -1592,7 +1592,17 @@ where
} }
}, },
(&Kind::End(a, _), &Kind::Start(b, _)) if a != Bound::Included(b) => (), (&Kind::End(a, _), &Kind::Start(b, _)) if a != Bound::Included(b) => (),
_ => return Some((a.range(), b.range())), _ => {
// skip if the range `a` is completely included into the range `b`
if let Ordering::Equal | Ordering::Less = a.cmp(&b) {
let kind_a = Kind::End(a.range().node.1, a.range());
let kind_b = Kind::End(b.range().node.1, b.range());
if let Ordering::Equal | Ordering::Greater = kind_a.cmp(&kind_b) {
return None;
}
}
return Some((a.range(), b.range()));
},
} }
} }

View file

@ -247,7 +247,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
(ForeignMod(l), ForeignMod(r)) => { (ForeignMod(l), ForeignMod(r)) => {
both(&l.abi, &r.abi, |l, r| eq_str_lit(l, r)) both(&l.abi, &r.abi, |l, r| eq_str_lit(l, r))
&& over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind)) && over(&l.items, &r.items, |l, r| eq_item(l, r, eq_foreign_item_kind))
} },
(TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => { (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
eq_defaultness(*ld, *rd) eq_defaultness(*ld, *rd)
&& eq_generics(lg, rg) && eq_generics(lg, rg)
@ -259,7 +259,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
}, },
(Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => { (Struct(lv, lg), Struct(rv, rg)) | (Union(lv, lg), Union(rv, rg)) => {
eq_variant_data(lv, rv) && eq_generics(lg, rg) eq_variant_data(lv, rv) && eq_generics(lg, rg)
} },
(Trait(box TraitKind(la, lu, lg, lb, li)), Trait(box TraitKind(ra, ru, rg, rb, ri))) => { (Trait(box TraitKind(la, lu, lg, lb, li)), Trait(box TraitKind(ra, ru, rg, rb, ri))) => {
la == ra la == ra
&& matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No) && matches!(lu, Unsafe::No) == matches!(ru, Unsafe::No)
@ -331,15 +331,10 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool { pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
use AssocItemKind::*; use AssocItemKind::*;
match (l, r) { match (l, r) {
(Const(ld, lt, le), Const(rd, rt, re)) => { (Const(ld, lt, le), Const(rd, rt, re)) => eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re),
eq_defaultness(*ld, *rd) && eq_ty(lt, rt) && eq_expr_opt(le, re)
}
(Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => { (Fn(box FnKind(ld, lf, lg, lb)), Fn(box FnKind(rd, rf, rg, rb))) => {
eq_defaultness(*ld, *rd) eq_defaultness(*ld, *rd) && eq_fn_sig(lf, rf) && eq_generics(lg, rg) && both(lb, rb, |l, r| eq_block(l, r))
&& eq_fn_sig(lf, rf) },
&& eq_generics(lg, rg)
&& both(lb, rb, |l, r| eq_block(l, r))
}
(TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => { (TyAlias(box TyAliasKind(ld, lg, lb, lt)), TyAlias(box TyAliasKind(rd, rg, rb, rt))) => {
eq_defaultness(*ld, *rd) eq_defaultness(*ld, *rd)
&& eq_generics(lg, rg) && eq_generics(lg, rg)

View file

@ -110,7 +110,7 @@ pub fn span_lint_and_help<'a, T: LintContext>(
pub fn span_lint_and_note<'a, T: LintContext>( pub fn span_lint_and_note<'a, T: LintContext>(
cx: &'a T, cx: &'a T,
lint: &'static Lint, lint: &'static Lint,
span: Span, span: impl Into<MultiSpan>,
msg: &str, msg: &str,
note_span: Option<Span>, note_span: Option<Span>,
note: &str, note: &str,

View file

@ -760,7 +760,7 @@ impl<'tcx> LateLintPass<'tcx> for MatchTypeOnDiagItem {
// Extract the path to the matched type // Extract the path to the matched type
if let Some(segments) = path_to_matched_type(cx, ty_path); if let Some(segments) = path_to_matched_type(cx, ty_path);
let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect(); let segments: Vec<&str> = segments.iter().map(|sym| &**sym).collect();
if let Some(ty_did) = path_to_res(cx, &segments[..]).and_then(|res| res.opt_def_id()); if let Some(ty_did) = path_to_res(cx, &segments[..]).opt_def_id();
// Check if the matched type is a diagnostic item // Check if the matched type is a diagnostic item
let diag_items = cx.tcx.diagnostic_items(ty_did.krate); let diag_items = cx.tcx.diagnostic_items(ty_did.krate);
if let Some(item_name) = diag_items.iter().find_map(|(k, v)| if *v == ty_did { Some(k) } else { None }); if let Some(item_name) = diag_items.iter().find_map(|(k, v)| if *v == ty_did { Some(k) } else { None });
@ -833,7 +833,7 @@ fn path_to_matched_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<Ve
// This is not a complete resolver for paths. It works on all the paths currently used in the paths // This is not a complete resolver for paths. It works on all the paths currently used in the paths
// module. That's all it does and all it needs to do. // module. That's all it does and all it needs to do.
pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool { pub fn check_path(cx: &LateContext<'_>, path: &[&str]) -> bool {
if path_to_res(cx, path).is_some() { if path_to_res(cx, path) != Res::Err {
return true; return true;
} }
@ -906,7 +906,7 @@ impl<'tcx> LateLintPass<'tcx> for InterningDefinedSymbol {
} }
for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] { for &module in &[&paths::KW_MODULE, &paths::SYM_MODULE] {
if let Some(Res::Def(_, def_id)) = path_to_res(cx, module) { if let Some(def_id) = path_to_res(cx, module).opt_def_id() {
for item in cx.tcx.item_children(def_id).iter() { for item in cx.tcx.item_children(def_id).iter() {
if_chain! { if_chain! {
if let Res::Def(DefKind::Const, item_def_id) = item.res; if let Res::Def(DefKind::Const, item_def_id) = item.res;

View file

@ -309,7 +309,15 @@ pub fn match_path_ast(path: &ast::Path, segments: &[&str]) -> bool {
/// Gets the definition associated to a path. /// Gets the definition associated to a path.
#[allow(clippy::shadow_unrelated)] // false positive #6563 #[allow(clippy::shadow_unrelated)] // false positive #6563
pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option<Res> { pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
macro_rules! try_res {
($e:expr) => {
match $e {
Some(e) => e,
None => return Res::Err,
}
};
}
fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export<HirId>> { fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export<HirId>> {
tcx.item_children(def_id) tcx.item_children(def_id)
.iter() .iter()
@ -318,12 +326,12 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option<Res> {
let (krate, first, path) = match *path { let (krate, first, path) = match *path {
[krate, first, ref path @ ..] => (krate, first, path), [krate, first, ref path @ ..] => (krate, first, path),
_ => return None, _ => return Res::Err,
}; };
let tcx = cx.tcx; let tcx = cx.tcx;
let crates = tcx.crates(); let crates = tcx.crates();
let krate = crates.iter().find(|&&num| tcx.crate_name(num).as_str() == krate)?; let krate = try_res!(crates.iter().find(|&&num| tcx.crate_name(num).as_str() == krate));
let first = item_child_by_name(tcx, krate.as_def_id(), first)?; let first = try_res!(item_child_by_name(tcx, krate.as_def_id(), first));
let last = path let last = path
.iter() .iter()
.copied() .copied()
@ -343,21 +351,15 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Option<Res> {
} else { } else {
None None
} }
})?; });
Some(last.res) try_res!(last).res
} }
/// Convenience function to get the `DefId` of a trait by path. /// Convenience function to get the `DefId` of a trait by path.
/// It could be a trait or trait alias. /// It could be a trait or trait alias.
pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> { pub fn get_trait_def_id(cx: &LateContext<'_>, path: &[&str]) -> Option<DefId> {
let res = match path_to_res(cx, path) { match path_to_res(cx, path) {
Some(res) => res,
None => return None,
};
match res {
Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id), Res::Def(DefKind::Trait | DefKind::TraitAlias, trait_id) => Some(trait_id),
Res::Err => unreachable!("this trait resolution is impossible: {:?}", &path),
_ => None, _ => None,
} }
} }
@ -1532,10 +1534,11 @@ pub fn fn_def_id(cx: &LateContext<'_>, expr: &Expr<'_>) -> Option<DefId> {
ExprKind::Call( ExprKind::Call(
Expr { Expr {
kind: ExprKind::Path(qpath), kind: ExprKind::Path(qpath),
hir_id: path_hir_id,
.. ..
}, },
.., ..,
) => cx.typeck_results().qpath_res(qpath, expr.hir_id).opt_def_id(), ) => cx.typeck_results().qpath_res(qpath, *path_hir_id).opt_def_id(),
_ => None, _ => None,
} }
} }

View file

@ -233,7 +233,11 @@ impl_lint_pass!(Write => [
impl EarlyLintPass for Write { impl EarlyLintPass for Write {
fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) { fn check_item(&mut self, _: &EarlyContext<'_>, item: &Item) {
if let ItemKind::Impl(box ImplKind { of_trait: Some(trait_ref), .. }) = &item.kind { if let ItemKind::Impl(box ImplKind {
of_trait: Some(trait_ref),
..
}) = &item.kind
{
let trait_name = trait_ref let trait_name = trait_ref
.path .path
.segments .segments

View file

@ -581,15 +581,15 @@ in the following steps:
3. Passing the configuration value to the lint impl struct: 3. Passing the configuration value to the lint impl struct:
First find the struct construction in the [clippy_lints lib file](/clippy_lints/src/lib.rs). First find the struct construction in the [clippy_lints lib file](/clippy_lints/src/lib.rs).
Make sure that `clippy dev update_lints` added it beforehand. The configuration value is now The configuration value is now cloned or copied into a local value that is then passed to the
cloned or copied into a local value that is then passed to the impl struct like this: impl struct like this:
```rust ```rust
// Default generated registration: // Default generated registration:
store.register_late_pass(|| box module::StructName); store.register_*_pass(|| box module::StructName);
// New registration with configuration value // New registration with configuration value
let configuration_ident = conf.configuration_ident.clone(); let configuration_ident = conf.configuration_ident.clone();
store.register_late_pass(move || box module::StructName::new(configuration_ident)); store.register_*_pass(move || box module::StructName::new(configuration_ident));
``` ```
Congratulations the work is almost done. The configuration value can now be accessed Congratulations the work is almost done. The configuration value can now be accessed
@ -599,7 +599,7 @@ in the following steps:
1. The default configured value can be tested like any normal lint in [`tests/ui`](/tests/ui). 1. The default configured value can be tested like any normal lint in [`tests/ui`](/tests/ui).
2. The configuration itself will be tested separately in [`tests/ui-toml`](/tests/ui-toml). 2. The configuration itself will be tested separately in [`tests/ui-toml`](/tests/ui-toml).
Simply add a new subfolder with a fitting name. This folder contains a `clippy.toml` file Simply add a new subfolder with a fitting name. This folder contains a `clippy.toml` file
with the configuration value and a rust file that should be linted by clippy. The test can with the configuration value and a rust file that should be linted by Clippy. The test can
otherwise be written as usual. otherwise be written as usual.
## Cheatsheet ## Cheatsheet

View file

@ -109,7 +109,7 @@ See <https://rustc-dev-guide.rust-lang.org/contributing.html#opening-a-pr>.
| HIR | High-Level Intermediate Representation | | HIR | High-Level Intermediate Representation |
| TCX | Type context | | TCX | Type context |
This is a concise list of abbreviations that can come up during clippy development. An extensive This is a concise list of abbreviations that can come up during Clippy development. An extensive
general list can be found in the [rustc-dev-guide glossary][glossary]. Always feel free to ask if general list can be found in the [rustc-dev-guide glossary][glossary]. Always feel free to ask if
an abbreviation or meaning is unclear to you. an abbreviation or meaning is unclear to you.

View file

@ -7,6 +7,9 @@ extern crate proc_macro;
use proc_macro::{quote, TokenStream}; use proc_macro::{quote, TokenStream};
#[proc_macro_derive(ClippyMiniMacroTest)] #[proc_macro_derive(ClippyMiniMacroTest)]
/// # Panics
///
/// Panics if the macro derivation fails
pub fn mini_macro(_: TokenStream) -> TokenStream { pub fn mini_macro(_: TokenStream) -> TokenStream {
quote!( quote!(
#[allow(unused)] #[allow(unused)]

View file

@ -1,3 +1,3 @@
[toolchain] [toolchain]
channel = "nightly-2021-01-30" channel = "nightly-2021-02-03"
components = ["llvm-tools-preview", "rustc-dev", "rust-src", "rustfmt"] components = ["llvm-tools-preview", "rustc-dev", "rust-src", "rustfmt"]

95
tests/ui/doc_panics.rs Normal file
View file

@ -0,0 +1,95 @@
#![warn(clippy::missing_panics_doc)]
#![allow(clippy::option_map_unit_fn)]
fn main() {}
/// This needs to be documented
pub fn unwrap() {
let result = Err("Hi");
result.unwrap()
}
/// This needs to be documented
pub fn panic() {
panic!("This function panics")
}
/// This needs to be documented
pub fn todo() {
todo!()
}
/// This needs to be documented
pub fn inner_body(opt: Option<u32>) {
opt.map(|x| {
if x == 10 {
panic!()
}
});
}
/// This is documented
///
/// # Panics
///
/// Panics if `result` if an error
pub fn unwrap_documented() {
let result = Err("Hi");
result.unwrap()
}
/// This is documented
///
/// # Panics
///
/// Panics just because
pub fn panic_documented() {
panic!("This function panics")
}
/// This is documented
///
/// # Panics
///
/// Panics if `opt` is Just(10)
pub fn inner_body_documented(opt: Option<u32>) {
opt.map(|x| {
if x == 10 {
panic!()
}
});
}
/// This is documented
///
/// # Panics
///
/// We still need to do this part
pub fn todo_documented() {
todo!()
}
/// This is okay because it is private
fn unwrap_private() {
let result = Err("Hi");
result.unwrap()
}
/// This is okay because it is private
fn panic_private() {
panic!("This function panics")
}
/// This is okay because it is private
fn todo_private() {
todo!()
}
/// This is okay because it is private
fn inner_body_private(opt: Option<u32>) {
opt.map(|x| {
if x == 10 {
panic!()
}
});
}

View file

@ -0,0 +1,67 @@
error: docs for function which may panic missing `# Panics` section
--> $DIR/doc_panics.rs:7:1
|
LL | / pub fn unwrap() {
LL | | let result = Err("Hi");
LL | | result.unwrap()
LL | | }
| |_^
|
= note: `-D clippy::missing-panics-doc` implied by `-D warnings`
note: first possible panic found here
--> $DIR/doc_panics.rs:9:5
|
LL | result.unwrap()
| ^^^^^^^^^^^^^^^
error: docs for function which may panic missing `# Panics` section
--> $DIR/doc_panics.rs:13:1
|
LL | / pub fn panic() {
LL | | panic!("This function panics")
LL | | }
| |_^
|
note: first possible panic found here
--> $DIR/doc_panics.rs:14:5
|
LL | panic!("This function panics")
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: docs for function which may panic missing `# Panics` section
--> $DIR/doc_panics.rs:18:1
|
LL | / pub fn todo() {
LL | | todo!()
LL | | }
| |_^
|
note: first possible panic found here
--> $DIR/doc_panics.rs:19:5
|
LL | todo!()
| ^^^^^^^
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: docs for function which may panic missing `# Panics` section
--> $DIR/doc_panics.rs:23:1
|
LL | / pub fn inner_body(opt: Option<u32>) {
LL | | opt.map(|x| {
LL | | if x == 10 {
LL | | panic!()
LL | | }
LL | | });
LL | | }
| |_^
|
note: first possible panic found here
--> $DIR/doc_panics.rs:26:13
|
LL | panic!()
| ^^^^^^^^
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
error: aborting due to 4 previous errors

View file

@ -56,27 +56,36 @@ pub mod enums {
pub mod structs { pub mod structs {
#[non_exhaustive] #[non_exhaustive]
pub struct Exhaustive { pub struct Exhaustive {
foo: u8, pub foo: u8,
bar: String, pub bar: String,
} }
// no warning, already non_exhaustive // no warning, already non_exhaustive
#[non_exhaustive] #[non_exhaustive]
pub struct NonExhaustive { pub struct NonExhaustive {
foo: u8, pub foo: u8,
pub bar: String,
}
// no warning, private fields
pub struct ExhaustivePrivateFieldTuple(u8);
// no warning, private fields
pub struct ExhaustivePrivateField {
pub foo: u8,
bar: String, bar: String,
} }
// no warning, private // no warning, private
struct ExhaustivePrivate { struct ExhaustivePrivate {
foo: u8, pub foo: u8,
bar: String, pub bar: String,
} }
// no warning, private // no warning, private
#[non_exhaustive] #[non_exhaustive]
struct NonExhaustivePrivate { struct NonExhaustivePrivate {
foo: u8, pub foo: u8,
bar: String, pub bar: String,
} }
} }

View file

@ -53,27 +53,36 @@ pub mod enums {
pub mod structs { pub mod structs {
pub struct Exhaustive { pub struct Exhaustive {
foo: u8, pub foo: u8,
bar: String, pub bar: String,
} }
// no warning, already non_exhaustive // no warning, already non_exhaustive
#[non_exhaustive] #[non_exhaustive]
pub struct NonExhaustive { pub struct NonExhaustive {
foo: u8, pub foo: u8,
pub bar: String,
}
// no warning, private fields
pub struct ExhaustivePrivateFieldTuple(u8);
// no warning, private fields
pub struct ExhaustivePrivateField {
pub foo: u8,
bar: String, bar: String,
} }
// no warning, private // no warning, private
struct ExhaustivePrivate { struct ExhaustivePrivate {
foo: u8, pub foo: u8,
bar: String, pub bar: String,
} }
// no warning, private // no warning, private
#[non_exhaustive] #[non_exhaustive]
struct NonExhaustivePrivate { struct NonExhaustivePrivate {
foo: u8, pub foo: u8,
bar: String, pub bar: String,
} }
} }

View file

@ -41,8 +41,8 @@ error: exported structs should not be exhaustive
--> $DIR/exhaustive_items.rs:55:5 --> $DIR/exhaustive_items.rs:55:5
| |
LL | / pub struct Exhaustive { LL | / pub struct Exhaustive {
LL | | foo: u8, LL | | pub foo: u8,
LL | | bar: String, LL | | pub bar: String,
LL | | } LL | | }
| |_____^ | |_____^
| |

View file

@ -117,7 +117,11 @@ mod no_lint_if_stmt_borrows {
fn drop(&mut self) {} fn drop(&mut self) {}
} }
impl Foo<'_> { impl<'a> Foo<'a> {
fn new(inner: &'a Inner) -> Self {
Self { inner }
}
fn value(&self) -> i32 { fn value(&self) -> i32 {
42 42
} }
@ -132,6 +136,12 @@ mod no_lint_if_stmt_borrows {
let value = some_foo(&x).value(); let value = some_foo(&x).value();
value value
} }
fn test2() -> i32 {
let x = Inner {};
let value = Foo::new(&x).value();
value
}
} }
} }

View file

@ -28,7 +28,7 @@ LL | 5
| |
error: returning the result of a `let` binding from a block error: returning the result of a `let` binding from a block
--> $DIR/let_and_return.rs:154:13 --> $DIR/let_and_return.rs:164:13
| |
LL | let clone = Arc::clone(&self.foo); LL | let clone = Arc::clone(&self.foo);
| ---------------------------------- unnecessary `let` binding | ---------------------------------- unnecessary `let` binding

View file

@ -57,6 +57,36 @@ fn overlapping() {
_ => (), _ => (),
} }
match 42 {
5..7 => println!("5 .. 7"),
0..10 => println!("0 .. 10"),
_ => (),
}
match 42 {
5..10 => println!("5 .. 10"),
0..=10 => println!("0 ... 10"),
_ => (),
}
match 42 {
0..14 => println!("0 .. 14"),
5..10 => println!("5 .. 10"),
_ => (),
}
match 42 {
5..14 => println!("5 .. 14"),
0..=10 => println!("0 ... 10"),
_ => (),
}
match 42 {
0..7 => println!("0 .. 7"),
0..=10 => println!("0 ... 10"),
_ => (),
}
/* /*
// FIXME(JohnTitor): uncomment this once rustfmt knows half-open patterns // FIXME(JohnTitor): uncomment this once rustfmt knows half-open patterns
match 42 { match 42 {

View file

@ -23,30 +23,6 @@ note: overlaps with this
LL | FOO..=11 => println!("0 ... 11"), LL | FOO..=11 => println!("0 ... 11"),
| ^^^^^^^^ | ^^^^^^^^
error: some ranges overlap
--> $DIR/match_overlapping_arm.rs:26:9
|
LL | 0..=5 => println!("0 ... 5"),
| ^^^^^
|
note: overlaps with this
--> $DIR/match_overlapping_arm.rs:25:9
|
LL | 2 => println!("2"),
| ^
error: some ranges overlap
--> $DIR/match_overlapping_arm.rs:32:9
|
LL | 0..=2 => println!("0 ... 2"),
| ^^^^^
|
note: overlaps with this
--> $DIR/match_overlapping_arm.rs:31:9
|
LL | 2 => println!("2"),
| ^
error: some ranges overlap error: some ranges overlap
--> $DIR/match_overlapping_arm.rs:55:9 --> $DIR/match_overlapping_arm.rs:55:9
| |
@ -59,5 +35,29 @@ note: overlaps with this
LL | 0..=11 => println!("0 ... 11"), LL | 0..=11 => println!("0 ... 11"),
| ^^^^^^ | ^^^^^^
error: some ranges overlap
--> $DIR/match_overlapping_arm.rs:80:9
|
LL | 0..=10 => println!("0 ... 10"),
| ^^^^^^
|
note: overlaps with this
--> $DIR/match_overlapping_arm.rs:79:9
|
LL | 5..14 => println!("5 .. 14"),
| ^^^^^
error: some ranges overlap
--> $DIR/match_overlapping_arm.rs:85:9
|
LL | 0..7 => println!("0 .. 7"),
| ^^^^
|
note: overlaps with this
--> $DIR/match_overlapping_arm.rs:86:9
|
LL | 0..=10 => println!("0 ... 10"),
| ^^^^^^
error: aborting due to 5 previous errors error: aborting due to 5 previous errors

View file

@ -8,7 +8,8 @@
clippy::unused_self, clippy::unused_self,
clippy::needless_lifetimes, clippy::needless_lifetimes,
clippy::missing_safety_doc, clippy::missing_safety_doc,
clippy::wrong_self_convention clippy::wrong_self_convention,
clippy::missing_panics_doc
)] )]
use std::ops::Mul; use std::ops::Mul;

View file

@ -8,7 +8,8 @@
clippy::unused_self, clippy::unused_self,
clippy::needless_lifetimes, clippy::needless_lifetimes,
clippy::missing_safety_doc, clippy::missing_safety_doc,
clippy::wrong_self_convention clippy::wrong_self_convention,
clippy::missing_panics_doc
)] )]
use std::ops::Mul; use std::ops::Mul;

View file

@ -1,5 +1,5 @@
error: method `add` can be confused for the standard trait method `std::ops::Add::add` error: method `add` can be confused for the standard trait method `std::ops::Add::add`
--> $DIR/method_list_1.rs:25:5 --> $DIR/method_list_1.rs:26:5
| |
LL | / pub fn add(self, other: T) -> T { LL | / pub fn add(self, other: T) -> T {
LL | | unimplemented!() LL | | unimplemented!()
@ -10,7 +10,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Add` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Add` or choosing a less ambiguous method name
error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut` error: method `as_mut` can be confused for the standard trait method `std::convert::AsMut::as_mut`
--> $DIR/method_list_1.rs:29:5 --> $DIR/method_list_1.rs:30:5
| |
LL | / pub fn as_mut(&mut self) -> &mut T { LL | / pub fn as_mut(&mut self) -> &mut T {
LL | | unimplemented!() LL | | unimplemented!()
@ -20,7 +20,7 @@ LL | | }
= help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name = help: consider implementing the trait `std::convert::AsMut` or choosing a less ambiguous method name
error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref` error: method `as_ref` can be confused for the standard trait method `std::convert::AsRef::as_ref`
--> $DIR/method_list_1.rs:33:5 --> $DIR/method_list_1.rs:34:5
| |
LL | / pub fn as_ref(&self) -> &T { LL | / pub fn as_ref(&self) -> &T {
LL | | unimplemented!() LL | | unimplemented!()
@ -30,7 +30,7 @@ LL | | }
= help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name = help: consider implementing the trait `std::convert::AsRef` or choosing a less ambiguous method name
error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand` error: method `bitand` can be confused for the standard trait method `std::ops::BitAnd::bitand`
--> $DIR/method_list_1.rs:37:5 --> $DIR/method_list_1.rs:38:5
| |
LL | / pub fn bitand(self, rhs: T) -> T { LL | / pub fn bitand(self, rhs: T) -> T {
LL | | unimplemented!() LL | | unimplemented!()
@ -40,7 +40,7 @@ LL | | }
= help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::BitAnd` or choosing a less ambiguous method name
error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor` error: method `bitor` can be confused for the standard trait method `std::ops::BitOr::bitor`
--> $DIR/method_list_1.rs:41:5 --> $DIR/method_list_1.rs:42:5
| |
LL | / pub fn bitor(self, rhs: Self) -> Self { LL | / pub fn bitor(self, rhs: Self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -50,7 +50,7 @@ LL | | }
= help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::BitOr` or choosing a less ambiguous method name
error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor` error: method `bitxor` can be confused for the standard trait method `std::ops::BitXor::bitxor`
--> $DIR/method_list_1.rs:45:5 --> $DIR/method_list_1.rs:46:5
| |
LL | / pub fn bitxor(self, rhs: Self) -> Self { LL | / pub fn bitxor(self, rhs: Self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -60,7 +60,7 @@ LL | | }
= help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::BitXor` or choosing a less ambiguous method name
error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow` error: method `borrow` can be confused for the standard trait method `std::borrow::Borrow::borrow`
--> $DIR/method_list_1.rs:49:5 --> $DIR/method_list_1.rs:50:5
| |
LL | / pub fn borrow(&self) -> &str { LL | / pub fn borrow(&self) -> &str {
LL | | unimplemented!() LL | | unimplemented!()
@ -70,7 +70,7 @@ LL | | }
= help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name = help: consider implementing the trait `std::borrow::Borrow` or choosing a less ambiguous method name
error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut` error: method `borrow_mut` can be confused for the standard trait method `std::borrow::BorrowMut::borrow_mut`
--> $DIR/method_list_1.rs:53:5 --> $DIR/method_list_1.rs:54:5
| |
LL | / pub fn borrow_mut(&mut self) -> &mut str { LL | / pub fn borrow_mut(&mut self) -> &mut str {
LL | | unimplemented!() LL | | unimplemented!()
@ -80,7 +80,7 @@ LL | | }
= help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name = help: consider implementing the trait `std::borrow::BorrowMut` or choosing a less ambiguous method name
error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone` error: method `clone` can be confused for the standard trait method `std::clone::Clone::clone`
--> $DIR/method_list_1.rs:57:5 --> $DIR/method_list_1.rs:58:5
| |
LL | / pub fn clone(&self) -> Self { LL | / pub fn clone(&self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -90,7 +90,7 @@ LL | | }
= help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name = help: consider implementing the trait `std::clone::Clone` or choosing a less ambiguous method name
error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp` error: method `cmp` can be confused for the standard trait method `std::cmp::Ord::cmp`
--> $DIR/method_list_1.rs:61:5 --> $DIR/method_list_1.rs:62:5
| |
LL | / pub fn cmp(&self, other: &Self) -> Self { LL | / pub fn cmp(&self, other: &Self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -100,7 +100,7 @@ LL | | }
= help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name = help: consider implementing the trait `std::cmp::Ord` or choosing a less ambiguous method name
error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref` error: method `deref` can be confused for the standard trait method `std::ops::Deref::deref`
--> $DIR/method_list_1.rs:69:5 --> $DIR/method_list_1.rs:70:5
| |
LL | / pub fn deref(&self) -> &Self { LL | / pub fn deref(&self) -> &Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -110,7 +110,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Deref` or choosing a less ambiguous method name
error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut` error: method `deref_mut` can be confused for the standard trait method `std::ops::DerefMut::deref_mut`
--> $DIR/method_list_1.rs:73:5 --> $DIR/method_list_1.rs:74:5
| |
LL | / pub fn deref_mut(&mut self) -> &mut Self { LL | / pub fn deref_mut(&mut self) -> &mut Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -120,7 +120,7 @@ LL | | }
= help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::DerefMut` or choosing a less ambiguous method name
error: method `div` can be confused for the standard trait method `std::ops::Div::div` error: method `div` can be confused for the standard trait method `std::ops::Div::div`
--> $DIR/method_list_1.rs:77:5 --> $DIR/method_list_1.rs:78:5
| |
LL | / pub fn div(self, rhs: Self) -> Self { LL | / pub fn div(self, rhs: Self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -130,7 +130,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Div` or choosing a less ambiguous method name
error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop` error: method `drop` can be confused for the standard trait method `std::ops::Drop::drop`
--> $DIR/method_list_1.rs:81:5 --> $DIR/method_list_1.rs:82:5
| |
LL | / pub fn drop(&mut self) { LL | / pub fn drop(&mut self) {
LL | | unimplemented!() LL | | unimplemented!()

View file

@ -8,7 +8,8 @@
clippy::unused_self, clippy::unused_self,
clippy::needless_lifetimes, clippy::needless_lifetimes,
clippy::missing_safety_doc, clippy::missing_safety_doc,
clippy::wrong_self_convention clippy::wrong_self_convention,
clippy::missing_panics_doc
)] )]
use std::ops::Mul; use std::ops::Mul;

View file

@ -1,5 +1,5 @@
error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq` error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq`
--> $DIR/method_list_2.rs:26:5 --> $DIR/method_list_2.rs:27:5
| |
LL | / pub fn eq(&self, other: &Self) -> bool { LL | / pub fn eq(&self, other: &Self) -> bool {
LL | | unimplemented!() LL | | unimplemented!()
@ -10,7 +10,7 @@ LL | | }
= help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name = help: consider implementing the trait `std::cmp::PartialEq` or choosing a less ambiguous method name
error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter` error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter`
--> $DIR/method_list_2.rs:30:5 --> $DIR/method_list_2.rs:31:5
| |
LL | / pub fn from_iter<T>(iter: T) -> Self { LL | / pub fn from_iter<T>(iter: T) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -20,7 +20,7 @@ LL | | }
= help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name
error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str`
--> $DIR/method_list_2.rs:34:5 --> $DIR/method_list_2.rs:35:5
| |
LL | / pub fn from_str(s: &str) -> Result<Self, Self> { LL | / pub fn from_str(s: &str) -> Result<Self, Self> {
LL | | unimplemented!() LL | | unimplemented!()
@ -30,7 +30,7 @@ LL | | }
= help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name
error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash` error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash`
--> $DIR/method_list_2.rs:38:5 --> $DIR/method_list_2.rs:39:5
| |
LL | / pub fn hash(&self, state: &mut T) { LL | / pub fn hash(&self, state: &mut T) {
LL | | unimplemented!() LL | | unimplemented!()
@ -40,7 +40,7 @@ LL | | }
= help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name
error: method `index` can be confused for the standard trait method `std::ops::Index::index` error: method `index` can be confused for the standard trait method `std::ops::Index::index`
--> $DIR/method_list_2.rs:42:5 --> $DIR/method_list_2.rs:43:5
| |
LL | / pub fn index(&self, index: usize) -> &Self { LL | / pub fn index(&self, index: usize) -> &Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -50,7 +50,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name
error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut` error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut`
--> $DIR/method_list_2.rs:46:5 --> $DIR/method_list_2.rs:47:5
| |
LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self { LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -60,7 +60,7 @@ LL | | }
= help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name
error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter` error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter`
--> $DIR/method_list_2.rs:50:5 --> $DIR/method_list_2.rs:51:5
| |
LL | / pub fn into_iter(self) -> Self { LL | / pub fn into_iter(self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -70,7 +70,7 @@ LL | | }
= help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name
error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul` error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul`
--> $DIR/method_list_2.rs:54:5 --> $DIR/method_list_2.rs:55:5
| |
LL | / pub fn mul(self, rhs: Self) -> Self { LL | / pub fn mul(self, rhs: Self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -80,7 +80,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name
error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg` error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg`
--> $DIR/method_list_2.rs:58:5 --> $DIR/method_list_2.rs:59:5
| |
LL | / pub fn neg(self) -> Self { LL | / pub fn neg(self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -90,7 +90,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name
error: method `next` can be confused for the standard trait method `std::iter::Iterator::next` error: method `next` can be confused for the standard trait method `std::iter::Iterator::next`
--> $DIR/method_list_2.rs:62:5 --> $DIR/method_list_2.rs:63:5
| |
LL | / pub fn next(&mut self) -> Option<Self> { LL | / pub fn next(&mut self) -> Option<Self> {
LL | | unimplemented!() LL | | unimplemented!()
@ -100,7 +100,7 @@ LL | | }
= help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name
error: method `not` can be confused for the standard trait method `std::ops::Not::not` error: method `not` can be confused for the standard trait method `std::ops::Not::not`
--> $DIR/method_list_2.rs:66:5 --> $DIR/method_list_2.rs:67:5
| |
LL | / pub fn not(self) -> Self { LL | / pub fn not(self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -110,7 +110,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name
error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem` error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem`
--> $DIR/method_list_2.rs:70:5 --> $DIR/method_list_2.rs:71:5
| |
LL | / pub fn rem(self, rhs: Self) -> Self { LL | / pub fn rem(self, rhs: Self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -120,7 +120,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name
error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl` error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl`
--> $DIR/method_list_2.rs:74:5 --> $DIR/method_list_2.rs:75:5
| |
LL | / pub fn shl(self, rhs: Self) -> Self { LL | / pub fn shl(self, rhs: Self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -130,7 +130,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name
error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr` error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr`
--> $DIR/method_list_2.rs:78:5 --> $DIR/method_list_2.rs:79:5
| |
LL | / pub fn shr(self, rhs: Self) -> Self { LL | / pub fn shr(self, rhs: Self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()
@ -140,7 +140,7 @@ LL | | }
= help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name
error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub` error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub`
--> $DIR/method_list_2.rs:82:5 --> $DIR/method_list_2.rs:83:5
| |
LL | / pub fn sub(self, rhs: Self) -> Self { LL | / pub fn sub(self, rhs: Self) -> Self {
LL | | unimplemented!() LL | | unimplemented!()