Skip to content

Update clippy #81692

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 31 commits into from
Feb 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
70704db
Do not lint when range is completely included into another one
ThibsG Jan 15, 2021
0518911
Add more tests for `match_overlapping_arm` lint
ThibsG Jan 24, 2021
69f2b8f
Updated some NITs in the documentation from #6630
xFrednet Jan 25, 2021
52fabbf
Added the rustbot claim command to the contribution guide.
xFrednet Jan 26, 2021
7f1595e
Fix let_and_return false positive
phlip9 Jan 30, 2021
ac912be
Merge commit '95c0459217d1661edfa794c8bb122452b92fb485' into clippyup
flip1995 Jan 30, 2021
3a0ae08
Update clippy test output for panic macros.
m-ou-se Jan 30, 2021
da26b21
clippy_dev: Pass stderr to CommandFailed
phansch Jan 31, 2021
ed11274
Auto merge of #6656 - phansch:command-failed-print-stderr, r=flip1995
bors Jan 31, 2021
c5f3f9d
Auto merge of #6603 - ThibsG:MatchOverlappingArm5986, r=flip1995
bors Jan 31, 2021
939136d
Remove Option from path_to_res return type
camsteffen Jan 25, 2021
6fd01e0
Box the biggest ast::ItemKind variants
bugadani Jan 29, 2021
9607b5c
Auto merge of #80851 - m-ou-se:panic-2021, r=petrochenkov
bors Feb 1, 2021
0fb09d6
exhaustive_structs: don't trigger for structs with private fields
Manishearth Feb 2, 2021
4a13c8c
Fix test formatting
flip1995 Feb 2, 2021
8d82ac5
Auto merge of #6661 - Manishearth:exhaustive-fix, r=flip1995
bors Feb 2, 2021
f870876
Auto merge of #6659 - phlip9:let_and_return_fix, r=phansch
bors Feb 2, 2021
bde667a
Add missing_panics_doc lint
brightly-salty Dec 30, 2020
28794e9
Auto merge of #6523 - brightly-salty:missing-panic-doc, r=flip1995
bors Feb 2, 2021
9fd4f3e
Auto merge of #6664 - camsteffen:path-to-res, r=Manishearth
bors Feb 2, 2021
e05e477
Add .editorconfig
vn971 Jan 22, 2021
448a97b
Auto merge of #81405 - bugadani:ast, r=cjgillot
bors Feb 2, 2021
a2d2aee
Updated the list of active mentors
xFrednet Feb 2, 2021
11edf92
Auto merge of #6639 - xFrednet:0000-configuration-documentation-some-…
bors Feb 2, 2021
b56b751
Rollup merge of #81260 - vn971:restore-editorconfig, r=Mark-Simulacrum
jackh726 Feb 2, 2021
5c957b8
Merge remote-tracking branch 'origin/master' into rustup
Manishearth Feb 3, 2021
6fb1075
Rustup
Manishearth Feb 3, 2021
a31e5f5
Run rustfmt
Manishearth Feb 3, 2021
741259b
Merge branch 'sync-from-rust3' into rustup
Manishearth Feb 3, 2021
3e41797
Auto merge of #6667 - Manishearth:rustup, r=Manishearth
bors Feb 3, 2021
5889312
Merge commit '3e4179766bcecd712824da04356621b8df012ea4' into sync-fro…
Manishearth Feb 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/tools/clippy/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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_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_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
[`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
Expand Down
9 changes: 5 additions & 4 deletions src/tools/clippy/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@ first read the [Basics docs](doc/basics.md).**

### Finding something to fix/improve

All issues on Clippy are mentored, if you want help with a bug just ask
@Manishearth, @flip1995, @phansch or @yaahc.
All issues on Clippy are mentored, if you want help simply ask @Manishearth, @flip1995, @phansch
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.
If you want to work on an issue, please leave a comment so that we can assign it to you!
Some issues are easier than others. The [`good-first-issue`] label can be used to find the easy
issues. You can use `@rustbot claim` to assign the issue to yourself.

There are also some abandoned PRs, marked with [`S-inactive-closed`].
Pretty often these PRs are nearly completed and just need some extra steps
Expand Down
3 changes: 3 additions & 0 deletions src/tools/clippy/clippy_dev/src/bless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ static CLIPPY_BUILD_TIME: SyncLazy<Option<std::time::SystemTime>> = SyncLazy::ne
fs::metadata(path).ok()?.modified().ok()
});

/// # Panics
///
/// Panics if the path to a test file is broken
pub fn bless(ignore_timestamp: bool) {
let test_suite_dirs = [
clippy_project_root().join("tests").join("ui"),
Expand Down
23 changes: 15 additions & 8 deletions src/tools/clippy/clippy_dev/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use walkdir::WalkDir;

#[derive(Debug)]
pub enum CliError {
CommandFailed(String),
CommandFailed(String, String),
IoError(io::Error),
RustfmtNotInstalled,
WalkDirError(walkdir::Error),
Expand Down Expand Up @@ -75,8 +75,8 @@ pub fn run(check: bool, verbose: bool) {

fn output_err(err: CliError) {
match err {
CliError::CommandFailed(command) => {
eprintln!("error: A command failed! `{}`", command);
CliError::CommandFailed(command, stderr) => {
eprintln!("error: A command failed! `{}`\nstderr: {}", command, stderr);
},
CliError::IoError(err) => {
eprintln!("error: {}", err);
Expand Down Expand Up @@ -136,12 +136,16 @@ fn exec(
println!("{}", format_command(&program, &dir, args));
}

let mut child = Command::new(&program).current_dir(&dir).args(args.iter()).spawn()?;
let code = child.wait()?;
let success = code.success();
let child = Command::new(&program).current_dir(&dir).args(args.iter()).spawn()?;
let output = child.wait_with_output()?;
let success = output.status.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)
Expand Down Expand Up @@ -177,7 +181,10 @@ fn rustfmt_test(context: &FmtContext) -> Result<(), CliError> {
{
Err(CliError::RustfmtNotInstalled)
} 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(),
))
}
}

Expand Down
13 changes: 13 additions & 0 deletions src/tools/clippy/clippy_dev/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,10 @@ pub struct FileChange {
/// `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.
///
/// # Panics
///
/// Panics if the path could not read or then written
pub fn replace_region_in_file<F>(
path: &Path,
start: &str,
Expand Down Expand Up @@ -283,6 +287,10 @@ where
/// .new_lines;
/// 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
where
F: FnOnce() -> Vec<String>,
Expand Down Expand Up @@ -329,6 +337,11 @@ where
}

/// 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]
pub fn clippy_project_root() -> PathBuf {
let current_dir = std::env::current_dir().unwrap();
Expand Down
3 changes: 3 additions & 0 deletions src/tools/clippy/clippy_dev/src/ra_setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use std::path::{Path, PathBuf};
// 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

/// # 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>) {
// we can unwrap here because the arg is required by clap
let rustc_path = PathBuf::from(rustc_path.unwrap());
Expand Down
3 changes: 3 additions & 0 deletions src/tools/clippy/clippy_dev/src/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ use std::process::Command;
use std::thread;
use std::time::{Duration, SystemTime};

/// # Panics
///
/// Panics if the python commands could not be spawned
pub fn run(port: u16, lint: Option<&str>) -> ! {
let mut url = Some(match lint {
None => format!("http://localhost:{}", port),
Expand Down
125 changes: 120 additions & 5 deletions src/tools/clippy/clippy_lints/src/doc.rs
Original file line number Diff line number Diff line change
@@ -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 itertools::Itertools;
use rustc_ast::ast::{Async, AttrKind, Attribute, FnKind, FnRetTy, ItemKind};
Expand All @@ -8,7 +11,10 @@ use rustc_data_structures::sync::Lrc;
use rustc_errors::emitter::EmitterWriter;
use rustc_errors::Handler;
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_middle::hir::map::Map;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty;
use rustc_parse::maybe_new_parser_from_source_str;
Expand Down Expand Up @@ -122,6 +128,37 @@ declare_clippy_lint! {
"`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! {
/// **What it does:** Checks for `fn main() { .. }` in doctests
///
Expand Down Expand Up @@ -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 {
fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) {
Expand All @@ -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())
|| 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_) => {
Expand All @@ -200,7 +247,7 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
let headers = check_attrs(cx, &self.valid_idents, &item.attrs);
if let hir::TraitItemKind::Fn(ref sig, ..) = item.kind {
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);
}
}
}
Expand All @@ -211,7 +258,15 @@ impl<'tcx> LateLintPass<'tcx> for DocMarkdown {
return;
}
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);
}
}
}
Expand All @@ -223,6 +278,7 @@ fn lint_for_missing_headers<'tcx>(
sig: &hir::FnSig<'_>,
headers: DocHeaders,
body_id: Option<hir::BodyId>,
panic_span: Option<Span>,
) {
if !cx.access_levels.is_exported(hir_id) {
return; // Private functions do not require doc comments
Expand All @@ -235,6 +291,16 @@ fn lint_for_missing_headers<'tcx>(
"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 is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym::result_type) {
span_lint(
Expand Down Expand Up @@ -321,6 +387,7 @@ pub fn strip_doc_comment_decoration(doc: &str, comment_kind: CommentKind, span:
struct DocHeaders {
safety: bool,
errors: bool,
panics: bool,
}

fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs: &'a [Attribute]) -> DocHeaders {
Expand All @@ -338,6 +405,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
return DocHeaders {
safety: true,
errors: true,
panics: true,
};
}
}
Expand All @@ -353,6 +421,7 @@ fn check_attrs<'a>(cx: &LateContext<'_>, valid_idents: &FxHashSet<String>, attrs
return DocHeaders {
safety: false,
errors: false,
panics: false,
};
}

Expand Down Expand Up @@ -394,6 +463,7 @@ fn check_doc<'a, Events: Iterator<Item = (pulldown_cmark::Event<'a>, Range<usize
let mut headers = DocHeaders {
safety: false,
errors: false,
panics: false,
};
let mut in_code = false;
let mut in_link = None;
Expand Down Expand Up @@ -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.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)) {
Ok(o) => o,
Err(e) => e - 1,
Expand Down Expand Up @@ -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())
}
}
8 changes: 5 additions & 3 deletions src/tools/clippy/clippy_lints/src/excessive_bools.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,15 +160,17 @@ impl EarlyLintPass for ExcessiveBools {
"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)) => {
for item in items {
if let AssocItemKind::Fn(box FnKind(_, fn_sig, _, _)) = &item.kind {
self.check_fn_sig(cx, fn_sig, item.span);
}
}
}
},
ItemKind::Fn(box FnKind(_, fn_sig, _, _)) => self.check_fn_sig(cx, fn_sig, item.span),
_ => (),
}
Expand Down
Loading