]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #79780 - camelid:use-summary_opts, r=GuillaumeGomez
authorbors <bors@rust-lang.org>
Tue, 8 Dec 2020 01:15:26 +0000 (01:15 +0000)
committerbors <bors@rust-lang.org>
Tue, 8 Dec 2020 01:15:26 +0000 (01:15 +0000)
Use `summary_opts()` in another spot

I added `summary_opts()` before I cut the branch for #77686 (2 months
ago!), so this "slipped through the cracks".

491 files changed:
Cargo.lock
compiler/rustc_ast_lowering/src/expr.rs
compiler/rustc_error_codes/src/error_codes/E0390.md
compiler/rustc_hir/src/arena.rs
compiler/rustc_hir/src/hir.rs
compiler/rustc_hir/src/intravisit.rs
compiler/rustc_hir_pretty/src/lib.rs
compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
compiler/rustc_lint_defs/src/builtin.rs
compiler/rustc_middle/src/ty/fold.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_mir/src/interpret/util.rs
compiler/rustc_mir_build/src/thir/cx/expr.rs
compiler/rustc_parse/src/parser/mod.rs
compiler/rustc_passes/src/intrinsicck.rs
compiler/rustc_passes/src/liveness.rs
compiler/rustc_passes/src/naked_functions.rs
compiler/rustc_trait_selection/src/traits/query/normalize.rs
compiler/rustc_typeck/src/astconv/generics.rs
compiler/rustc_typeck/src/check/check.rs
compiler/rustc_typeck/src/check/expr.rs
compiler/rustc_typeck/src/coherence/inherent_impls.rs
compiler/rustc_typeck/src/expr_use_visitor.rs
library/core/src/ops/control_flow.rs
library/core/src/str/mod.rs
library/std/src/sys/unix/fs.rs
library/std/src/sys/unix/kernel_copy.rs
library/std/src/sys/unix/kernel_copy/tests.rs
library/std/tests/env.rs
src/librustdoc/clean/mod.rs
src/librustdoc/json/mod.rs
src/librustdoc/json/types.rs
src/test/rustdoc-json/nested.expected [new file with mode: 0644]
src/test/rustdoc-json/nested.rs [new file with mode: 0644]
src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs [new file with mode: 0644]
src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs [deleted file]
src/test/ui/asm/naked-functions.rs [new file with mode: 0644]
src/test/ui/asm/naked-functions.stderr [new file with mode: 0644]
src/test/ui/asm/naked-params.rs [deleted file]
src/test/ui/asm/naked-params.stderr [deleted file]
src/test/ui/auxiliary/extern-prelude-vec.rs [deleted file]
src/test/ui/auxiliary/extern-prelude.rs [deleted file]
src/test/ui/const-generics/issues/issue-62878.full.stderr
src/test/ui/const-generics/min_const_generics/inferred_const.rs [new file with mode: 0644]
src/test/ui/const-generics/min_const_generics/inferred_const.stderr [new file with mode: 0644]
src/test/ui/derives/issue-36617.rs [new file with mode: 0644]
src/test/ui/derives/issue-36617.stderr [new file with mode: 0644]
src/test/ui/double-import.rs [deleted file]
src/test/ui/double-import.stderr [deleted file]
src/test/ui/env-vars.rs
src/test/ui/error-codes/E0390.stderr
src/test/ui/export-glob-imports-target.rs [deleted file]
src/test/ui/extern-prelude-fail.rs [deleted file]
src/test/ui/extern-prelude-fail.stderr [deleted file]
src/test/ui/extern-prelude.rs [deleted file]
src/test/ui/feature-gates/feature-gate-naked_functions.rs
src/test/ui/feature-gates/feature-gate-naked_functions.stderr
src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.rs
src/test/ui/generic-associated-types/parse/trait-path-missing-gen_arg.stderr
src/test/ui/glob-resolve1.rs [deleted file]
src/test/ui/glob-resolve1.stderr [deleted file]
src/test/ui/hidden-rt-injection.rs [deleted file]
src/test/ui/hidden-rt-injection.stderr [deleted file]
src/test/ui/hidden-rt-injection2.rs [deleted file]
src/test/ui/hidden-rt-injection2.stderr [deleted file]
src/test/ui/import.rs [deleted file]
src/test/ui/import.stderr [deleted file]
src/test/ui/import2.rs [deleted file]
src/test/ui/import2.stderr [deleted file]
src/test/ui/import3.rs [deleted file]
src/test/ui/import3.stderr [deleted file]
src/test/ui/import4.rs [deleted file]
src/test/ui/import4.stderr [deleted file]
src/test/ui/imports/auxiliary/issue-36881-aux.rs [new file with mode: 0644]
src/test/ui/imports/auxiliary/issue-52891.rs [new file with mode: 0644]
src/test/ui/imports/auxiliary/issue-59764.rs [new file with mode: 0644]
src/test/ui/imports/double-import.rs [new file with mode: 0644]
src/test/ui/imports/double-import.stderr [new file with mode: 0644]
src/test/ui/imports/export-glob-imports-target.rs [new file with mode: 0644]
src/test/ui/imports/glob-resolve1.rs [new file with mode: 0644]
src/test/ui/imports/glob-resolve1.stderr [new file with mode: 0644]
src/test/ui/imports/import-rpass.rs [new file with mode: 0644]
src/test/ui/imports/import.rs
src/test/ui/imports/import.stderr [new file with mode: 0644]
src/test/ui/imports/import2-rpass.rs [new file with mode: 0644]
src/test/ui/imports/import2.rs
src/test/ui/imports/import2.stderr [new file with mode: 0644]
src/test/ui/imports/import3-rpass.rs [new file with mode: 0644]
src/test/ui/imports/import3.rs
src/test/ui/imports/import3.stderr [new file with mode: 0644]
src/test/ui/imports/import4-rpass.rs [new file with mode: 0644]
src/test/ui/imports/import4.rs
src/test/ui/imports/import4.stderr [new file with mode: 0644]
src/test/ui/imports/issue-13404.rs [new file with mode: 0644]
src/test/ui/imports/issue-13404.stderr [new file with mode: 0644]
src/test/ui/imports/issue-1697.rs [new file with mode: 0644]
src/test/ui/imports/issue-1697.stderr [new file with mode: 0644]
src/test/ui/imports/issue-18083.rs [new file with mode: 0644]
src/test/ui/imports/issue-19498.rs [new file with mode: 0644]
src/test/ui/imports/issue-19498.stderr [new file with mode: 0644]
src/test/ui/imports/issue-24081.rs [new file with mode: 0644]
src/test/ui/imports/issue-24081.stderr [new file with mode: 0644]
src/test/ui/imports/issue-25396.rs [new file with mode: 0644]
src/test/ui/imports/issue-25396.stderr [new file with mode: 0644]
src/test/ui/imports/issue-26886.rs [new file with mode: 0644]
src/test/ui/imports/issue-26886.stderr [new file with mode: 0644]
src/test/ui/imports/issue-28134.rs [new file with mode: 0644]
src/test/ui/imports/issue-28134.stderr [new file with mode: 0644]
src/test/ui/imports/issue-28388-1.rs [new file with mode: 0644]
src/test/ui/imports/issue-28388-1.stderr [new file with mode: 0644]
src/test/ui/imports/issue-28388-2.rs [new file with mode: 0644]
src/test/ui/imports/issue-28388-2.stderr [new file with mode: 0644]
src/test/ui/imports/issue-2937.rs [new file with mode: 0644]
src/test/ui/imports/issue-2937.stderr [new file with mode: 0644]
src/test/ui/imports/issue-30560.rs [new file with mode: 0644]
src/test/ui/imports/issue-30560.stderr [new file with mode: 0644]
src/test/ui/imports/issue-31212.rs [new file with mode: 0644]
src/test/ui/imports/issue-31212.stderr [new file with mode: 0644]
src/test/ui/imports/issue-32354-suggest-import-rename.fixed [new file with mode: 0644]
src/test/ui/imports/issue-32354-suggest-import-rename.rs [new file with mode: 0644]
src/test/ui/imports/issue-32354-suggest-import-rename.stderr [new file with mode: 0644]
src/test/ui/imports/issue-32833.rs [new file with mode: 0644]
src/test/ui/imports/issue-32833.stderr [new file with mode: 0644]
src/test/ui/imports/issue-33464.rs [new file with mode: 0644]
src/test/ui/imports/issue-33464.stderr [new file with mode: 0644]
src/test/ui/imports/issue-36881.rs [new file with mode: 0644]
src/test/ui/imports/issue-36881.stderr [new file with mode: 0644]
src/test/ui/imports/issue-37887.rs [new file with mode: 0644]
src/test/ui/imports/issue-37887.stderr [new file with mode: 0644]
src/test/ui/imports/issue-38293.rs [new file with mode: 0644]
src/test/ui/imports/issue-38293.stderr [new file with mode: 0644]
src/test/ui/imports/issue-4366-2.rs [new file with mode: 0644]
src/test/ui/imports/issue-4366-2.stderr [new file with mode: 0644]
src/test/ui/imports/issue-4366.rs [new file with mode: 0644]
src/test/ui/imports/issue-4366.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed [new file with mode: 0644]
src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs [new file with mode: 0644]
src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/auxiliary/issue-45829-a.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/auxiliary/issue-45829-b.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/import-self.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/import-self.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/import-twice.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/import-twice.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/issue-45829.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/issue-45829.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-extern-vs-use.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-extern-vs-use.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-extern-with-tab.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-extern-with-tab.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-extern.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-extern.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-use-vs-extern.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-use-vs-extern.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-use-with-tabs.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-use-with-tabs.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-with-path.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename-with-path.stderr [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename.rs [new file with mode: 0644]
src/test/ui/imports/issue-45829/rename.stderr [new file with mode: 0644]
src/test/ui/imports/issue-47623.rs [new file with mode: 0644]
src/test/ui/imports/issue-47623.stderr [new file with mode: 0644]
src/test/ui/imports/issue-4865-1.rs [new file with mode: 0644]
src/test/ui/imports/issue-4865-2.rs [new file with mode: 0644]
src/test/ui/imports/issue-4865-3.rs [new file with mode: 0644]
src/test/ui/imports/issue-52891.fixed [new file with mode: 0644]
src/test/ui/imports/issue-52891.rs [new file with mode: 0644]
src/test/ui/imports/issue-52891.stderr [new file with mode: 0644]
src/test/ui/imports/issue-53565.rs [new file with mode: 0644]
src/test/ui/imports/issue-53565.stderr [new file with mode: 0644]
src/test/ui/imports/issue-59764.rs [new file with mode: 0644]
src/test/ui/imports/issue-59764.stderr [new file with mode: 0644]
src/test/ui/imports/issue-8208.rs [new file with mode: 0644]
src/test/ui/imports/issue-8208.stderr [new file with mode: 0644]
src/test/ui/imports/issue-8640.rs [new file with mode: 0644]
src/test/ui/imports/issue-8640.stderr [new file with mode: 0644]
src/test/ui/imports/resolve_self_super_hint.rs [new file with mode: 0644]
src/test/ui/imports/resolve_self_super_hint.stderr [new file with mode: 0644]
src/test/ui/issues/auxiliary/issue-36881-aux.rs [deleted file]
src/test/ui/issues/auxiliary/issue-52891.rs [deleted file]
src/test/ui/issues/auxiliary/issue-59764.rs [deleted file]
src/test/ui/issues/auxiliary/lint-stability.rs [deleted file]
src/test/ui/issues/issue-13404.rs [deleted file]
src/test/ui/issues/issue-13404.stderr [deleted file]
src/test/ui/issues/issue-1697.rs [deleted file]
src/test/ui/issues/issue-1697.stderr [deleted file]
src/test/ui/issues/issue-18083.rs [deleted file]
src/test/ui/issues/issue-19498.rs [deleted file]
src/test/ui/issues/issue-19498.stderr [deleted file]
src/test/ui/issues/issue-20616-3.rs
src/test/ui/issues/issue-20616-3.stderr
src/test/ui/issues/issue-20616-4.rs
src/test/ui/issues/issue-20616-4.stderr
src/test/ui/issues/issue-20616-5.rs
src/test/ui/issues/issue-20616-5.stderr
src/test/ui/issues/issue-20616-6.rs
src/test/ui/issues/issue-20616-6.stderr
src/test/ui/issues/issue-20616-7.rs
src/test/ui/issues/issue-20616-7.stderr
src/test/ui/issues/issue-24081.rs [deleted file]
src/test/ui/issues/issue-24081.stderr [deleted file]
src/test/ui/issues/issue-25396.rs [deleted file]
src/test/ui/issues/issue-25396.stderr [deleted file]
src/test/ui/issues/issue-26886.rs [deleted file]
src/test/ui/issues/issue-26886.stderr [deleted file]
src/test/ui/issues/issue-28075.rs [deleted file]
src/test/ui/issues/issue-28075.stderr [deleted file]
src/test/ui/issues/issue-28134.rs [deleted file]
src/test/ui/issues/issue-28134.stderr [deleted file]
src/test/ui/issues/issue-28388-1.rs [deleted file]
src/test/ui/issues/issue-28388-1.stderr [deleted file]
src/test/ui/issues/issue-28388-2.rs [deleted file]
src/test/ui/issues/issue-28388-2.stderr [deleted file]
src/test/ui/issues/issue-28388-3.rs [deleted file]
src/test/ui/issues/issue-28388-3.stderr [deleted file]
src/test/ui/issues/issue-2937.rs [deleted file]
src/test/ui/issues/issue-2937.stderr [deleted file]
src/test/ui/issues/issue-30560.rs [deleted file]
src/test/ui/issues/issue-30560.stderr [deleted file]
src/test/ui/issues/issue-30730.rs [deleted file]
src/test/ui/issues/issue-30730.stderr [deleted file]
src/test/ui/issues/issue-31212.rs [deleted file]
src/test/ui/issues/issue-31212.stderr [deleted file]
src/test/ui/issues/issue-32354-suggest-import-rename.fixed [deleted file]
src/test/ui/issues/issue-32354-suggest-import-rename.rs [deleted file]
src/test/ui/issues/issue-32354-suggest-import-rename.stderr [deleted file]
src/test/ui/issues/issue-32833.rs [deleted file]
src/test/ui/issues/issue-32833.stderr [deleted file]
src/test/ui/issues/issue-33464.rs [deleted file]
src/test/ui/issues/issue-33464.stderr [deleted file]
src/test/ui/issues/issue-36617.rs [deleted file]
src/test/ui/issues/issue-36617.stderr [deleted file]
src/test/ui/issues/issue-36881.rs [deleted file]
src/test/ui/issues/issue-36881.stderr [deleted file]
src/test/ui/issues/issue-37887.rs [deleted file]
src/test/ui/issues/issue-37887.stderr [deleted file]
src/test/ui/issues/issue-38293.rs [deleted file]
src/test/ui/issues/issue-38293.stderr [deleted file]
src/test/ui/issues/issue-4366-2.rs [deleted file]
src/test/ui/issues/issue-4366-2.stderr [deleted file]
src/test/ui/issues/issue-4366.rs [deleted file]
src/test/ui/issues/issue-4366.stderr [deleted file]
src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed [deleted file]
src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs [deleted file]
src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr [deleted file]
src/test/ui/issues/issue-45829/auxiliary/issue-45829-a.rs [deleted file]
src/test/ui/issues/issue-45829/auxiliary/issue-45829-b.rs [deleted file]
src/test/ui/issues/issue-45829/import-self.rs [deleted file]
src/test/ui/issues/issue-45829/import-self.stderr [deleted file]
src/test/ui/issues/issue-45829/import-twice.rs [deleted file]
src/test/ui/issues/issue-45829/import-twice.stderr [deleted file]
src/test/ui/issues/issue-45829/issue-45829.rs [deleted file]
src/test/ui/issues/issue-45829/issue-45829.stderr [deleted file]
src/test/ui/issues/issue-45829/rename-extern-vs-use.rs [deleted file]
src/test/ui/issues/issue-45829/rename-extern-vs-use.stderr [deleted file]
src/test/ui/issues/issue-45829/rename-extern-with-tab.rs [deleted file]
src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr [deleted file]
src/test/ui/issues/issue-45829/rename-extern.rs [deleted file]
src/test/ui/issues/issue-45829/rename-extern.stderr [deleted file]
src/test/ui/issues/issue-45829/rename-use-vs-extern.rs [deleted file]
src/test/ui/issues/issue-45829/rename-use-vs-extern.stderr [deleted file]
src/test/ui/issues/issue-45829/rename-use-with-tabs.rs [deleted file]
src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr [deleted file]
src/test/ui/issues/issue-45829/rename-with-path.rs [deleted file]
src/test/ui/issues/issue-45829/rename-with-path.stderr [deleted file]
src/test/ui/issues/issue-45829/rename.rs [deleted file]
src/test/ui/issues/issue-45829/rename.stderr [deleted file]
src/test/ui/issues/issue-46576.rs [deleted file]
src/test/ui/issues/issue-46576.stderr [deleted file]
src/test/ui/issues/issue-47623.rs [deleted file]
src/test/ui/issues/issue-47623.stderr [deleted file]
src/test/ui/issues/issue-4865-1.rs [deleted file]
src/test/ui/issues/issue-4865-2.rs [deleted file]
src/test/ui/issues/issue-4865-3.rs [deleted file]
src/test/ui/issues/issue-49074.rs [deleted file]
src/test/ui/issues/issue-49074.stderr [deleted file]
src/test/ui/issues/issue-52891.fixed [deleted file]
src/test/ui/issues/issue-52891.rs [deleted file]
src/test/ui/issues/issue-52891.stderr [deleted file]
src/test/ui/issues/issue-53565.rs [deleted file]
src/test/ui/issues/issue-53565.stderr [deleted file]
src/test/ui/issues/issue-56411-aux.rs [deleted file]
src/test/ui/issues/issue-56411.rs [deleted file]
src/test/ui/issues/issue-56411.stderr [deleted file]
src/test/ui/issues/issue-59764.rs [deleted file]
src/test/ui/issues/issue-59764.stderr [deleted file]
src/test/ui/issues/issue-59896.rs [deleted file]
src/test/ui/issues/issue-59896.stderr [deleted file]
src/test/ui/issues/issue-70041.rs [deleted file]
src/test/ui/issues/issue-70041.stderr [deleted file]
src/test/ui/issues/issue-8208.rs [deleted file]
src/test/ui/issues/issue-8208.stderr [deleted file]
src/test/ui/issues/issue-8640.rs [deleted file]
src/test/ui/issues/issue-8640.stderr [deleted file]
src/test/ui/kinds-of-primitive-impl.rs [new file with mode: 0644]
src/test/ui/kinds-of-primitive-impl.stderr [new file with mode: 0644]
src/test/ui/modules/issue-56411-aux.rs [new file with mode: 0644]
src/test/ui/modules/issue-56411.rs [new file with mode: 0644]
src/test/ui/modules/issue-56411.stderr [new file with mode: 0644]
src/test/ui/parser/removed-syntax-uniq-mut-ty.rs
src/test/ui/parser/removed-syntax-uniq-mut-ty.stderr
src/test/ui/resolve-pseudo-shadowing.rs [deleted file]
src/test/ui/resolve/auxiliary/extern-prelude-vec.rs [new file with mode: 0644]
src/test/ui/resolve/auxiliary/extern-prelude.rs [new file with mode: 0644]
src/test/ui/resolve/extern-prelude-fail.rs [new file with mode: 0644]
src/test/ui/resolve/extern-prelude-fail.stderr [new file with mode: 0644]
src/test/ui/resolve/extern-prelude.rs [new file with mode: 0644]
src/test/ui/resolve/issue-49074.rs [new file with mode: 0644]
src/test/ui/resolve/issue-49074.stderr [new file with mode: 0644]
src/test/ui/resolve/resolve-pseudo-shadowing.rs [new file with mode: 0644]
src/test/ui/resolve_self_super_hint.rs [deleted file]
src/test/ui/resolve_self_super_hint.stderr [deleted file]
src/test/ui/rfc-2091-track-caller/error-with-naked.rs
src/test/ui/rfc-2091-track-caller/error-with-naked.stderr
src/test/ui/single-primitive-inherent-impl.stderr
src/test/ui/stability-attribute/auxiliary/lint-stability.rs [new file with mode: 0644]
src/test/ui/stability-attribute/issue-28075.rs [new file with mode: 0644]
src/test/ui/stability-attribute/issue-28075.stderr [new file with mode: 0644]
src/test/ui/stability-attribute/issue-28388-3.rs [new file with mode: 0644]
src/test/ui/stability-attribute/issue-28388-3.stderr [new file with mode: 0644]
src/test/ui/unused/issue-30730.rs [new file with mode: 0644]
src/test/ui/unused/issue-30730.stderr [new file with mode: 0644]
src/test/ui/unused/issue-46576.rs [new file with mode: 0644]
src/test/ui/unused/issue-46576.stderr [new file with mode: 0644]
src/test/ui/unused/issue-59896.rs [new file with mode: 0644]
src/test/ui/unused/issue-59896.stderr [new file with mode: 0644]
src/test/ui/unused/issue-70041.rs [new file with mode: 0644]
src/test/ui/unused/issue-70041.stderr [new file with mode: 0644]
src/tools/clippy/.github/workflows/clippy_bors.yml
src/tools/clippy/CHANGELOG.md
src/tools/clippy/CONTRIBUTING.md
src/tools/clippy/Cargo.toml
src/tools/clippy/README.md
src/tools/clippy/clippy_dev/src/lib.rs
src/tools/clippy/clippy_dev/src/update_lints.rs
src/tools/clippy/clippy_lints/Cargo.toml
src/tools/clippy/clippy_lints/src/attrs.rs
src/tools/clippy/clippy_lints/src/collapsible_match.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/comparison_chain.rs
src/tools/clippy/clippy_lints/src/default.rs
src/tools/clippy/clippy_lints/src/deprecated_lints.rs
src/tools/clippy/clippy_lints/src/eq_op.rs
src/tools/clippy/clippy_lints/src/if_let_some_result.rs
src/tools/clippy/clippy_lints/src/implicit_return.rs
src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs
src/tools/clippy/clippy_lints/src/items_after_statements.rs
src/tools/clippy/clippy_lints/src/large_const_arrays.rs
src/tools/clippy/clippy_lints/src/large_stack_arrays.rs
src/tools/clippy/clippy_lints/src/let_if_seq.rs
src/tools/clippy/clippy_lints/src/lib.rs
src/tools/clippy/clippy_lints/src/literal_representation.rs
src/tools/clippy/clippy_lints/src/loops.rs
src/tools/clippy/clippy_lints/src/manual_non_exhaustive.rs
src/tools/clippy/clippy_lints/src/manual_strip.rs
src/tools/clippy/clippy_lints/src/map_err_ignore.rs
src/tools/clippy/clippy_lints/src/matches.rs
src/tools/clippy/clippy_lints/src/methods/manual_saturating_arithmetic.rs
src/tools/clippy/clippy_lints/src/methods/mod.rs
src/tools/clippy/clippy_lints/src/misc.rs
src/tools/clippy/clippy_lints/src/needless_bool.rs
src/tools/clippy/clippy_lints/src/panic_unimplemented.rs
src/tools/clippy/clippy_lints/src/question_mark.rs
src/tools/clippy/clippy_lints/src/redundant_closure_call.rs
src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/strings.rs
src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/trait_bounds.rs
src/tools/clippy/clippy_lints/src/transmuting_null.rs
src/tools/clippy/clippy_lints/src/types.rs
src/tools/clippy/clippy_lints/src/unnecessary_wraps.rs
src/tools/clippy/clippy_lints/src/utils/ast_utils.rs
src/tools/clippy/clippy_lints/src/utils/ast_utils/ident_iter.rs [new file with mode: 0644]
src/tools/clippy/clippy_lints/src/utils/attrs.rs
src/tools/clippy/clippy_lints/src/utils/conf.rs
src/tools/clippy/clippy_lints/src/utils/diagnostics.rs
src/tools/clippy/clippy_lints/src/utils/higher.rs
src/tools/clippy/clippy_lints/src/utils/hir_utils.rs
src/tools/clippy/clippy_lints/src/utils/inspector.rs
src/tools/clippy/clippy_lints/src/utils/mod.rs
src/tools/clippy/clippy_lints/src/utils/paths.rs
src/tools/clippy/clippy_lints/src/utils/visitors.rs
src/tools/clippy/tests/compile-test.rs
src/tools/clippy/tests/dogfood.rs
src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/custom_ice_message.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/custom_ice_message.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/default_lint.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/default_lint.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/invalid_paths.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/invalid_paths.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/outer_expn_data.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/outer_expn_data.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-internal/outer_expn_data.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/invalid_min_rust_version/clippy.toml [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/lint_decimal_readability/clippy.toml [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/min_rust_version/clippy.toml [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs [new file with mode: 0644]
src/tools/clippy/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
src/tools/clippy/tests/ui/as_conversions.rs
src/tools/clippy/tests/ui/as_conversions.stderr
src/tools/clippy/tests/ui/auxiliary/macro_rules.rs
src/tools/clippy/tests/ui/collapsible_match.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/collapsible_match.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/collapsible_match2.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/collapsible_match2.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/collapsible_span_lint_calls.fixed [deleted file]
src/tools/clippy/tests/ui/collapsible_span_lint_calls.rs [deleted file]
src/tools/clippy/tests/ui/collapsible_span_lint_calls.stderr [deleted file]
src/tools/clippy/tests/ui/custom_ice_message.rs [deleted file]
src/tools/clippy/tests/ui/custom_ice_message.stderr [deleted file]
src/tools/clippy/tests/ui/default_lint.rs [deleted file]
src/tools/clippy/tests/ui/default_lint.stderr [deleted file]
src/tools/clippy/tests/ui/deprecated.rs
src/tools/clippy/tests/ui/deprecated.stderr
src/tools/clippy/tests/ui/deprecated_old.rs
src/tools/clippy/tests/ui/deprecated_old.stderr
src/tools/clippy/tests/ui/eq_op.rs
src/tools/clippy/tests/ui/eq_op.stderr
src/tools/clippy/tests/ui/invalid_paths.rs [deleted file]
src/tools/clippy/tests/ui/invalid_paths.stderr [deleted file]
src/tools/clippy/tests/ui/item_after_statement.rs
src/tools/clippy/tests/ui/lint_without_lint_pass.rs [deleted file]
src/tools/clippy/tests/ui/lint_without_lint_pass.stderr [deleted file]
src/tools/clippy/tests/ui/map_err.rs
src/tools/clippy/tests/ui/map_err.stderr
src/tools/clippy/tests/ui/match_type_on_diag_item.rs [deleted file]
src/tools/clippy/tests/ui/match_type_on_diag_item.stderr [deleted file]
src/tools/clippy/tests/ui/min_rust_version_attr.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/min_rust_version_attr.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/min_rust_version_no_patch.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/modulo_one.rs
src/tools/clippy/tests/ui/modulo_one.stderr
src/tools/clippy/tests/ui/needless_collect_indirect.rs
src/tools/clippy/tests/ui/outer_expn_data.fixed [deleted file]
src/tools/clippy/tests/ui/outer_expn_data.rs [deleted file]
src/tools/clippy/tests/ui/outer_expn_data.stderr [deleted file]
src/tools/clippy/tests/ui/panicking_macros.stderr
src/tools/clippy/tests/ui/redundant_pattern_matching.fixed [deleted file]
src/tools/clippy/tests/ui/redundant_pattern_matching.rs [deleted file]
src/tools/clippy/tests/ui/redundant_pattern_matching.stderr [deleted file]
src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_pattern_matching_option.fixed
src/tools/clippy/tests/ui/redundant_pattern_matching_option.rs
src/tools/clippy/tests/ui/redundant_pattern_matching_option.stderr
src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/size_of_in_element_count.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/size_of_in_element_count.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/str_to_string.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/str_to_string.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/string_to_string.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/string_to_string.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/suspicious_operation_groupings.rs [new file with mode: 0644]
src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr [new file with mode: 0644]
src/tools/clippy/tests/ui/unnecessary_cast.rs
src/tools/clippy/tests/ui/unnecessary_cast_fixable.fixed
src/tools/clippy/tests/ui/unnecessary_cast_fixable.rs
src/tools/clippy/tests/ui/unnecessary_cast_fixable.stderr
src/tools/clippy/tests/ui/unnecessary_wraps.rs
src/tools/clippy/tests/ui/unreadable_literal.fixed
src/tools/clippy/tests/ui/unreadable_literal.rs
src/tools/clippy/tests/ui/unreadable_literal.stderr
src/tools/clippy/tests/ui/wildcard_enum_match_arm.fixed
src/tools/clippy/tests/ui/wildcard_enum_match_arm.rs
src/tools/clippy/tests/ui/wildcard_enum_match_arm.stderr
src/tools/publish_toolstate.py
src/tools/rls
src/tools/rustc-workspace-hack/Cargo.toml
src/tools/rustfmt

index 85be4c392afae3eaf9b1978e6183afa77037329b..5c096e9f80c30e6558f4d8ef5dfac2d717baaaa7 100644 (file)
@@ -569,6 +569,7 @@ dependencies = [
  "quine-mc_cluskey",
  "quote",
  "regex-syntax",
+ "rustc-semver",
  "semver 0.11.0",
  "serde",
  "smallvec 1.4.2",
@@ -1924,17 +1925,6 @@ version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
 
-[[package]]
-name = "md-5"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8"
-dependencies = [
- "block-buffer 0.7.3",
- "digest 0.8.1",
- "opaque-debug 0.2.3",
-]
-
 [[package]]
 name = "md-5"
 version = "0.9.1"
@@ -2695,9 +2685,9 @@ dependencies = [
 
 [[package]]
 name = "racer"
-version = "2.1.40"
+version = "2.1.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68c5fb83bc092c10e12ca863ab8922b1833382d5d248aaafca779886d3396a44"
+checksum = "a2f1a4baaaf5c4a9aa30c708c339ae293d02976d2b7f1575a59f44558d25bfea"
 dependencies = [
  "bitflags",
  "clap",
@@ -3024,18 +3014,18 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_arena"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "477085eefed2f12085c68577cc3827c8c39a31a4a750978aacb9af10f7903174"
+checksum = "81f7b9bc5a6f79b1f230833cb4c8f8928d48c129b21df5b372c202fb826c0b5e"
 dependencies = [
  "smallvec 1.4.2",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_ast"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d4ad5ec25f6b3d122354595be0d1b513f37fca3299d9b448b1db28f4a9e4b12"
+checksum = "3d77f313e9f30af93f2737f1a99d6552e26b702c5cef3bb65e35f5b4fe5191f1"
 dependencies = [
  "bitflags",
  "rustc-ap-rustc_data_structures",
@@ -3050,9 +3040,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_ast_passes"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c6d8635298d7736decdb3c6e92e784d3eccde557462a9c10ac11a34fec3d756"
+checksum = "30408fbf42fa6fbeb383d3fce0f24d2490c3d12527beb2f48e6e728765bc8695"
 dependencies = [
  "itertools 0.9.0",
  "rustc-ap-rustc_ast",
@@ -3069,9 +3059,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_ast_pretty"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a61bdb5252e1a95b7715038949e10f07ce770a436fcd497cdd9bc7255471de9"
+checksum = "d47b8a3adcccc204578b0ee9cd2f9952921fa43977f58343913cca04cce87043"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_span",
@@ -3081,9 +3071,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_attr"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84520a16cb61bd31e9c27e87eca5d933a9c94ac84f25649bddcc19989275ab2a"
+checksum = "66f5f53ecdbf7d8b47905936f93eb1fdae496137e94b7e4023a0b866b0e1a92d"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_ast_pretty",
@@ -3100,9 +3090,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_data_structures"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1cb2b6a38759cf7c0c1434c8b4cbfcab9cd24970d05f960f2ca01226ddb4d68"
+checksum = "3aa913fa40b90157067b17dd7ddfd5df0d8566e339ffa8351a638bdf3fc7ee81"
 dependencies = [
  "arrayvec",
  "bitflags",
@@ -3131,13 +3121,14 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_errors"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46cfb19536426bf9252827a78552d635be207a4be74f4e92832aad82d7f2135c"
+checksum = "5d4b4956287d7c4996409b8362aa69c0c9a6853751ff00ee0a6f78223c5ef3ad"
 dependencies = [
  "annotate-snippets 0.8.0",
  "atty",
  "rustc-ap-rustc_data_structures",
+ "rustc-ap-rustc_lint_defs",
  "rustc-ap-rustc_macros",
  "rustc-ap-rustc_serialize",
  "rustc-ap-rustc_span",
@@ -3150,9 +3141,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_expand"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6273e60042a0ef31f6cfe783c519873993eb426f055be2bc058a48b6ca3934d0"
+checksum = "3fa908bb1b67230dd4309e93edefc6a6c2f3d8b6a195f77c47743c882114a22e"
 dependencies = [
  "rustc-ap-rustc_ast",
  "rustc-ap-rustc_ast_passes",
@@ -3173,9 +3164,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_feature"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2936e8346157e2848305e509f38aa3ed4e97697975ef68027587f5db6a38703f"
+checksum = "d9b7a1db115893ed7ed0db80f70d2246c1709de7854238acde76471495930f2a"
 dependencies = [
  "rustc-ap-rustc_data_structures",
  "rustc-ap-rustc_span",
@@ -3183,21 +3174,21 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_fs_util"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b4c3ae17776b5a5aa441ca510a650f75805e1f5569edd231caa8378552195a4"
+checksum = "55937887cb606cc72193ea3c5feb8bbbb810d812aa233b9a1e7749155c4a3501"
 
 [[package]]
 name = "rustc-ap-rustc_graphviz"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5611bf0ac0ac49c2a22c959c7d8b17f85f69959293f0e8c4f753eca832fe7ad0"
+checksum = "e39e179e616356927f0c4eda43e3a35d88476f91e1ac8e4a0a09661dbab44a6e"
 
 [[package]]
 name = "rustc-ap-rustc_index"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca67cf37c427057192e451c7f912e94ae9a8ca5ad69fd481c011fad3f86982cb"
+checksum = "572d3962d6999f3b1a71d335308e939e204339d4ad36e6ebe7a591c9d4329f5d"
 dependencies = [
  "arrayvec",
  "rustc-ap-rustc_macros",
@@ -3206,18 +3197,32 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_lexer"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5b04cd2159495584d976d501c5394498470c2e94e4f0cebb8186562d407a678"
+checksum = "44bc89d9ca7a78fb82e103b389362c55f03800745f8ba14e068b805cfaf783ec"
 dependencies = [
  "unicode-xid",
 ]
 
+[[package]]
+name = "rustc-ap-rustc_lint_defs"
+version = "691.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7d39bda92aabd77e49ac8ad5e24fccf9d7245b8ff2bf1249ab98733e2e5a2863"
+dependencies = [
+ "rustc-ap-rustc_ast",
+ "rustc-ap-rustc_data_structures",
+ "rustc-ap-rustc_macros",
+ "rustc-ap-rustc_serialize",
+ "rustc-ap-rustc_span",
+ "tracing",
+]
+
 [[package]]
 name = "rustc-ap-rustc_macros"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61ec6d623853449acd3c65050d249d3674edab5f6e4d9f074c7bac183269f9c8"
+checksum = "a3295fbc9625197494e356e92d8ac08370eddafa60189861c7b2f084b3b5a6b8"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3227,9 +3232,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_parse"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca524bafce4b04d2b49fee2d40b4b26c3ebab9f1a4f731fdf561f00617862f02"
+checksum = "9ff5d0094396844efead43303a6eb25b8a4962e2c80fb0ea4a86e4101fbfd404"
 dependencies = [
  "bitflags",
  "rustc-ap-rustc_ast",
@@ -3247,9 +3252,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_serialize"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c67920561e58f98c4de864407c92b2dd05ace5d5e5301e17444f10f742c005b7"
+checksum = "2d5cff6709a8b51a3730288a9ead17cabe8146b1c787db52298447ef7890140a"
 dependencies = [
  "indexmap",
  "smallvec 1.4.2",
@@ -3257,9 +3262,9 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_session"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0762fd855792e06ef639327237898e4e092ad68150e6a8e19aeb7dc06276ad7a"
+checksum = "36bb15ef12174b5ed6419a7e4260a899ce8927e8c8fd1f0cddf178818737dcdf"
 dependencies = [
  "bitflags",
  "getopts",
@@ -3269,6 +3274,7 @@ dependencies = [
  "rustc-ap-rustc_errors",
  "rustc-ap-rustc_feature",
  "rustc-ap-rustc_fs_util",
+ "rustc-ap-rustc_lint_defs",
  "rustc-ap-rustc_macros",
  "rustc-ap-rustc_serialize",
  "rustc-ap-rustc_span",
@@ -3278,28 +3284,29 @@ dependencies = [
 
 [[package]]
 name = "rustc-ap-rustc_span"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bf3db7b4ca5d21c14c45475df155e5e020c9a3760346945a662c9a9053b49c8"
+checksum = "104d349a32be9cfd3d39a5a70ad6c5e682ce262fc5cc8717d35a01e980c0d8b2"
 dependencies = [
  "cfg-if 0.1.10",
- "md-5 0.8.0",
+ "md-5",
  "rustc-ap-rustc_arena",
  "rustc-ap-rustc_data_structures",
  "rustc-ap-rustc_index",
  "rustc-ap-rustc_macros",
  "rustc-ap-rustc_serialize",
  "scoped-tls",
- "sha-1 0.8.2",
+ "sha-1 0.9.1",
+ "sha2",
  "tracing",
  "unicode-width",
 ]
 
 [[package]]
 name = "rustc-ap-rustc_target"
-version = "686.0.0"
+version = "691.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3aa6560bb9742b276064d67ab9edb5766ecb303f8ae3854835ad3fad4b432188"
+checksum = "9d7ac4ded9a6aecb534744c836a160497985f0d53b272581e95e7890d31b9e17"
 dependencies = [
  "bitflags",
  "rustc-ap-rustc_data_structures",
@@ -3359,6 +3366,12 @@ dependencies = [
  "num_cpus",
 ]
 
+[[package]]
+name = "rustc-semver"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be1bdc7edf596692617627bbfeaba522131b18e06ca4df2b6b689e3c5d5ce84"
+
 [[package]]
 name = "rustc-std-workspace-alloc"
 version = "1.99.0"
@@ -3386,6 +3399,7 @@ version = "1.0.0"
 dependencies = [
  "byteorder",
  "crossbeam-utils 0.7.2",
+ "libc",
  "proc-macro2",
  "quote",
  "serde",
@@ -4144,7 +4158,7 @@ name = "rustc_span"
 version = "0.0.0"
 dependencies = [
  "cfg-if 0.1.10",
- "md-5 0.9.1",
+ "md-5",
  "rustc_arena",
  "rustc_data_structures",
  "rustc_index",
@@ -4335,7 +4349,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.4.27"
+version = "1.4.29"
 dependencies = [
  "annotate-snippets 0.6.1",
  "anyhow",
index e0e78a4d60953665f4694176b09efffbe3041f26..6ad6e664316f40421aafa2934171619e6adc7fe6 100644 (file)
@@ -1307,7 +1307,7 @@ fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
                         hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
                     }
                 };
-                Some(op)
+                Some((op, *op_sp))
             })
             .collect();
 
@@ -1326,7 +1326,7 @@ fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
             } = *p
             {
                 let op_sp = asm.operands[operand_idx].1;
-                match &operands[operand_idx] {
+                match &operands[operand_idx].0 {
                     hir::InlineAsmOperand::In { reg, .. }
                     | hir::InlineAsmOperand::Out { reg, .. }
                     | hir::InlineAsmOperand::InOut { reg, .. }
@@ -1385,8 +1385,7 @@ fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
         let mut used_input_regs = FxHashMap::default();
         let mut used_output_regs = FxHashMap::default();
         let mut required_features: Vec<&str> = vec![];
-        for (idx, op) in operands.iter().enumerate() {
-            let op_sp = asm.operands[idx].1;
+        for (idx, &(ref op, op_sp)) in operands.iter().enumerate() {
             if let Some(reg) = op.reg() {
                 // Make sure we don't accidentally carry features from the
                 // previous iteration.
@@ -1458,8 +1457,7 @@ fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
                                     skip = true;
 
                                     let idx2 = *o.get();
-                                    let op2 = &operands[idx2];
-                                    let op_sp2 = asm.operands[idx2].1;
+                                    let &(ref op2, op_sp2) = &operands[idx2];
                                     let reg2 = match op2.reg() {
                                         Some(asm::InlineAsmRegOrRegClass::Reg(r)) => r,
                                         _ => unreachable!(),
index ecc5b5568ada15c41384d90e84dcf83840cbd8f5..7a13160d09858a621a11c0d1cc5985a832435f14 100644 (file)
@@ -1,4 +1,4 @@
-A method was implemented on a primitive type.
+A method or constant was implemented on a primitive type.
 
 Erroneous code example:
 
@@ -12,7 +12,8 @@ impl *mut Foo {}
 //        `#[lang = "mut_ptr"]` is allowed for the `*mut T` primitive
 ```
 
-This isn't allowed, but using a trait to implement a method is a good solution.
+This isn't allowed, but using a trait to implement a method or constant
+is a good solution.
 Example:
 
 ```
index 44dfdcfccab9b5367e2757e01ff3b9fbe53eade5..c7dc66b70fef1107e4451500331f14db3406f105 100644 (file)
@@ -14,7 +14,7 @@ macro_rules! arena_types {
             // HIR types
             [few] hir_krate: rustc_hir::Crate<$tcx>,
             [] arm: rustc_hir::Arm<$tcx>,
-            [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>,
+            [] asm_operand: (rustc_hir::InlineAsmOperand<$tcx>, Span),
             [] asm_template: rustc_ast::InlineAsmTemplatePiece,
             [] attribute: rustc_ast::Attribute,
             [] block: rustc_hir::Block<$tcx>,
index 44dc6673564a5d12a88a46e0c8a9c2963e93c9c1..280e863d4744d02578e6d45523c04d350f3fbfc0 100644 (file)
@@ -2143,7 +2143,7 @@ pub fn reg(&self) -> Option<InlineAsmRegOrRegClass> {
 #[derive(Debug, HashStable_Generic)]
 pub struct InlineAsm<'hir> {
     pub template: &'hir [InlineAsmTemplatePiece],
-    pub operands: &'hir [InlineAsmOperand<'hir>],
+    pub operands: &'hir [(InlineAsmOperand<'hir>, Span)],
     pub options: InlineAsmOptions,
     pub line_spans: &'hir [Span],
 }
index 3e8fc689acf7a83987b838055134408824dfe752..3c330c5d6c5288b2ffdc11f05c9a4cba334ef152 100644 (file)
@@ -1191,7 +1191,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
             walk_list!(visitor, visit_expr, optional_expression);
         }
         ExprKind::InlineAsm(ref asm) => {
-            for op in asm.operands {
+            for (op, _op_sp) in asm.operands {
                 match op {
                     InlineAsmOperand::In { expr, .. }
                     | InlineAsmOperand::InOut { expr, .. }
index 25b09d76295f2951d24ccf000480652251c37372..597c55b4bd7f3237cc4de0191773bb7e1744e692 100644 (file)
@@ -1462,7 +1462,7 @@ enum AsmArg<'a> {
 
                 let mut args = vec![];
                 args.push(AsmArg::Template(ast::InlineAsmTemplatePiece::to_string(&a.template)));
-                args.extend(a.operands.iter().map(|o| AsmArg::Operand(o)));
+                args.extend(a.operands.iter().map(|(o, _)| AsmArg::Operand(o)));
                 if !a.options.is_empty() {
                     args.push(AsmArg::Options(a.options));
                 }
index 6781fbc95c0eef955a99ac45219981a40f784f77..8a60b196e5e6e3a13ddf1c480e2f6aafd34b8017 100644 (file)
@@ -505,7 +505,7 @@ fn canonicalize<V>(
             let canon_value = Canonical {
                 max_universe: ty::UniverseIndex::ROOT,
                 variables: List::empty(),
-                value: value.clone(),
+                value,
             };
             return canon_value;
         }
index fa82dce0ae2ed48ce3401bd16ce1df6c3c0a2619..a9358c9610a5e6029171fface5491af493370a37 100644 (file)
     "detects deprecation attributes with no effect",
 }
 
+declare_lint! {
+    /// The `unsupported_naked_functions` lint detects naked function
+    /// definitions that are unsupported but were previously accepted.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #![feature(naked_functions)]
+    ///
+    /// #[naked]
+    /// pub fn f() -> u32 {
+    ///     42
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The naked functions must be defined using a single inline assembly
+    /// block.
+    ///
+    /// The execution must never fall through past the end of the assembly
+    /// code so the block must use `noreturn` option. The asm block can also
+    /// use `att_syntax` option, but other options are not allowed.
+    ///
+    /// The asm block must not contain any operands other than `const` and
+    /// `sym`. Additionally, naked function should specify a non-Rust ABI.
+    ///
+    /// While other definitions of naked functions were previously accepted,
+    /// they are unsupported and might not work reliably. This is a
+    /// [future-incompatible] lint that will transition into hard error in
+    /// the future.
+    ///
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub UNSUPPORTED_NAKED_FUNCTIONS,
+    Warn,
+    "unsupported naked function definitions",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #32408 <https://github.com/rust-lang/rust/issues/32408>",
+        edition: None,
+    };
+}
+
 declare_tool_lint! {
     pub rustc::INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
     Deny,
         UNINHABITED_STATIC,
         FUNCTION_ITEM_REFERENCES,
         USELESS_DEPRECATED,
+        UNSUPPORTED_NAKED_FUNCTIONS,
     ]
 }
 
index 1883c89a15193d70e6b7f953c7fec9d4d5f14a71..13c8d6b2bccb822b92e82c5e0946b5c17c6c80c4 100644 (file)
@@ -581,7 +581,7 @@ pub fn replace_escaping_bound_vars<T, F, G, H>(
         let mut const_map = FxHashMap::default();
 
         if !value.has_escaping_bound_vars() {
-            (value.clone(), region_map)
+            (value, region_map)
         } else {
             let mut real_fld_r = |br| *region_map.entry(br).or_insert_with(|| fld_r(br));
 
index 5d8edcf70bfd3329eff91af509afa157cbf3a37a..2d7f417b64a1dd6c921f233b08ea27b7ce26a36b 100644 (file)
@@ -1683,34 +1683,59 @@ pub struct BoundConst<'tcx> {
 
 pub type PlaceholderConst<'tcx> = Placeholder<BoundConst<'tcx>>;
 
-/// A `DefId` which is potentially bundled with its corresponding generic parameter
-/// in case `did` is a const argument.
+/// A `DefId` which, in case it is a const argument, is potentially bundled with
+/// the `DefId` of the generic parameter it instantiates.
 ///
-/// This is used to prevent cycle errors during typeck
-/// as `type_of(const_arg)` depends on `typeck(owning_body)`
-/// which once again requires the type of its generic arguments.
-///
-/// Luckily we only need to deal with const arguments once we
-/// know their corresponding parameters. We (ab)use this by
-/// calling `type_of(param_did)` for these arguments.
+/// This is used to avoid calls to `type_of` for const arguments during typeck
+/// which cause cycle errors.
 ///
 /// ```rust
 /// #![feature(const_generics)]
 ///
 /// struct A;
 /// impl A {
-///     fn foo<const N: usize>(&self) -> usize { N }
+///     fn foo<const N: usize>(&self) -> [u8; N] { [0; N] }
+///     //           ^ const parameter
 /// }
 /// struct B;
 /// impl B {
-///     fn foo<const N: u8>(&self) -> usize { 42 }
+///     fn foo<const M: u8>(&self) -> usize { 42 }
+///     //           ^ const parameter
 /// }
 ///
 /// fn main() {
 ///     let a = A;
-///     a.foo::<7>();
+///     let _b = a.foo::<{ 3 + 7 }>();
+///     //               ^^^^^^^^^ const argument
 /// }
 /// ```
+///
+/// Let's look at the call `a.foo::<{ 3 + 7 }>()` here. We do not know
+/// which `foo` is used until we know the type of `a`.
+///
+/// We only know the type of `a` once we are inside of `typeck(main)`.
+/// We also end up normalizing the type of `_b` during `typeck(main)` which
+/// requires us to evaluate the const argument.
+///
+/// To evaluate that const argument we need to know its type,
+/// which we would get using `type_of(const_arg)`. This requires us to
+/// resolve `foo` as it can be either `usize` or `u8` in this example.
+/// However, resolving `foo` once again requires `typeck(main)` to get the type of `a`,
+/// which results in a cycle.
+///
+/// In short we must not call `type_of(const_arg)` during `typeck(main)`.
+///
+/// When first creating the `ty::Const` of the const argument inside of `typeck` we have
+/// already resolved `foo` so we know which const parameter this argument instantiates.
+/// This means that we also know the expected result of `type_of(const_arg)` even if we
+/// aren't allowed to call that query: it is equal to `type_of(const_param)` which is
+/// trivial to compute.
+///
+/// If we now want to use that constant in a place which potentionally needs its type
+/// we also pass the type of its `const_param`. This is the point of `WithOptConstParam`,
+/// except that instead of a `Ty` we bundle the `DefId` of the const parameter.
+/// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some`
+/// to get the type of `did`.
 #[derive(Copy, Clone, Debug, TypeFoldable, Lift, TyEncodable, TyDecodable)]
 #[derive(PartialEq, Eq, PartialOrd, Ord)]
 #[derive(Hash, HashStable)]
@@ -1721,7 +1746,7 @@ pub struct WithOptConstParam<T> {
     ///
     /// Note that even if `did` is a const argument, this may still be `None`.
     /// All queries taking `WithOptConstParam` start by calling `tcx.opt_const_param_of(def.did)`
-    /// to potentially update `param_did` in case it `None`.
+    /// to potentially update `param_did` in the case it is `None`.
     pub const_param_did: Option<DefId>,
 }
 
index ec90f063a55240fb4afcca9094b010bcbbd77eae..c2165db278fa0f946ac4cc488a4cc5d2ceb28d30 100644 (file)
         return Ok(());
     }
 
+    struct FoundParam;
     struct UsedParamsNeedSubstVisitor<'tcx> {
         tcx: TyCtxt<'tcx>,
     }
 
     impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
-        type BreakTy = ();
+        type BreakTy = FoundParam;
 
         fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
             if !c.needs_subst() {
@@ -26,7 +27,7 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
             }
 
             match c.val {
-                ty::ConstKind::Param(..) => ControlFlow::BREAK,
+                ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
                 _ => c.super_visit_with(self),
             }
         }
@@ -37,7 +38,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
             }
 
             match *ty.kind() {
-                ty::Param(_) => ControlFlow::BREAK,
+                ty::Param(_) => ControlFlow::Break(FoundParam),
                 ty::Closure(def_id, substs)
                 | ty::Generator(def_id, substs, ..)
                 | ty::FnDef(def_id, substs) => {
@@ -76,7 +77,7 @@ fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
     }
 
     let mut vis = UsedParamsNeedSubstVisitor { tcx };
-    if ty.visit_with(&mut vis).is_break() {
+    if matches!(ty.visit_with(&mut vis), ControlFlow::Break(FoundParam)) {
         throw_inval!(TooGeneric);
     } else {
         Ok(())
index e404afeb698a6809cf9209eb9a7ad51b7b7eb78c..e934d8ed9da5f9a18643254a53dbd46dff156cd2 100644 (file)
@@ -408,7 +408,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
             operands: asm
                 .operands
                 .iter()
-                .map(|op| {
+                .map(|(op, _op_sp)| {
                     match *op {
                         hir::InlineAsmOperand::In { reg, ref expr } => {
                             InlineAsmOperand::In { reg, expr: expr.to_ref() }
index b746256f5fefc609524b78f999367135a2bdf26b..22f308ff36dbaa5cd1737db34538f47cd834b502 100644 (file)
@@ -264,7 +264,7 @@ fn to_string(&self) -> String {
             TokenType::Ident => "identifier".to_string(),
             TokenType::Path => "path".to_string(),
             TokenType::Type => "type".to_string(),
-            TokenType::Const => "const".to_string(),
+            TokenType::Const => "a const expression".to_string(),
         }
     }
 }
index 956be925be815eac5b223d198ec1f47b3da6ac06..711e8e87c6c6e7d70133e7b24c7a305b752ab7ab 100644 (file)
@@ -347,7 +347,7 @@ fn check_asm_operand_type(
     }
 
     fn check_asm(&self, asm: &hir::InlineAsm<'tcx>) {
-        for (idx, op) in asm.operands.iter().enumerate() {
+        for (idx, (op, _op_sp)) in asm.operands.iter().enumerate() {
             match *op {
                 hir::InlineAsmOperand::In { reg, ref expr } => {
                     self.check_asm_operand_type(idx, reg, expr, asm.template, None);
index debb873beb93b9fbc90affa78a20036e4c302bde..a64c6fa319ca98f3874d0c8afa55e8bceada7676 100644 (file)
@@ -1174,7 +1174,7 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
                 };
 
                 // Do a first pass for writing outputs only
-                for op in asm.operands.iter().rev() {
+                for (op, _op_sp) in asm.operands.iter().rev() {
                     match op {
                         hir::InlineAsmOperand::In { .. }
                         | hir::InlineAsmOperand::Const { .. }
@@ -1197,7 +1197,7 @@ fn propagate_through_expr(&mut self, expr: &Expr<'_>, succ: LiveNode) -> LiveNod
 
                 // Then do a second pass for inputs
                 let mut succ = succ;
-                for op in asm.operands.iter().rev() {
+                for (op, _op_sp) in asm.operands.iter().rev() {
                     match op {
                         hir::InlineAsmOperand::In { expr, .. }
                         | hir::InlineAsmOperand::Const { expr, .. }
@@ -1454,7 +1454,7 @@ fn check_expr<'tcx>(this: &mut Liveness<'_, 'tcx>, expr: &'tcx Expr<'tcx>) {
         }
 
         hir::ExprKind::InlineAsm(ref asm) => {
-            for op in asm.operands {
+            for (op, _op_sp) in asm.operands {
                 match op {
                     hir::InlineAsmOperand::Out { expr, .. } => {
                         if let Some(expr) = expr {
index 6ef45cdd391de6e30ac5f6ddadcdb7168d079ce9..5b50ef8627b25482aa8213a9f78cc1338b4f8d3a 100644 (file)
@@ -1,10 +1,16 @@
+//! Checks validity of naked functions.
+
+use rustc_ast::InlineAsmOptions;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::intravisit::{ErasedMap, FnKind, NestedVisitorMap, Visitor};
+use rustc_hir::{ExprKind, HirId, InlineAsmOperand, StmtKind};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
+use rustc_session::lint::builtin::UNSUPPORTED_NAKED_FUNCTIONS;
 use rustc_span::symbol::sym;
 use rustc_span::Span;
+use rustc_target::spec::abi::Abi;
 
 fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalDefId) {
     tcx.hir().visit_item_likes_in_module(
@@ -33,27 +39,52 @@ fn visit_fn(
         fk: FnKind<'v>,
         _fd: &'tcx hir::FnDecl<'tcx>,
         body_id: hir::BodyId,
-        _span: Span,
-        _hir_id: hir::HirId,
+        span: Span,
+        hir_id: HirId,
     ) {
+        let ident_span;
+        let fn_header;
+
         match fk {
-            // Rejected during attribute check. Do not validate further.
-            FnKind::Closure(..) => return,
-            FnKind::ItemFn(..) | FnKind::Method(..) => {}
+            FnKind::Closure(..) => {
+                // Closures with a naked attribute are rejected during attribute
+                // check. Don't validate them any further.
+                return;
+            }
+            FnKind::ItemFn(ident, _, ref header, ..) => {
+                ident_span = ident.span;
+                fn_header = header;
+            }
+
+            FnKind::Method(ident, ref sig, ..) => {
+                ident_span = ident.span;
+                fn_header = &sig.header;
+            }
         }
 
         let naked = fk.attrs().iter().any(|attr| attr.has_name(sym::naked));
         if naked {
             let body = self.tcx.hir().body(body_id);
-            check_params(self.tcx, body);
-            check_body(self.tcx, body);
+            check_abi(self.tcx, hir_id, fn_header.abi, ident_span);
+            check_no_patterns(self.tcx, body.params);
+            check_no_parameters_use(self.tcx, body);
+            check_asm(self.tcx, hir_id, body, span);
         }
     }
 }
 
+/// Checks that function uses non-Rust ABI.
+fn check_abi(tcx: TyCtxt<'_>, hir_id: HirId, abi: Abi, fn_ident_span: Span) {
+    if abi == Abi::Rust {
+        tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, fn_ident_span, |lint| {
+            lint.build("Rust ABI is unsupported in naked functions").emit();
+        });
+    }
+}
+
 /// Checks that parameters don't use patterns. Mirrors the checks for function declarations.
-fn check_params(tcx: TyCtxt<'_>, body: &hir::Body<'_>) {
-    for param in body.params {
+fn check_no_patterns(tcx: TyCtxt<'_>, params: &[hir::Param<'_>]) {
+    for param in params {
         match param.pat.kind {
             hir::PatKind::Wild
             | hir::PatKind::Binding(hir::BindingAnnotation::Unannotated, _, _, None) => {}
@@ -69,23 +100,23 @@ fn check_params(tcx: TyCtxt<'_>, body: &hir::Body<'_>) {
     }
 }
 
-/// Checks that function parameters aren't referenced in the function body.
-fn check_body<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>) {
+/// Checks that function parameters aren't used in the function body.
+fn check_no_parameters_use<'tcx>(tcx: TyCtxt<'tcx>, body: &'tcx hir::Body<'tcx>) {
     let mut params = hir::HirIdSet::default();
     for param in body.params {
         param.pat.each_binding(|_binding_mode, hir_id, _span, _ident| {
             params.insert(hir_id);
         });
     }
-    CheckBody { tcx, params }.visit_body(body);
+    CheckParameters { tcx, params }.visit_body(body);
 }
 
-struct CheckBody<'tcx> {
+struct CheckParameters<'tcx> {
     tcx: TyCtxt<'tcx>,
     params: hir::HirIdSet,
 }
 
-impl<'tcx> Visitor<'tcx> for CheckBody<'tcx> {
+impl<'tcx> Visitor<'tcx> for CheckParameters<'tcx> {
     type Map = ErasedMap<'tcx>;
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
@@ -103,11 +134,189 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                     .sess
                     .struct_span_err(
                         expr.span,
-                        "use of parameters not allowed inside naked functions",
+                        "referencing function parameters is not allowed in naked functions",
                     )
+                    .help("follow the calling convention in asm block to use parameters")
                     .emit();
+                return;
             }
         }
         hir::intravisit::walk_expr(self, expr);
     }
 }
+
+/// Checks that function body contains a single inline assembly block.
+fn check_asm<'tcx>(tcx: TyCtxt<'tcx>, hir_id: HirId, body: &'tcx hir::Body<'tcx>, fn_span: Span) {
+    let mut this = CheckInlineAssembly { tcx, items: Vec::new() };
+    this.visit_body(body);
+    if let &[(ItemKind::Asm, _)] = &this.items[..] {
+        // Ok.
+    } else {
+        tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, fn_span, |lint| {
+            let mut diag = lint.build("naked functions must contain a single asm block");
+            let mut has_asm = false;
+            for &(kind, span) in &this.items {
+                match kind {
+                    ItemKind::Asm if has_asm => {
+                        diag.span_label(
+                            span,
+                            "multiple asm blocks are unsupported in naked functions",
+                        );
+                    }
+                    ItemKind::Asm => has_asm = true,
+                    ItemKind::NonAsm => {
+                        diag.span_label(span, "non-asm is unsupported in naked functions");
+                    }
+                }
+            }
+            diag.emit();
+        });
+    }
+}
+
+struct CheckInlineAssembly<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    items: Vec<(ItemKind, Span)>,
+}
+
+#[derive(Copy, Clone)]
+enum ItemKind {
+    Asm,
+    NonAsm,
+}
+
+impl<'tcx> CheckInlineAssembly<'tcx> {
+    fn check_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, span: Span) {
+        match expr.kind {
+            ExprKind::Box(..)
+            | ExprKind::ConstBlock(..)
+            | ExprKind::Array(..)
+            | ExprKind::Call(..)
+            | ExprKind::MethodCall(..)
+            | ExprKind::Tup(..)
+            | ExprKind::Binary(..)
+            | ExprKind::Unary(..)
+            | ExprKind::Lit(..)
+            | ExprKind::Cast(..)
+            | ExprKind::Type(..)
+            | ExprKind::Loop(..)
+            | ExprKind::Match(..)
+            | ExprKind::Closure(..)
+            | ExprKind::Assign(..)
+            | ExprKind::AssignOp(..)
+            | ExprKind::Field(..)
+            | ExprKind::Index(..)
+            | ExprKind::Path(..)
+            | ExprKind::AddrOf(..)
+            | ExprKind::Break(..)
+            | ExprKind::Continue(..)
+            | ExprKind::Ret(..)
+            | ExprKind::Struct(..)
+            | ExprKind::Repeat(..)
+            | ExprKind::Yield(..) => {
+                self.items.push((ItemKind::NonAsm, span));
+            }
+
+            ExprKind::InlineAsm(ref asm) => {
+                self.items.push((ItemKind::Asm, span));
+                self.check_inline_asm(expr.hir_id, asm, span);
+            }
+
+            ExprKind::LlvmInlineAsm(..) => {
+                self.items.push((ItemKind::Asm, span));
+                self.tcx.struct_span_lint_hir(
+                    UNSUPPORTED_NAKED_FUNCTIONS,
+                    expr.hir_id,
+                    span,
+                    |lint| {
+                        lint.build(
+                            "the LLVM-style inline assembly is unsupported in naked functions",
+                        )
+                        .help("use the new asm! syntax specified in RFC 2873")
+                        .emit();
+                    },
+                );
+            }
+
+            ExprKind::DropTemps(..) | ExprKind::Block(..) | ExprKind::Err => {
+                hir::intravisit::walk_expr(self, expr);
+            }
+        }
+    }
+
+    fn check_inline_asm(&self, hir_id: HirId, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) {
+        let unsupported_operands: Vec<Span> = asm
+            .operands
+            .iter()
+            .filter_map(|&(ref op, op_sp)| match op {
+                InlineAsmOperand::Const { .. } | InlineAsmOperand::Sym { .. } => None,
+                InlineAsmOperand::In { .. }
+                | InlineAsmOperand::Out { .. }
+                | InlineAsmOperand::InOut { .. }
+                | InlineAsmOperand::SplitInOut { .. } => Some(op_sp),
+            })
+            .collect();
+        if !unsupported_operands.is_empty() {
+            self.tcx.struct_span_lint_hir(
+                UNSUPPORTED_NAKED_FUNCTIONS,
+                hir_id,
+                unsupported_operands,
+                |lint| {
+                    lint.build("only `const` and `sym` operands are supported in naked functions")
+                        .emit();
+                },
+            );
+        }
+
+        let unsupported_options: Vec<&'static str> = [
+            (InlineAsmOptions::NOMEM, "`nomem`"),
+            (InlineAsmOptions::NOSTACK, "`nostack`"),
+            (InlineAsmOptions::PRESERVES_FLAGS, "`preserves_flags`"),
+            (InlineAsmOptions::PURE, "`pure`"),
+            (InlineAsmOptions::READONLY, "`readonly`"),
+        ]
+        .iter()
+        .filter_map(|&(option, name)| if asm.options.contains(option) { Some(name) } else { None })
+        .collect();
+
+        if !unsupported_options.is_empty() {
+            self.tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, span, |lint| {
+                lint.build(&format!(
+                    "asm options unsupported in naked functions: {}",
+                    unsupported_options.join(", ")
+                ))
+                .emit();
+            });
+        }
+
+        if !asm.options.contains(InlineAsmOptions::NORETURN) {
+            self.tcx.struct_span_lint_hir(UNSUPPORTED_NAKED_FUNCTIONS, hir_id, span, |lint| {
+                lint.build("asm in naked functions must use `noreturn` option").emit();
+            });
+        }
+    }
+}
+
+impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> {
+    type Map = ErasedMap<'tcx>;
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+
+    fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) {
+        match stmt.kind {
+            StmtKind::Item(..) => {}
+            StmtKind::Local(..) => {
+                self.items.push((ItemKind::NonAsm, stmt.span));
+            }
+            StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => {
+                self.check_expr(expr, stmt.span);
+            }
+        }
+    }
+
+    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
+        self.check_expr(&expr, expr.span);
+    }
+}
index 54743ef9ce9115cd2349ee2cbcf002edb55fea92..33cd509cbb8df12b6f4deedb14cddf55942b3355 100644 (file)
@@ -49,7 +49,7 @@ fn normalize<T>(&self, value: T) -> Result<Normalized<'tcx, T>, NoSolution>
             self.param_env,
         );
         if !value.has_projections() {
-            return Ok(Normalized { value: value.clone(), obligations: vec![] });
+            return Ok(Normalized { value, obligations: vec![] });
         }
 
         let mut normalizer = QueryNormalizer {
index 0db5fda272a262db2436215889e865b64d4c2232..b7e77f389f8575c9500156ed57eebeef00e5b64c 100644 (file)
@@ -44,6 +44,13 @@ fn generic_arg_mismatch_err(
             // the match is non-exhaustive.
             _ => bug!("invalid generic parameter kind {}", kind),
         };
+
+        if let ParamKindOrd::Const { .. } = kind_ord {
+            if let GenericArg::Type(hir::Ty { kind: hir::TyKind::Infer, .. }) = arg {
+                err.help("const arguments cannot yet be inferred with `_`");
+            }
+        }
+
         let arg_ord = match arg {
             GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
             GenericArg::Type(_) => ParamKindOrd::Type,
index 489d836298f8700ae9b4738f1a5a82cae39b026e..ec7369fd3e8ee6c96329ae849e36438a9244843d 100644 (file)
@@ -462,39 +462,25 @@ pub(super) fn check_opaque<'tcx>(
 
 /// Checks that an opaque type does not use `Self` or `T::Foo` projections that would result
 /// in "inheriting lifetimes".
+#[instrument(skip(tcx, span))]
 pub(super) fn check_opaque_for_inheriting_lifetimes(
     tcx: TyCtxt<'tcx>,
     def_id: LocalDefId,
     span: Span,
 ) {
     let item = tcx.hir().expect_item(tcx.hir().local_def_id_to_hir_id(def_id));
-    debug!(
-        "check_opaque_for_inheriting_lifetimes: def_id={:?} span={:?} item={:?}",
-        def_id, span, item
-    );
-
-    #[derive(Debug)]
-    struct ProhibitOpaqueVisitor<'tcx> {
-        opaque_identity_ty: Ty<'tcx>,
-        generics: &'tcx ty::Generics,
-    }
+    debug!(?item, ?span);
 
-    impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
-        type BreakTy = Option<Ty<'tcx>>;
-
-        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
-            debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
-            if t != self.opaque_identity_ty && t.super_visit_with(self).is_break() {
-                return ControlFlow::Break(Some(t));
-            }
-            ControlFlow::CONTINUE
-        }
+    struct FoundParentLifetime;
+    struct FindParentLifetimeVisitor<'tcx>(&'tcx ty::Generics);
+    impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> {
+        type BreakTy = FoundParentLifetime;
 
         fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
-            debug!("check_opaque_for_inheriting_lifetimes: (visit_region) r={:?}", r);
+            debug!("FindParentLifetimeVisitor: r={:?}", r);
             if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
-                if *index < self.generics.parent_count as u32 {
-                    return ControlFlow::Break(None);
+                if *index < self.0.parent_count as u32 {
+                    return ControlFlow::Break(FoundParentLifetime);
                 } else {
                     return ControlFlow::CONTINUE;
                 }
@@ -505,7 +491,7 @@ fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
 
         fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
             if let ty::ConstKind::Unevaluated(..) = c.val {
-                // FIXME(#72219) We currenctly don't detect lifetimes within substs
+                // FIXME(#72219) We currently don't detect lifetimes within substs
                 // which would violate this check. Even though the particular substitution is not used
                 // within the const, this should still be fixed.
                 return ControlFlow::CONTINUE;
@@ -514,6 +500,26 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
         }
     }
 
+    #[derive(Debug)]
+    struct ProhibitOpaqueVisitor<'tcx> {
+        opaque_identity_ty: Ty<'tcx>,
+        generics: &'tcx ty::Generics,
+    }
+
+    impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
+        type BreakTy = Ty<'tcx>;
+
+        fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+            debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
+            if t == self.opaque_identity_ty {
+                ControlFlow::CONTINUE
+            } else {
+                t.super_visit_with(&mut FindParentLifetimeVisitor(self.generics))
+                    .map_break(|FoundParentLifetime| t)
+            }
+        }
+    }
+
     if let ItemKind::OpaqueTy(hir::OpaqueTy {
         origin: hir::OpaqueTyOrigin::AsyncFn | hir::OpaqueTyOrigin::FnReturn,
         ..
@@ -555,14 +561,12 @@ fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy
 
             if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) {
                 if snippet == "Self" {
-                    if let Some(ty) = ty {
-                        err.span_suggestion(
-                            span,
-                            "consider spelling out the type instead",
-                            format!("{:?}", ty),
-                            Applicability::MaybeIncorrect,
-                        );
-                    }
+                    err.span_suggestion(
+                        span,
+                        "consider spelling out the type instead",
+                        format!("{:?}", ty),
+                        Applicability::MaybeIncorrect,
+                    );
                 }
             }
             err.emit();
index 26962d2222d32f592c87264183e5e9c8372cc855..b8a2a4779d9853aa357b9ed6eea2fff9b74ae69c 100644 (file)
@@ -1929,7 +1929,7 @@ fn check_expr_asm_operand(&self, expr: &'tcx hir::Expr<'tcx>, is_input: bool) {
     }
 
     fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>) -> Ty<'tcx> {
-        for op in asm.operands {
+        for (op, _op_sp) in asm.operands {
             match op {
                 hir::InlineAsmOperand::In { expr, .. } | hir::InlineAsmOperand::Const { expr } => {
                     self.check_expr_asm_operand(expr, true);
index 483ab2f58f222f51f608a3ec6ad3cc2df55fa106..0c1578498b846bfcf73ebc2283b3838fb64aa221 100644 (file)
@@ -44,8 +44,8 @@ struct InherentCollect<'tcx> {
 
 impl ItemLikeVisitor<'v> for InherentCollect<'tcx> {
     fn visit_item(&mut self, item: &hir::Item<'_>) {
-        let ty = match item.kind {
-            hir::ItemKind::Impl { of_trait: None, ref self_ty, .. } => self_ty,
+        let (ty, assoc_items) = match item.kind {
+            hir::ItemKind::Impl { of_trait: None, ref self_ty, items, .. } => (self_ty, items),
             _ => return,
         };
 
@@ -70,6 +70,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "bool",
                     "bool",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Char => {
@@ -80,6 +81,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "char",
                     "char",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Str => {
@@ -90,6 +92,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "str",
                     "str",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Slice(slice_item) if slice_item == self.tcx.types.u8 => {
@@ -100,6 +103,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "slice_u8",
                     "[u8]",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Slice(_) => {
@@ -110,6 +114,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "slice",
                     "[T]",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Array(_, _) => {
@@ -120,6 +125,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "array",
                     "[T; N]",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Not })
@@ -132,6 +138,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "const_slice_ptr",
                     "*const [T]",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::RawPtr(ty::TypeAndMut { ty: inner, mutbl: hir::Mutability::Mut })
@@ -144,6 +151,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "mut_slice_ptr",
                     "*mut [T]",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Not }) => {
@@ -154,6 +162,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "const_ptr",
                     "*const T",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::RawPtr(ty::TypeAndMut { ty: _, mutbl: hir::Mutability::Mut }) => {
@@ -164,6 +173,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "mut_ptr",
                     "*mut T",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Int(ast::IntTy::I8) => {
@@ -174,6 +184,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "i8",
                     "i8",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Int(ast::IntTy::I16) => {
@@ -184,6 +195,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "i16",
                     "i16",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Int(ast::IntTy::I32) => {
@@ -194,6 +206,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "i32",
                     "i32",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Int(ast::IntTy::I64) => {
@@ -204,6 +217,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "i64",
                     "i64",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Int(ast::IntTy::I128) => {
@@ -214,6 +228,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "i128",
                     "i128",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Int(ast::IntTy::Isize) => {
@@ -224,6 +239,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "isize",
                     "isize",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Uint(ast::UintTy::U8) => {
@@ -234,6 +250,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "u8",
                     "u8",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Uint(ast::UintTy::U16) => {
@@ -244,6 +261,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "u16",
                     "u16",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Uint(ast::UintTy::U32) => {
@@ -254,6 +272,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "u32",
                     "u32",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Uint(ast::UintTy::U64) => {
@@ -264,6 +283,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "u64",
                     "u64",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Uint(ast::UintTy::U128) => {
@@ -274,6 +294,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "u128",
                     "u128",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Uint(ast::UintTy::Usize) => {
@@ -284,6 +305,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "usize",
                     "usize",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Float(ast::FloatTy::F32) => {
@@ -294,6 +316,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "f32",
                     "f32",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Float(ast::FloatTy::F64) => {
@@ -304,6 +327,7 @@ fn visit_item(&mut self, item: &hir::Item<'_>) {
                     "f64",
                     "f64",
                     item.span,
+                    assoc_items,
                 );
             }
             ty::Error(_) => {}
@@ -369,6 +393,7 @@ fn check_primitive_impl(
         lang: &str,
         ty: &str,
         span: Span,
+        assoc_items: &[hir::ImplItemRef<'_>],
     ) {
         match (lang_def_id, lang_def_id2) {
             (Some(lang_def_id), _) if lang_def_id == impl_def_id.to_def_id() => {
@@ -378,6 +403,32 @@ fn check_primitive_impl(
                 // OK
             }
             _ => {
+                let to_implement = if assoc_items.len() == 0 {
+                    String::new()
+                } else {
+                    let plural = assoc_items.len() > 1;
+                    let assoc_items_kind = {
+                        let item_types = assoc_items.iter().map(|x| x.kind);
+                        if item_types.clone().all(|x| x == hir::AssocItemKind::Const) {
+                            "constant"
+                        } else if item_types
+                            .clone()
+                            .all(|x| matches! {x, hir::AssocItemKind::Fn{ .. } })
+                        {
+                            "method"
+                        } else {
+                            "associated item"
+                        }
+                    };
+
+                    format!(
+                        " to implement {} {}{}",
+                        if plural { "these" } else { "this" },
+                        assoc_items_kind,
+                        if plural { "s" } else { "" }
+                    )
+                };
+
                 struct_span_err!(
                     self.tcx.sess,
                     span,
@@ -387,7 +438,7 @@ fn check_primitive_impl(
                     lang,
                     ty
                 )
-                .span_help(span, "consider using a trait to implement these methods")
+                .help(&format!("consider using a trait{}", to_implement))
                 .emit();
             }
         }
index 1b51d5e0182fde51426de0751acd373488cacdd8..95848ac2c076794dcc846168765f4a3046dc1edc 100644 (file)
@@ -243,7 +243,7 @@ pub fn walk_expr(&mut self, expr: &hir::Expr<'_>) {
             }
 
             hir::ExprKind::InlineAsm(ref asm) => {
-                for op in asm.operands {
+                for (op, _op_sp) in asm.operands {
                     match op {
                         hir::InlineAsmOperand::In { expr, .. }
                         | hir::InlineAsmOperand::Const { expr, .. }
index 5ede1ba8e2c104076aa205dff4ff2edd5e87a738..4834ca74b8270eaf0a09260fc62f10d4880ba387 100644 (file)
@@ -56,6 +56,20 @@ pub fn break_value(self) -> Option<B> {
             ControlFlow::Break(x) => Some(x),
         }
     }
+
+    /// Maps `ControlFlow<B, C>` to `ControlFlow<T, C>` by applying a function
+    /// to the break value in case it exists.
+    #[inline]
+    #[unstable(feature = "control_flow_enum", reason = "new API", issue = "75744")]
+    pub fn map_break<T, F>(self, f: F) -> ControlFlow<T, C>
+    where
+        F: FnOnce(B) -> T,
+    {
+        match self {
+            ControlFlow::Continue(x) => ControlFlow::Continue(x),
+            ControlFlow::Break(x) => ControlFlow::Break(f(x)),
+        }
+    }
 }
 
 impl<R: Try> ControlFlow<R, R::Ok> {
index a944514f694b68d63819578ed9ba55338edfdced..83cf47c8c8f61edbde4661068275e210d55a50ae 100644 (file)
@@ -1131,6 +1131,13 @@ pub fn rfind<'a, P>(&'a self, pat: P) -> Option<usize>
     /// assert_eq!(v, ["lion", "tiger", "leopard"]);
     /// ```
     ///
+    /// If the pattern is a slice of chars, split on each occurrence of any of the characters:
+    ///
+    /// ```
+    /// let v: Vec<&str> = "2020-11-03 23:59".split(&['-', ' ', ':', '@'][..]).collect();
+    /// assert_eq!(v, ["2020", "11", "03", "23", "59"]);
+    /// ```
+    ///
     /// A more complex pattern, using a closure:
     ///
     /// ```
index e2f0870ef0e398c5ee06ee82ede85d157f301c5a..d1b0ad9e5f847cd34a7292ca5e7d0abab7ca8127 100644 (file)
@@ -1211,7 +1211,8 @@ pub fn copy(from: &Path, to: &Path) -> io::Result<u64> {
     use super::kernel_copy::{copy_regular_files, CopyResult};
 
     match copy_regular_files(reader.as_raw_fd(), writer.as_raw_fd(), max_len) {
-        CopyResult::Ended(result) => result,
+        CopyResult::Ended(bytes) => Ok(bytes),
+        CopyResult::Error(e, _) => Err(e),
         CopyResult::Fallback(written) => match io::copy::generic_copy(&mut reader, &mut writer) {
             Ok(bytes) => Ok(bytes + written),
             Err(e) => Err(e),
index f08c828ecfff03419110275a0f0c3927608f0482..5bfac80315348b959a5671805ed0fcc115514459 100644 (file)
@@ -167,10 +167,11 @@ fn copy(self) -> Result<u64> {
 
             if input_meta.copy_file_range_candidate() && output_meta.copy_file_range_candidate() {
                 let result = copy_regular_files(readfd, writefd, max_write);
+                result.update_take(reader);
 
                 match result {
-                    CopyResult::Ended(Ok(bytes_copied)) => return Ok(bytes_copied + written),
-                    CopyResult::Ended(err) => return err,
+                    CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
+                    CopyResult::Error(e, _) => return Err(e),
                     CopyResult::Fallback(bytes) => written += bytes,
                 }
             }
@@ -182,20 +183,22 @@ fn copy(self) -> Result<u64> {
             // fall back to the generic copy loop.
             if input_meta.potential_sendfile_source() {
                 let result = sendfile_splice(SpliceMode::Sendfile, readfd, writefd, max_write);
+                result.update_take(reader);
 
                 match result {
-                    CopyResult::Ended(Ok(bytes_copied)) => return Ok(bytes_copied + written),
-                    CopyResult::Ended(err) => return err,
+                    CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
+                    CopyResult::Error(e, _) => return Err(e),
                     CopyResult::Fallback(bytes) => written += bytes,
                 }
             }
 
             if input_meta.maybe_fifo() || output_meta.maybe_fifo() {
                 let result = sendfile_splice(SpliceMode::Splice, readfd, writefd, max_write);
+                result.update_take(reader);
 
                 match result {
-                    CopyResult::Ended(Ok(bytes_copied)) => return Ok(bytes_copied + written),
-                    CopyResult::Ended(err) => return err,
+                    CopyResult::Ended(bytes_copied) => return Ok(bytes_copied + written),
+                    CopyResult::Error(e, _) => return Err(e),
                     CopyResult::Fallback(0) => { /* use the fallback below */ }
                     CopyResult::Fallback(_) => {
                         unreachable!("splice should not return > 0 bytes on the fallback path")
@@ -225,6 +228,9 @@ fn drain_to<W: Write>(&mut self, _writer: &mut W, _limit: u64) -> Result<u64> {
         Ok(0)
     }
 
+    /// Updates `Take` wrappers to remove the number of bytes copied.
+    fn taken(&mut self, _bytes: u64) {}
+
     /// The minimum of the limit of all `Take<_>` wrappers, `u64::MAX` otherwise.
     /// This method does not account for data `BufReader` buffers and would underreport
     /// the limit of a `Take<BufReader<Take<_>>>` type. Thus its result is only valid
@@ -251,6 +257,10 @@ fn drain_to<W: Write>(&mut self, writer: &mut W, limit: u64) -> Result<u64> {
         (**self).drain_to(writer, limit)
     }
 
+    fn taken(&mut self, bytes: u64) {
+        (**self).taken(bytes);
+    }
+
     fn min_limit(&self) -> u64 {
         (**self).min_limit()
     }
@@ -407,6 +417,11 @@ fn drain_to<W: Write>(&mut self, writer: &mut W, outer_limit: u64) -> Result<u64
         Ok(bytes_drained)
     }
 
+    fn taken(&mut self, bytes: u64) {
+        self.set_limit(self.limit() - bytes);
+        self.get_mut().taken(bytes);
+    }
+
     fn min_limit(&self) -> u64 {
         min(Take::limit(self), self.get_ref().min_limit())
     }
@@ -432,6 +447,10 @@ fn drain_to<W: Write>(&mut self, writer: &mut W, outer_limit: u64) -> Result<u64
         Ok(bytes as u64 + inner_bytes)
     }
 
+    fn taken(&mut self, bytes: u64) {
+        self.get_mut().taken(bytes);
+    }
+
     fn min_limit(&self) -> u64 {
         self.get_ref().min_limit()
     }
@@ -457,10 +476,21 @@ fn fd_to_meta<T: AsRawFd>(fd: &T) -> FdMeta {
 }
 
 pub(super) enum CopyResult {
-    Ended(Result<u64>),
+    Ended(u64),
+    Error(Error, u64),
     Fallback(u64),
 }
 
+impl CopyResult {
+    fn update_take(&self, reader: &mut impl CopyRead) {
+        match *self {
+            CopyResult::Fallback(bytes)
+            | CopyResult::Ended(bytes)
+            | CopyResult::Error(_, bytes) => reader.taken(bytes),
+        }
+    }
+}
+
 /// linux-specific implementation that will attempt to use copy_file_range for copy offloading
 /// as the name says, it only works on regular files
 ///
@@ -527,7 +557,7 @@ fn copy_file_range(
                 // - copying from an overlay filesystem in docker. reported to occur on fedora 32.
                 return CopyResult::Fallback(0);
             }
-            Ok(0) => return CopyResult::Ended(Ok(written)), // reached EOF
+            Ok(0) => return CopyResult::Ended(written), // reached EOF
             Ok(ret) => written += ret as u64,
             Err(err) => {
                 return match err.raw_os_error() {
@@ -545,12 +575,12 @@ fn copy_file_range(
                         assert_eq!(written, 0);
                         CopyResult::Fallback(0)
                     }
-                    _ => CopyResult::Ended(Err(err)),
+                    _ => CopyResult::Error(err, written),
                 };
             }
         }
     }
-    CopyResult::Ended(Ok(written))
+    CopyResult::Ended(written)
 }
 
 #[derive(PartialEq)]
@@ -623,10 +653,10 @@ fn splice(
                     Some(os_err) if mode == SpliceMode::Sendfile && os_err == libc::EOVERFLOW => {
                         CopyResult::Fallback(written)
                     }
-                    _ => CopyResult::Ended(Err(err)),
+                    _ => CopyResult::Error(err, written),
                 };
             }
         }
     }
-    CopyResult::Ended(Ok(written))
+    CopyResult::Ended(written)
 }
index 554ebd94022341dfd08d7f1bc56cc3d8dba17bcb..3937a1ffa38b5fee6d7271c3e6c755ca262cae52 100644 (file)
@@ -42,8 +42,15 @@ fn copy_specialization() -> Result<()> {
         assert_eq!(sink.buffer(), b"wxyz");
 
         let copied = crate::io::copy(&mut source, &mut sink)?;
-        assert_eq!(copied, 10);
-        assert_eq!(sink.buffer().len(), 0);
+        assert_eq!(copied, 10, "copy obeyed limit imposed by Take");
+        assert_eq!(sink.buffer().len(), 0, "sink buffer was flushed");
+        assert_eq!(source.limit(), 0, "outer Take was exhausted");
+        assert_eq!(source.get_ref().buffer().len(), 0, "source buffer should be drained");
+        assert_eq!(
+            source.get_ref().get_ref().limit(),
+            1,
+            "inner Take allowed reading beyond end of file, some bytes should be left"
+        );
 
         let mut sink = sink.into_inner()?;
         sink.seek(SeekFrom::Start(0))?;
@@ -210,7 +217,7 @@ fn bench_socket_pipe_socket_copy(b: &mut test::Bencher) {
     );
 
     match probe {
-        CopyResult::Ended(Ok(1)) => {
+        CopyResult::Ended(1) => {
             // splice works
         }
         _ => {
index 76056637a4cf911f216dc2357ea1de548bdd05db..b095c2dde628536baedfb755d55bea55cc0671f3 100644 (file)
@@ -78,9 +78,11 @@ fn test_env_set_var() {
 }
 
 #[test]
-#[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
+#[cfg_attr(not(any(unix, windows)), ignore, allow(unused))]
 #[allow(deprecated)]
 fn env_home_dir() {
+    use std::path::PathBuf;
+
     fn var_to_os_string(var: Result<String, VarError>) -> Option<OsString> {
         match var {
             Ok(var) => Some(OsString::from(var)),
@@ -91,8 +93,6 @@ fn var_to_os_string(var: Result<String, VarError>) -> Option<OsString> {
 
     cfg_if::cfg_if! {
         if #[cfg(unix)] {
-            use std::path::PathBuf;
-
             let oldhome = var_to_os_string(var("HOME"));
 
             set_var("HOME", "/home/MountainView");
@@ -110,8 +110,6 @@ fn var_to_os_string(var: Result<String, VarError>) -> Option<OsString> {
 
             if let Some(oldhome) = oldhome { set_var("HOME", oldhome); }
         } else if #[cfg(windows)] {
-            use std::path::PathBuf;
-
             let oldhome = var_to_os_string(var("HOME"));
             let olduserprofile = var_to_os_string(var("USERPROFILE"));
 
index 8c344338de7a589978344b049bcadc17f2f8b396..16274430902e42486f3020117f4020e74b4c5efe 100644 (file)
@@ -2263,7 +2263,7 @@ fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.span.clean(cx),
-            def_id: DefId::local(CRATE_DEF_INDEX),
+            def_id: cx.tcx.hir().local_def_id(self.id).to_def_id(),
             visibility: self.vis.clean(cx),
             stability: None,
             const_stability: None,
index c080ad21c0f33f5d6a9c52e1195d771e12e4594a..5f640bfddf10b95760ba0f2e7d2dfc2a6c58916c 100644 (file)
@@ -151,7 +151,12 @@ fn item(&mut self, item: clean::Item, cache: &Cache) -> Result<(), Error> {
             } else if let types::ItemEnum::EnumItem(ref mut e) = new_item.inner {
                 e.impls = self.get_impls(id, cache)
             }
-            self.index.borrow_mut().insert(id.into(), new_item);
+            let removed = self.index.borrow_mut().insert(id.into(), new_item.clone());
+            // FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
+            // to make sure the items are unique.
+            if let Some(old_item) = removed {
+                assert_eq!(old_item, new_item);
+            }
         }
 
         Ok(())
index 10bf2a2acc5b9e908d95aeb9b163ad79064053c5..9335fe9be1a4b15e9d521eefc397f1fce916e296 100644 (file)
@@ -11,7 +11,7 @@
 /// A `Crate` is the root of the emitted JSON blob. It contains all type/documentation information
 /// about the language items in the local crate, as well as info about external items to allow
 /// tools to find or link to them.
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Crate {
     /// The id of the root [`Module`] item of the local crate.
     pub root: Id,
@@ -31,7 +31,7 @@ pub struct Crate {
     pub format_version: u32,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct ExternalCrate {
     pub name: String,
     pub html_root_url: Option<String>,
@@ -41,7 +41,7 @@ pub struct ExternalCrate {
 /// information. This struct should contain enough to generate a link/reference to the item in
 /// question, or can be used by a tool that takes the json output of multiple crates to find
 /// the actual item definition with all the relevant info.
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct ItemSummary {
     /// Can be used to look up the name and html_root_url of the crate this item came from in the
     /// `external_crates` map.
@@ -53,7 +53,7 @@ pub struct ItemSummary {
     pub kind: ItemKind,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Item {
     /// The unique identifier of this item. Can be used to find this item in various mappings.
     pub id: Id,
@@ -79,7 +79,7 @@ pub struct Item {
     pub inner: ItemEnum,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Span {
     /// The path to the source file for this span relative to the path `rustdoc` was invoked with.
     pub filename: PathBuf,
@@ -89,14 +89,14 @@ pub struct Span {
     pub end: (usize, usize),
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Deprecation {
     pub since: Option<String>,
     pub note: Option<String>,
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum Visibility {
     Public,
     /// For the most part items are private by default. The exceptions are associated items of
@@ -112,7 +112,7 @@ pub enum Visibility {
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum GenericArgs {
     /// <'a, 32, B: Copy, C = u32>
     AngleBracketed { args: Vec<GenericArg>, bindings: Vec<TypeBinding> },
@@ -121,14 +121,14 @@ pub enum GenericArgs {
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum GenericArg {
     Lifetime(String),
     Type(Type),
     Const(Constant),
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Constant {
     #[serde(rename = "type")]
     pub type_: Type,
@@ -137,14 +137,14 @@ pub struct Constant {
     pub is_literal: bool,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct TypeBinding {
     pub name: String,
     pub binding: TypeBindingKind,
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum TypeBindingKind {
     Equality(Type),
     Constraint(Vec<GenericBound>),
@@ -154,7 +154,7 @@ pub enum TypeBindingKind {
 pub struct Id(pub String);
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum ItemKind {
     Module,
     ExternCrate,
@@ -184,7 +184,7 @@ pub enum ItemKind {
 }
 
 #[serde(untagged)]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum ItemEnum {
     ModuleItem(Module),
     ExternCrateItem {
@@ -231,13 +231,13 @@ pub enum ItemEnum {
     },
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Module {
     pub is_crate: bool,
     pub items: Vec<Id>,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Struct {
     pub struct_type: StructType,
     pub generics: Generics,
@@ -246,7 +246,7 @@ pub struct Struct {
     pub impls: Vec<Id>,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Enum {
     pub generics: Generics,
     pub variants_stripped: bool,
@@ -256,7 +256,7 @@ pub struct Enum {
 
 #[serde(rename_all = "snake_case")]
 #[serde(tag = "variant_kind", content = "variant_inner")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum Variant {
     Plain,
     Tuple(Vec<Type>),
@@ -264,14 +264,14 @@ pub enum Variant {
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum StructType {
     Plain,
     Tuple,
     Unit,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Function {
     pub decl: FnDecl,
     pub generics: Generics,
@@ -279,7 +279,7 @@ pub struct Function {
     pub abi: String,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Method {
     pub decl: FnDecl,
     pub generics: Generics,
@@ -287,20 +287,20 @@ pub struct Method {
     pub has_body: bool,
 }
 
-#[derive(Clone, Debug, Default, Serialize, Deserialize)]
+#[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)]
 pub struct Generics {
     pub params: Vec<GenericParamDef>,
     pub where_predicates: Vec<WherePredicate>,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct GenericParamDef {
     pub name: String,
     pub kind: GenericParamDefKind,
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum GenericParamDefKind {
     Lifetime,
     Type { bounds: Vec<GenericBound>, default: Option<Type> },
@@ -308,7 +308,7 @@ pub enum GenericParamDefKind {
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum WherePredicate {
     BoundPredicate { ty: Type, bounds: Vec<GenericBound> },
     RegionPredicate { lifetime: String, bounds: Vec<GenericBound> },
@@ -316,7 +316,7 @@ pub enum WherePredicate {
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum GenericBound {
     TraitBound {
         #[serde(rename = "trait")]
@@ -329,7 +329,7 @@ pub enum GenericBound {
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum TraitBoundModifier {
     None,
     Maybe,
@@ -338,7 +338,7 @@ pub enum TraitBoundModifier {
 
 #[serde(rename_all = "snake_case")]
 #[serde(tag = "kind", content = "inner")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum Type {
     /// Structs, enums, and traits
     ResolvedPath {
@@ -391,7 +391,7 @@ pub enum Type {
     },
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct FunctionPointer {
     pub is_unsafe: bool,
     pub generic_params: Vec<GenericParamDef>,
@@ -399,14 +399,14 @@ pub struct FunctionPointer {
     pub abi: String,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct FnDecl {
     pub inputs: Vec<(String, Type)>,
     pub output: Option<Type>,
     pub c_variadic: bool,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Trait {
     pub is_auto: bool,
     pub is_unsafe: bool,
@@ -416,13 +416,13 @@ pub struct Trait {
     pub implementors: Vec<Id>,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct TraitAlias {
     pub generics: Generics,
     pub params: Vec<GenericBound>,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Impl {
     pub is_unsafe: bool,
     pub generics: Generics,
@@ -438,7 +438,7 @@ pub struct Impl {
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Import {
     /// The full path being imported.
     pub span: String,
@@ -451,14 +451,14 @@ pub struct Import {
     pub glob: bool,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct ProcMacro {
     pub kind: MacroKind,
     pub helpers: Vec<String>,
 }
 
 #[serde(rename_all = "snake_case")]
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub enum MacroKind {
     /// A bang macro `foo!()`.
     Bang,
@@ -468,20 +468,20 @@ pub enum MacroKind {
     Derive,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Typedef {
     #[serde(rename = "type")]
     pub type_: Type,
     pub generics: Generics,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct OpaqueTy {
     pub bounds: Vec<GenericBound>,
     pub generics: Generics,
 }
 
-#[derive(Clone, Debug, Serialize, Deserialize)]
+#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
 pub struct Static {
     #[serde(rename = "type")]
     pub type_: Type,
diff --git a/src/test/rustdoc-json/nested.expected b/src/test/rustdoc-json/nested.expected
new file mode 100644 (file)
index 0000000..65bb0c5
--- /dev/null
@@ -0,0 +1,196 @@
+{
+  "crate_version": null,
+  "external_crates": {},
+  "format_version": 1,
+  "includes_private": false,
+  "index": {
+    "0:0": {
+      "attrs": [],
+      "crate_id": 0,
+      "deprecation": null,
+      "docs": "",
+      "id": "0:0",
+      "inner": {
+        "is_crate": true,
+        "items": [
+          "0:3"
+        ]
+      },
+      "kind": "module",
+      "links": {},
+      "name": "nested",
+      "source": {
+        "begin": [
+          2,
+          0
+        ],
+        "end": [
+          7,
+          1
+        ],
+        "filename": "$TEST_BASE_DIR/nested.rs"
+      },
+      "visibility": "public"
+    },
+    "0:3": {
+      "attrs": [],
+      "crate_id": 0,
+      "deprecation": null,
+      "docs": "",
+      "id": "0:3",
+      "inner": {
+        "is_crate": false,
+        "items": [
+          "0:7",
+          "0:4"
+        ]
+      },
+      "kind": "module",
+      "links": {},
+      "name": "l1",
+      "source": {
+        "begin": [
+          2,
+          0
+        ],
+        "end": [
+          7,
+          1
+        ],
+        "filename": "$TEST_BASE_DIR/nested.rs"
+      },
+      "visibility": "public"
+    },
+    "0:4": {
+      "attrs": [],
+      "crate_id": 0,
+      "deprecation": null,
+      "docs": "",
+      "id": "0:4",
+      "inner": {
+        "is_crate": false,
+        "items": [
+          "0:5"
+        ]
+      },
+      "kind": "module",
+      "links": {},
+      "name": "l3",
+      "source": {
+        "begin": [
+          3,
+          4
+        ],
+        "end": [
+          5,
+          5
+        ],
+        "filename": "$TEST_BASE_DIR/nested.rs"
+      },
+      "visibility": "public"
+    },
+    "0:5": {
+      "attrs": [],
+      "crate_id": 0,
+      "deprecation": null,
+      "docs": "",
+      "id": "0:5",
+      "inner": {
+        "fields": [],
+        "fields_stripped": false,
+        "generics": {
+          "params": [],
+          "where_predicates": []
+        },
+        "impls": [
+          "0:10",
+          "0:11",
+          "0:12",
+          "0:14",
+          "0:15"
+        ],
+        "struct_type": "unit"
+      },
+      "kind": "struct",
+      "links": {},
+      "name": "L4",
+      "source": {
+        "begin": [
+          4,
+          8
+        ],
+        "end": [
+          4,
+          22
+        ],
+        "filename": "$TEST_BASE_DIR/nested.rs"
+      },
+      "visibility": "public"
+    },
+    "0:7": {
+      "attrs": [],
+      "crate_id": 0,
+      "deprecation": null,
+      "docs": "",
+      "id": "0:7",
+      "inner": {
+        "glob": false,
+        "id": "0:5",
+        "name": "L4",
+        "span": "l3::L4"
+      },
+      "kind": "import",
+      "links": {},
+      "name": null,
+      "source": {
+        "begin": [
+          6,
+          4
+        ],
+        "end": [
+          6,
+          19
+        ],
+        "filename": "$TEST_BASE_DIR/nested.rs"
+      },
+      "visibility": "public"
+    }
+  },
+  "paths": {
+    "0:0": {
+      "crate_id": 0,
+      "kind": "module",
+      "path": [
+        "nested"
+      ]
+    },
+    "0:3": {
+      "crate_id": 0,
+      "kind": "module",
+      "path": [
+        "nested",
+        "l1"
+      ]
+    },
+    "0:4": {
+      "crate_id": 0,
+      "kind": "module",
+      "path": [
+        "nested",
+        "l1",
+        "l3"
+      ]
+    },
+    "0:5": {
+      "crate_id": 0,
+      "kind": "struct",
+      "path": [
+        "nested",
+        "l1",
+        "l3",
+        "L4"
+      ]
+    }
+  },
+  "root": "0:0"
+}
\ No newline at end of file
diff --git a/src/test/rustdoc-json/nested.rs b/src/test/rustdoc-json/nested.rs
new file mode 100644 (file)
index 0000000..e460b34
--- /dev/null
@@ -0,0 +1,7 @@
+// edition:2018
+pub mod l1 {
+    pub mod l3 {
+        pub struct L4;
+    }
+    pub use l3::L4;
+}
diff --git a/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs b/src/test/rustdoc/const-generics/lazy_normalization_consts/const-equate-pred.rs
new file mode 100644 (file)
index 0000000..6cc02f7
--- /dev/null
@@ -0,0 +1,18 @@
+#![crate_name = "foo"]
+#![feature(lazy_normalization_consts)]
+#![allow(incomplete_features)]
+
+// Checking if `Send` is implemented for `Hasher` requires us to evaluate a `ConstEquate` predicate,
+// which previously caused an ICE.
+
+pub struct Hasher<T> {
+    cv_stack: T,
+}
+
+unsafe impl<T: Default> Send for Hasher<T> {}
+
+// @has foo/struct.Foo.html
+// @has - '//code' 'impl Send for Foo'
+pub struct Foo {
+    hasher: Hasher<[u8; 3]>,
+}
diff --git a/src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs b/src/test/rustdoc/lazy_normalization_consts/const-equate-pred.rs
deleted file mode 100644 (file)
index 6cc02f7..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-#![crate_name = "foo"]
-#![feature(lazy_normalization_consts)]
-#![allow(incomplete_features)]
-
-// Checking if `Send` is implemented for `Hasher` requires us to evaluate a `ConstEquate` predicate,
-// which previously caused an ICE.
-
-pub struct Hasher<T> {
-    cv_stack: T,
-}
-
-unsafe impl<T: Default> Send for Hasher<T> {}
-
-// @has foo/struct.Foo.html
-// @has - '//code' 'impl Send for Foo'
-pub struct Foo {
-    hasher: Hasher<[u8; 3]>,
-}
diff --git a/src/test/ui/asm/naked-functions.rs b/src/test/ui/asm/naked-functions.rs
new file mode 100644 (file)
index 0000000..a46ca45
--- /dev/null
@@ -0,0 +1,169 @@
+// only-x86_64
+#![feature(asm)]
+#![feature(llvm_asm)]
+#![feature(naked_functions)]
+#![feature(or_patterns)]
+#![crate_type = "lib"]
+
+#[repr(C)]
+pub struct P { x: u8, y: u16 }
+
+#[naked]
+pub unsafe extern "C" fn patterns(
+    mut a: u32,
+    //~^ ERROR patterns not allowed in naked function parameters
+    &b: &i32,
+    //~^ ERROR patterns not allowed in naked function parameters
+    (None | Some(_)): Option<std::ptr::NonNull<u8>>,
+    //~^ ERROR patterns not allowed in naked function parameters
+    P { x, y }: P,
+    //~^ ERROR patterns not allowed in naked function parameters
+) {
+    asm!("", options(noreturn))
+}
+
+#[naked]
+pub unsafe extern "C" fn inc(a: u32) -> u32 {
+    //~^ WARN naked functions must contain a single asm block
+    //~| WARN this was previously accepted
+    a + 1
+    //~^ ERROR referencing function parameters is not allowed in naked functions
+}
+
+#[naked]
+pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
+    asm!("/* {0} */", in(reg) a, options(noreturn));
+    //~^ ERROR referencing function parameters is not allowed in naked functions
+    //~| WARN only `const` and `sym` operands are supported in naked functions
+    //~| WARN this was previously accepted
+}
+
+#[naked]
+pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
+    //~^ WARN naked functions must contain a single asm block
+    //~| WARN this was previously accepted
+    (|| a + 1)()
+}
+
+#[naked]
+pub unsafe extern "C" fn unsupported_operands() {
+    //~^ WARN naked functions must contain a single asm block
+    //~| WARN this was previously accepted
+    let mut a = 0usize;
+    let mut b = 0usize;
+    let mut c = 0usize;
+    let mut d = 0usize;
+    let mut e = 0usize;
+    const F: usize = 0usize;
+    static G: usize = 0usize;
+    asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
+         //~^ WARN asm in naked functions must use `noreturn` option
+         //~| WARN this was previously accepted
+         in(reg) a,
+         //~^ WARN only `const` and `sym` operands are supported in naked functions
+         //~| WARN this was previously accepted
+         inlateout(reg) b,
+         inout(reg) c,
+         lateout(reg) d,
+         out(reg) e,
+         const F,
+         sym G,
+    );
+}
+
+#[naked]
+pub extern "C" fn missing_assembly() {
+    //~^ WARN naked functions must contain a single asm block
+    //~| WARN this was previously accepted
+}
+
+#[naked]
+pub extern "C" fn too_many_asm_blocks() {
+    //~^ WARN naked functions must contain a single asm block
+    //~| WARN this was previously accepted
+    asm!("");
+    //~^ WARN asm in naked functions must use `noreturn` option
+    //~| WARN this was previously accepted
+    asm!("");
+    //~^ WARN asm in naked functions must use `noreturn` option
+    //~| WARN this was previously accepted
+    asm!("");
+    //~^ WARN asm in naked functions must use `noreturn` option
+    //~| WARN this was previously accepted
+    asm!("", options(noreturn));
+}
+
+pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
+    #[naked]
+    pub extern "C" fn inner(y: usize) -> usize {
+        //~^ WARN naked functions must contain a single asm block
+        //~| WARN this was previously accepted
+        *&y
+        //~^ ERROR referencing function parameters is not allowed in naked functions
+    }
+    inner
+}
+
+#[naked]
+unsafe extern "C" fn llvm() -> ! {
+    //~^ WARN naked functions must contain a single asm block
+    //~| WARN this was previously accepted
+    llvm_asm!("");
+    //~^ WARN LLVM-style inline assembly is unsupported in naked functions
+    //~| WARN this was previously accepted
+    core::hint::unreachable_unchecked();
+}
+
+#[naked]
+unsafe extern "C" fn invalid_options() {
+    asm!("", options(nomem, preserves_flags, noreturn));
+    //~^ WARN asm options unsupported in naked functions: `nomem`, `preserves_flags`
+    //~| WARN this was previously accepted
+}
+
+#[naked]
+unsafe extern "C" fn invalid_options_continued() {
+    asm!("", options(readonly, nostack), options(pure));
+    //~^ ERROR asm with `pure` option must have at least one output
+    //~| WARN asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
+    //~| WARN this was previously accepted
+    //~| WARN asm in naked functions must use `noreturn` option
+    //~| WARN this was previously accepted
+}
+
+#[naked]
+pub unsafe fn default_abi() {
+    //~^ WARN Rust ABI is unsupported in naked functions
+    //~| WARN this was previously accepted
+    asm!("", options(noreturn));
+}
+
+#[naked]
+pub unsafe extern "Rust" fn rust_abi() {
+    //~^ WARN Rust ABI is unsupported in naked functions
+    //~| WARN this was previously accepted
+    asm!("", options(noreturn));
+}
+
+#[naked]
+pub extern "C" fn valid_a<T>() -> T {
+    unsafe { asm!("", options(noreturn)); }
+}
+
+#[naked]
+pub extern "C" fn valid_b() {
+    unsafe { { {
+        asm!("", options(noreturn)); ; ; ;
+    } ; }  ; }
+}
+
+#[naked]
+pub unsafe extern "C" fn valid_c() {
+    asm!("", options(noreturn));
+}
+
+#[cfg(target_arch = "x86_64")]
+#[naked]
+pub unsafe extern "C" fn valid_att_syntax() {
+    asm!("", options(noreturn, att_syntax));
+}
diff --git a/src/test/ui/asm/naked-functions.stderr b/src/test/ui/asm/naked-functions.stderr
new file mode 100644 (file)
index 0000000..0762894
--- /dev/null
@@ -0,0 +1,300 @@
+error: asm with `pure` option must have at least one output
+  --> $DIR/naked-functions.rs:126:14
+   |
+LL |     asm!("", options(readonly, nostack), options(pure));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^
+
+error: patterns not allowed in naked function parameters
+  --> $DIR/naked-functions.rs:13:5
+   |
+LL |     mut a: u32,
+   |     ^^^^^
+
+error: patterns not allowed in naked function parameters
+  --> $DIR/naked-functions.rs:15:5
+   |
+LL |     &b: &i32,
+   |     ^^
+
+error: patterns not allowed in naked function parameters
+  --> $DIR/naked-functions.rs:17:6
+   |
+LL |     (None | Some(_)): Option<std::ptr::NonNull<u8>>,
+   |      ^^^^^^^^^^^^^^
+
+error: patterns not allowed in naked function parameters
+  --> $DIR/naked-functions.rs:19:5
+   |
+LL |     P { x, y }: P,
+   |     ^^^^^^^^^^
+
+error: referencing function parameters is not allowed in naked functions
+  --> $DIR/naked-functions.rs:29:5
+   |
+LL |     a + 1
+   |     ^
+   |
+   = help: follow the calling convention in asm block to use parameters
+
+warning: naked functions must contain a single asm block
+  --> $DIR/naked-functions.rs:26:1
+   |
+LL | / pub unsafe extern "C" fn inc(a: u32) -> u32 {
+LL | |
+LL | |
+LL | |     a + 1
+   | |     ----- non-asm is unsupported in naked functions
+LL | |
+LL | | }
+   | |_^
+   |
+   = note: `#[warn(unsupported_naked_functions)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+error: referencing function parameters is not allowed in naked functions
+  --> $DIR/naked-functions.rs:35:31
+   |
+LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
+   |                               ^
+   |
+   = help: follow the calling convention in asm block to use parameters
+
+warning: only `const` and `sym` operands are supported in naked functions
+  --> $DIR/naked-functions.rs:35:23
+   |
+LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
+   |                       ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: naked functions must contain a single asm block
+  --> $DIR/naked-functions.rs:42:1
+   |
+LL | / pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
+LL | |
+LL | |
+LL | |     (|| a + 1)()
+   | |     ------------ non-asm is unsupported in naked functions
+LL | | }
+   | |_^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: only `const` and `sym` operands are supported in naked functions
+  --> $DIR/naked-functions.rs:62:10
+   |
+LL |          in(reg) a,
+   |          ^^^^^^^^^
+...
+LL |          inlateout(reg) b,
+   |          ^^^^^^^^^^^^^^^^
+LL |          inout(reg) c,
+   |          ^^^^^^^^^^^^
+LL |          lateout(reg) d,
+   |          ^^^^^^^^^^^^^^
+LL |          out(reg) e,
+   |          ^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: asm in naked functions must use `noreturn` option
+  --> $DIR/naked-functions.rs:59:5
+   |
+LL | /     asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
+LL | |
+LL | |
+LL | |          in(reg) a,
+...  |
+LL | |          sym G,
+LL | |     );
+   | |______^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: naked functions must contain a single asm block
+  --> $DIR/naked-functions.rs:49:1
+   |
+LL | / pub unsafe extern "C" fn unsupported_operands() {
+LL | |
+LL | |
+LL | |     let mut a = 0usize;
+   | |     ------------------- non-asm is unsupported in naked functions
+LL | |     let mut b = 0usize;
+   | |     ------------------- non-asm is unsupported in naked functions
+LL | |     let mut c = 0usize;
+   | |     ------------------- non-asm is unsupported in naked functions
+LL | |     let mut d = 0usize;
+   | |     ------------------- non-asm is unsupported in naked functions
+LL | |     let mut e = 0usize;
+   | |     ------------------- non-asm is unsupported in naked functions
+...  |
+LL | |     );
+LL | | }
+   | |_^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: naked functions must contain a single asm block
+  --> $DIR/naked-functions.rs:75:1
+   |
+LL | / pub extern "C" fn missing_assembly() {
+LL | |
+LL | |
+LL | | }
+   | |_^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: asm in naked functions must use `noreturn` option
+  --> $DIR/naked-functions.rs:84:5
+   |
+LL |     asm!("");
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: asm in naked functions must use `noreturn` option
+  --> $DIR/naked-functions.rs:87:5
+   |
+LL |     asm!("");
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: asm in naked functions must use `noreturn` option
+  --> $DIR/naked-functions.rs:90:5
+   |
+LL |     asm!("");
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: naked functions must contain a single asm block
+  --> $DIR/naked-functions.rs:81:1
+   |
+LL | / pub extern "C" fn too_many_asm_blocks() {
+LL | |
+LL | |
+LL | |     asm!("");
+...  |
+LL | |     asm!("");
+   | |     --------- multiple asm blocks are unsupported in naked functions
+...  |
+LL | |     asm!("");
+   | |     --------- multiple asm blocks are unsupported in naked functions
+...  |
+LL | |     asm!("", options(noreturn));
+   | |     ---------------------------- multiple asm blocks are unsupported in naked functions
+LL | | }
+   | |_^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+error: referencing function parameters is not allowed in naked functions
+  --> $DIR/naked-functions.rs:101:11
+   |
+LL |         *&y
+   |           ^
+   |
+   = help: follow the calling convention in asm block to use parameters
+
+warning: naked functions must contain a single asm block
+  --> $DIR/naked-functions.rs:98:5
+   |
+LL | /     pub extern "C" fn inner(y: usize) -> usize {
+LL | |
+LL | |
+LL | |         *&y
+   | |         --- non-asm is unsupported in naked functions
+LL | |
+LL | |     }
+   | |_____^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: the LLVM-style inline assembly is unsupported in naked functions
+  --> $DIR/naked-functions.rs:111:5
+   |
+LL |     llvm_asm!("");
+   |     ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+   = help: use the new asm! syntax specified in RFC 2873
+   = note: this warning originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: naked functions must contain a single asm block
+  --> $DIR/naked-functions.rs:108:1
+   |
+LL | / unsafe extern "C" fn llvm() -> ! {
+LL | |
+LL | |
+LL | |     llvm_asm!("");
+...  |
+LL | |     core::hint::unreachable_unchecked();
+   | |     ------------------------------------ non-asm is unsupported in naked functions
+LL | | }
+   | |_^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: asm options unsupported in naked functions: `nomem`, `preserves_flags`
+  --> $DIR/naked-functions.rs:119:5
+   |
+LL |     asm!("", options(nomem, preserves_flags, noreturn));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
+  --> $DIR/naked-functions.rs:126:5
+   |
+LL |     asm!("", options(readonly, nostack), options(pure));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: asm in naked functions must use `noreturn` option
+  --> $DIR/naked-functions.rs:126:5
+   |
+LL |     asm!("", options(readonly, nostack), options(pure));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: Rust ABI is unsupported in naked functions
+  --> $DIR/naked-functions.rs:135:15
+   |
+LL | pub unsafe fn default_abi() {
+   |               ^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+warning: Rust ABI is unsupported in naked functions
+  --> $DIR/naked-functions.rs:142:29
+   |
+LL | pub unsafe extern "Rust" fn rust_abi() {
+   |                             ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #32408 <https://github.com/rust-lang/rust/issues/32408>
+
+error: aborting due to 8 previous errors; 19 warnings emitted
+
diff --git a/src/test/ui/asm/naked-params.rs b/src/test/ui/asm/naked-params.rs
deleted file mode 100644 (file)
index 46a4fc1..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-// Check that use of function parameters is validate in naked functions.
-//
-// ignore-wasm32 asm unsupported
-#![feature(asm)]
-#![feature(naked_functions)]
-#![feature(or_patterns)]
-#![crate_type = "lib"]
-
-#[repr(C)]
-pub struct P { x: u8, y: u16 }
-
-#[naked]
-pub unsafe extern "C" fn f(
-    mut a: u32,
-    //~^ ERROR patterns not allowed in naked function parameters
-    &b: &i32,
-    //~^ ERROR patterns not allowed in naked function parameters
-    (None | Some(_)): Option<std::ptr::NonNull<u8>>,
-    //~^ ERROR patterns not allowed in naked function parameters
-    P { x, y }: P,
-    //~^ ERROR patterns not allowed in naked function parameters
-) {
-    asm!("", options(noreturn))
-}
-
-#[naked]
-pub unsafe extern "C" fn inc(a: u32) -> u32 {
-    a + 1
-    //~^ ERROR use of parameters not allowed inside naked functions
-}
-
-#[naked]
-pub unsafe extern "C" fn inc_asm(a: u32) -> u32 {
-    asm!("/* {0} */", in(reg) a, options(noreturn));
-    //~^ ERROR use of parameters not allowed inside naked functions
-}
-
-#[naked]
-pub unsafe extern "C" fn sum(x: u32, y: u32) -> u32 {
-    // FIXME: Should be detected by asm-only check.
-    (|| { x + y})()
-}
-
-pub fn outer(x: u32) -> extern "C" fn(usize) -> usize {
-    #[naked]
-    pub extern "C" fn inner(y: usize) -> usize {
-        *&y
-        //~^ ERROR use of parameters not allowed inside naked functions
-    }
-    inner
-}
diff --git a/src/test/ui/asm/naked-params.stderr b/src/test/ui/asm/naked-params.stderr
deleted file mode 100644 (file)
index 1a99e51..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-error: patterns not allowed in naked function parameters
-  --> $DIR/naked-params.rs:14:5
-   |
-LL |     mut a: u32,
-   |     ^^^^^
-
-error: patterns not allowed in naked function parameters
-  --> $DIR/naked-params.rs:16:5
-   |
-LL |     &b: &i32,
-   |     ^^
-
-error: patterns not allowed in naked function parameters
-  --> $DIR/naked-params.rs:18:6
-   |
-LL |     (None | Some(_)): Option<std::ptr::NonNull<u8>>,
-   |      ^^^^^^^^^^^^^^
-
-error: patterns not allowed in naked function parameters
-  --> $DIR/naked-params.rs:20:5
-   |
-LL |     P { x, y }: P,
-   |     ^^^^^^^^^^
-
-error: use of parameters not allowed inside naked functions
-  --> $DIR/naked-params.rs:28:5
-   |
-LL |     a + 1
-   |     ^
-
-error: use of parameters not allowed inside naked functions
-  --> $DIR/naked-params.rs:34:31
-   |
-LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
-   |                               ^
-
-error: use of parameters not allowed inside naked functions
-  --> $DIR/naked-params.rs:47:11
-   |
-LL |         *&y
-   |           ^
-
-error: aborting due to 7 previous errors
-
diff --git a/src/test/ui/auxiliary/extern-prelude-vec.rs b/src/test/ui/auxiliary/extern-prelude-vec.rs
deleted file mode 100644 (file)
index a643c88..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-#![crate_name = "Vec"]
-
-pub fn new(arg1: f32, arg2: ()) {}
diff --git a/src/test/ui/auxiliary/extern-prelude.rs b/src/test/ui/auxiliary/extern-prelude.rs
deleted file mode 100644 (file)
index 2fdfd85..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-pub struct S;
-
-impl S {
-    pub fn external(&self) {}
-}
index fc70be404971e93af88389ce4dde577f1717f62b..dce2e27c71a139536a0b666c407f9aa9eb2244d7 100644 (file)
@@ -9,6 +9,8 @@ error[E0747]: type provided when a constant was expected
    |
 LL |     foo::<_, {[1]}>();
    |           ^
+   |
+   = help: const arguments cannot yet be inferred with `_`
 
 error[E0308]: mismatched types
   --> $DIR/issue-62878.rs:11:15
diff --git a/src/test/ui/const-generics/min_const_generics/inferred_const.rs b/src/test/ui/const-generics/min_const_generics/inferred_const.rs
new file mode 100644 (file)
index 0000000..dcd069c
--- /dev/null
@@ -0,0 +1,8 @@
+#![feature(min_const_generics)]
+fn foo<const N: usize, const K: usize>(data: [u32; N]) -> [u32; K] {
+    [0; K]
+}
+fn main() {
+    let a = foo::<_, 2>([0, 1, 2]);
+               //~^ ERROR type provided when a constant was expected
+}
diff --git a/src/test/ui/const-generics/min_const_generics/inferred_const.stderr b/src/test/ui/const-generics/min_const_generics/inferred_const.stderr
new file mode 100644 (file)
index 0000000..e17105b
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0747]: type provided when a constant was expected
+  --> $DIR/inferred_const.rs:6:19
+   |
+LL |     let a = foo::<_, 2>([0, 1, 2]);
+   |                   ^
+   |
+   = help: const arguments cannot yet be inferred with `_`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0747`.
diff --git a/src/test/ui/derives/issue-36617.rs b/src/test/ui/derives/issue-36617.rs
new file mode 100644 (file)
index 0000000..1102f3c
--- /dev/null
@@ -0,0 +1,4 @@
+#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
+                 //~| ERROR cannot determine resolution for the derive macro `Copy`
+
+fn main() {}
diff --git a/src/test/ui/derives/issue-36617.stderr b/src/test/ui/derives/issue-36617.stderr
new file mode 100644 (file)
index 0000000..dc6ef16
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0774]: `derive` may only be applied to structs, enums and unions
+  --> $DIR/issue-36617.rs:1:1
+   |
+LL | #![derive(Copy)]
+   | ^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Copy)]`
+
+error: cannot determine resolution for the derive macro `Copy`
+  --> $DIR/issue-36617.rs:1:11
+   |
+LL | #![derive(Copy)]
+   |           ^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0774`.
diff --git a/src/test/ui/double-import.rs b/src/test/ui/double-import.rs
deleted file mode 100644 (file)
index e732536..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-// This tests that conflicting imports shows both `use` lines
-// when reporting the error.
-
-mod sub1 {
-    pub fn foo() {} // implementation 1
-}
-
-mod sub2 {
-    pub fn foo() {} // implementation 2
-}
-
-use sub1::foo;
-use sub2::foo; //~ ERROR the name `foo` is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/double-import.stderr b/src/test/ui/double-import.stderr
deleted file mode 100644 (file)
index 7a4e8e5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0252]: the name `foo` is defined multiple times
-  --> $DIR/double-import.rs:13:5
-   |
-LL | use sub1::foo;
-   |     --------- previous import of the value `foo` here
-LL | use sub2::foo;
-   |     ^^^^^^^^^ `foo` reimported here
-   |
-   = note: `foo` must be defined only once in the value namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use sub2::foo as other_foo;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0252`.
index f73902c40066df552b4fee5f18b6ea57903b4231..f5035bb2c69858ad68b10d8fcdba33b9072ed6e1 100644 (file)
@@ -5,6 +5,14 @@
 
 fn main() {
     for (k, v) in vars_os() {
+        // On Windows, the environment variable NUMBER_OF_PROCESSORS has special meaning.
+        // Unfortunately, you can get different answers, depending on whether you are
+        // enumerating all environment variables or querying a specific variable.
+        // This was causing this test to fail on machines with more than 64 processors.
+        if cfg!(target_os = "windows") && k == "NUMBER_OF_PROCESSORS" {
+            continue;
+        }
+
         let v2 = var_os(&k);
         assert!(v2.as_ref().map(|s| &**s) == Some(&*v),
                 "bad vars->var transition: {:?} {:?} {:?}", k, v, v2);
index 3ca3a77c74fb735c1ac4a15834cf25e1d4b733eb..be47e93d19a9bb79b3fb3311141044c6cfc15ad7 100644 (file)
@@ -4,11 +4,7 @@ error[E0390]: only a single inherent implementation marked with `#[lang = "mut_p
 LL | impl *mut Foo {}
    | ^^^^^^^^^^^^^^^^
    |
-help: consider using a trait to implement these methods
-  --> $DIR/E0390.rs:5:1
-   |
-LL | impl *mut Foo {}
-   | ^^^^^^^^^^^^^^^^
+   = help: consider using a trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/export-glob-imports-target.rs b/src/test/ui/export-glob-imports-target.rs
deleted file mode 100644 (file)
index 4df807e..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// run-pass
-
-#![allow(non_upper_case_globals)]
-#![allow(dead_code)]
-// Test that a glob-export functions as an import
-// when referenced within its own local scope.
-
-// Modified to not use export since it's going away. --pcw
-
-// pretty-expanded FIXME #23616
-
-mod foo {
-    use foo::bar::*;
-    pub mod bar {
-        pub static a : isize = 10;
-    }
-    pub fn zum() {
-        let _b = a;
-    }
-}
-
-pub fn main() { }
diff --git a/src/test/ui/extern-prelude-fail.rs b/src/test/ui/extern-prelude-fail.rs
deleted file mode 100644 (file)
index 7d38702..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-// compile-flags:--extern extern_prelude
-// aux-build:extern-prelude.rs
-
-// Extern prelude names are not available by absolute paths
-
-fn main() {
-    use extern_prelude::S; //~ ERROR unresolved import `extern_prelude`
-    let s = ::extern_prelude::S; //~ ERROR failed to resolve
-}
diff --git a/src/test/ui/extern-prelude-fail.stderr b/src/test/ui/extern-prelude-fail.stderr
deleted file mode 100644 (file)
index a59f4c9..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0432]: unresolved import `extern_prelude`
-  --> $DIR/extern-prelude-fail.rs:7:9
-   |
-LL |     use extern_prelude::S;
-   |         ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`?
-
-error[E0433]: failed to resolve: maybe a missing crate `extern_prelude`?
-  --> $DIR/extern-prelude-fail.rs:8:15
-   |
-LL |     let s = ::extern_prelude::S;
-   |               ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`?
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0432, E0433.
-For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/extern-prelude.rs b/src/test/ui/extern-prelude.rs
deleted file mode 100644 (file)
index 50fed60..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// build-pass (FIXME(62277): could be check-pass?)
-// compile-flags:--extern extern_prelude --extern Vec
-// aux-build:extern-prelude.rs
-// aux-build:extern-prelude-vec.rs
-
-fn basic() {
-    // It works
-    let s = extern_prelude::S;
-    s.external();
-}
-
-fn shadow_mod() {
-    // Local module shadows `extern_prelude` from extern prelude
-    mod extern_prelude {
-        pub struct S;
-
-        impl S {
-            pub fn internal(&self) {}
-        }
-    }
-
-    let s = extern_prelude::S;
-    s.internal(); // OK
-}
-
-fn shadow_prelude() {
-    // Extern prelude shadows standard library prelude
-    let x = Vec::new(0f32, ()); // OK
-}
-
-fn main() {}
index 16a51a1e82fc664f1928fbbcece5d6d05acfdb11..06bddc422cf80847318e87d4cd761af49f890172 100644 (file)
@@ -1,11 +1,15 @@
+#![feature(asm)]
+
 #[naked]
 //~^ the `#[naked]` attribute is an experimental feature
-fn naked() {}
+extern "C" fn naked() {
+    asm!("", options(noreturn))
+}
 
 #[naked]
 //~^ the `#[naked]` attribute is an experimental feature
-fn naked_2() -> isize {
-    0
+extern "C" fn naked_2() -> isize {
+    asm!("", options(noreturn))
 }
 
 fn main() {}
index e24dde5429d51192071c9380c528f00e05176f5a..d95561d20133e8768f8f3c65b91c8cbd6733e410 100644 (file)
@@ -1,5 +1,5 @@
 error[E0658]: the `#[naked]` attribute is an experimental feature
-  --> $DIR/feature-gate-naked_functions.rs:1:1
+  --> $DIR/feature-gate-naked_functions.rs:3:1
    |
 LL | #[naked]
    | ^^^^^^^^
@@ -8,7 +8,7 @@ LL | #[naked]
    = help: add `#![feature(naked_functions)]` to the crate attributes to enable
 
 error[E0658]: the `#[naked]` attribute is an experimental feature
-  --> $DIR/feature-gate-naked_functions.rs:5:1
+  --> $DIR/feature-gate-naked_functions.rs:9:1
    |
 LL | #[naked]
    | ^^^^^^^^
index dad8c2a2909da85a0bb7cf9d3db7155c043fb3d0..94dda17aad710f9d9792c8c707ff449a0a8d8743 100644 (file)
@@ -7,7 +7,7 @@ trait X {
 
 const _: () = {
   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
-      //~^ ERROR: expected one of `>`, const, lifetime, or type, found `:`
+      //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `:`
       //~| ERROR: expected parameter name, found `>`
       //~| ERROR: expected one of `!`, `)`, `+`, `,`, or `::`, found `>`
       //~| ERROR: constant provided when a type was expected
@@ -15,7 +15,7 @@ fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
 
 const _: () = {
   fn f1<'a>(arg : Box<dyn X< = 32 >>) {}
-      //~^ ERROR: expected one of `>`, const, lifetime, or type, found `=`
+      //~^ ERROR: expected one of `>`, a const expression, lifetime, or type, found `=`
 };
 
 fn main() {}
index 583697f0b67d2df01a62d1a4b4115a76e071686d..8a5e2c29c3665e8e92f693f6eb4d1df9c5f3c143 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, lifetime, or type, found `:`
+error: expected one of `>`, a const expression, lifetime, or type, found `:`
   --> $DIR/trait-path-missing-gen_arg.rs:9:30
    |
 LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
-   |                              ^ expected one of `>`, const, lifetime, or type
+   |                              ^ expected one of `>`, a const expression, lifetime, or type
    |
 help: expressions must be enclosed in braces to be used as const generic arguments
    |
@@ -24,11 +24,11 @@ LL |   fn f1<'a>(arg : Box<dyn X< : 32 >>) {}
    |                                    expected one of `!`, `)`, `+`, `,`, or `::`
    |                                    help: missing `,`
 
-error: expected one of `>`, const, lifetime, or type, found `=`
+error: expected one of `>`, a const expression, lifetime, or type, found `=`
   --> $DIR/trait-path-missing-gen_arg.rs:17:30
    |
 LL |   fn f1<'a>(arg : Box<dyn X< = 32 >>) {}
-   |                              ^ expected one of `>`, const, lifetime, or type
+   |                              ^ expected one of `>`, a const expression, lifetime, or type
 
 warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/trait-path-missing-gen_arg.rs:1:12
diff --git a/src/test/ui/glob-resolve1.rs b/src/test/ui/glob-resolve1.rs
deleted file mode 100644 (file)
index 32660fd..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-// Make sure that globs only bring in public things.
-
-use bar::*;
-
-mod bar {
-    use self::fpriv as import;
-    fn fpriv() {}
-    extern {
-        fn epriv();
-    }
-    enum A { A1 }
-    pub enum B { B1 }
-
-    struct C;
-
-    type D = isize;
-}
-
-fn foo<T>() {}
-
-fn main() {
-    fpriv(); //~ ERROR cannot find function `fpriv` in this scope
-    epriv(); //~ ERROR cannot find function `epriv` in this scope
-    B; //~ ERROR expected value, found enum `B`
-    C; //~ ERROR cannot find value `C` in this scope
-    import(); //~ ERROR: cannot find function `import` in this scope
-
-    foo::<A>(); //~ ERROR: cannot find type `A` in this scope
-    foo::<C>(); //~ ERROR: cannot find type `C` in this scope
-    foo::<D>(); //~ ERROR: cannot find type `D` in this scope
-}
-
-mod other {
-    pub fn import() {}
-}
diff --git a/src/test/ui/glob-resolve1.stderr b/src/test/ui/glob-resolve1.stderr
deleted file mode 100644 (file)
index cd128c1..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-error[E0425]: cannot find function `fpriv` in this scope
-  --> $DIR/glob-resolve1.rs:22:5
-   |
-LL |     fpriv();
-   |     ^^^^^ not found in this scope
-   |
-help: consider importing this function
-   |
-LL | use bar::fpriv;
-   |
-
-error[E0425]: cannot find function `epriv` in this scope
-  --> $DIR/glob-resolve1.rs:23:5
-   |
-LL |     epriv();
-   |     ^^^^^ not found in this scope
-   |
-help: consider importing this function
-   |
-LL | use bar::epriv;
-   |
-
-error[E0423]: expected value, found enum `B`
-  --> $DIR/glob-resolve1.rs:24:5
-   |
-LL |     B;
-   |     ^
-   |
-note: the enum is defined here
-  --> $DIR/glob-resolve1.rs:12:5
-   |
-LL |     pub enum B { B1 }
-   |     ^^^^^^^^^^^^^^^^^
-help: you might have meant to use the following enum variant
-   |
-LL |     B::B1;
-   |     ^^^^^
-
-error[E0425]: cannot find value `C` in this scope
-  --> $DIR/glob-resolve1.rs:25:5
-   |
-LL |     C;
-   |     ^ not found in this scope
-   |
-help: consider importing this unit struct
-   |
-LL | use bar::C;
-   |
-
-error[E0425]: cannot find function `import` in this scope
-  --> $DIR/glob-resolve1.rs:26:5
-   |
-LL |     import();
-   |     ^^^^^^ not found in this scope
-   |
-help: consider importing this function
-   |
-LL | use other::import;
-   |
-
-error[E0412]: cannot find type `A` in this scope
-  --> $DIR/glob-resolve1.rs:28:11
-   |
-LL |     pub enum B { B1 }
-   |     ---------- similarly named enum `B` defined here
-...
-LL |     foo::<A>();
-   |           ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     foo::<B>();
-   |           ^
-help: consider importing this enum
-   |
-LL | use bar::A;
-   |
-
-error[E0412]: cannot find type `C` in this scope
-  --> $DIR/glob-resolve1.rs:29:11
-   |
-LL |     pub enum B { B1 }
-   |     ---------- similarly named enum `B` defined here
-...
-LL |     foo::<C>();
-   |           ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     foo::<B>();
-   |           ^
-help: consider importing this struct
-   |
-LL | use bar::C;
-   |
-
-error[E0412]: cannot find type `D` in this scope
-  --> $DIR/glob-resolve1.rs:30:11
-   |
-LL |     pub enum B { B1 }
-   |     ---------- similarly named enum `B` defined here
-...
-LL |     foo::<D>();
-   |           ^
-   |
-help: an enum with a similar name exists
-   |
-LL |     foo::<B>();
-   |           ^
-help: consider importing this type alias
-   |
-LL | use bar::D;
-   |
-
-error: aborting due to 8 previous errors
-
-Some errors have detailed explanations: E0412, E0423, E0425.
-For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/hidden-rt-injection.rs b/src/test/ui/hidden-rt-injection.rs
deleted file mode 100644 (file)
index 3ca04f9..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// This is testing that users can't access the runtime crate.
-
-mod m {
-    // The rt has been called both 'native' and 'rt'
-    use native; //~ ERROR unresolved import
-}
-
-fn main() { }
diff --git a/src/test/ui/hidden-rt-injection.stderr b/src/test/ui/hidden-rt-injection.stderr
deleted file mode 100644 (file)
index 3e288b7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `native`
-  --> $DIR/hidden-rt-injection.rs:5:9
-   |
-LL |     use native;
-   |         ^^^^^^ no `native` in the root
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/hidden-rt-injection2.rs b/src/test/ui/hidden-rt-injection2.rs
deleted file mode 100644 (file)
index 2af113c..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// This is testing that users can't access the runtime crate.
-
-mod m {
-    // The rt has been called both 'native' and 'rt'
-    use rt; //~ ERROR unresolved import
-}
-
-fn main() { }
diff --git a/src/test/ui/hidden-rt-injection2.stderr b/src/test/ui/hidden-rt-injection2.stderr
deleted file mode 100644 (file)
index 73f89b5..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `rt`
-  --> $DIR/hidden-rt-injection2.rs:5:9
-   |
-LL |     use rt;
-   |         ^^ no `rt` in the root
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/import.rs b/src/test/ui/import.rs
deleted file mode 100644 (file)
index 3170dd2..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-use zed::bar;
-use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432]
-              //~| no `baz` in `zed`
-              //~| HELP a similar name exists in the module
-              //~| SUGGESTION bar
-
-
-mod zed {
-    pub fn bar() { println!("bar"); }
-    use foo; //~ ERROR unresolved import `foo` [E0432]
-             //~^ no `foo` in the root
-}
-
-fn main() {
-    zed::foo(); //~ ERROR `foo` is private
-    bar();
-}
diff --git a/src/test/ui/import.stderr b/src/test/ui/import.stderr
deleted file mode 100644 (file)
index 797712e..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-error[E0432]: unresolved import `zed::baz`
-  --> $DIR/import.rs:2:5
-   |
-LL | use zed::baz;
-   |     ^^^^^---
-   |     |    |
-   |     |    help: a similar name exists in the module: `bar`
-   |     no `baz` in `zed`
-
-error[E0432]: unresolved import `foo`
-  --> $DIR/import.rs:10:9
-   |
-LL |     use foo;
-   |         ^^^ no `foo` in the root
-
-error[E0603]: unresolved item import `foo` is private
-  --> $DIR/import.rs:15:10
-   |
-LL |     zed::foo();
-   |          ^^^ private unresolved item import
-   |
-note: the unresolved item import `foo` is defined here
-  --> $DIR/import.rs:10:9
-   |
-LL |     use foo;
-   |         ^^^
-
-error: aborting due to 3 previous errors
-
-Some errors have detailed explanations: E0432, E0603.
-For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/import2.rs b/src/test/ui/import2.rs
deleted file mode 100644 (file)
index 036d6bc..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-use baz::zed::bar; //~ ERROR unresolved import `baz::zed` [E0432]
-                   //~^ could not find `zed` in `baz`
-
-mod baz {}
-mod zed {
-    pub fn bar() { println!("bar3"); }
-}
-fn main() {
-    bar();
-}
diff --git a/src/test/ui/import2.stderr b/src/test/ui/import2.stderr
deleted file mode 100644 (file)
index da88897..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `baz::zed`
-  --> $DIR/import2.rs:1:10
-   |
-LL | use baz::zed::bar;
-   |          ^^^ could not find `zed` in `baz`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/import3.rs b/src/test/ui/import3.rs
deleted file mode 100644 (file)
index 2c6ac9a..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-// error-pattern: unresolved
-use main::bar;
-
-fn main() { println!("foo"); }
diff --git a/src/test/ui/import3.stderr b/src/test/ui/import3.stderr
deleted file mode 100644 (file)
index 7bb413b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `main`
-  --> $DIR/import3.rs:2:5
-   |
-LL | use main::bar;
-   |     ^^^^ maybe a missing crate `main`?
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/import4.rs b/src/test/ui/import4.rs
deleted file mode 100644 (file)
index ba3b7fb..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// error-pattern: import
-
-
-mod a { pub use b::foo; }
-mod b { pub use a::foo; }
-
-fn main() { println!("loop"); }
diff --git a/src/test/ui/import4.stderr b/src/test/ui/import4.stderr
deleted file mode 100644 (file)
index e0b478f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `a::foo`
-  --> $DIR/import4.rs:5:17
-   |
-LL | mod b { pub use a::foo; }
-   |                 ^^^^^^ no `foo` in `a`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/auxiliary/issue-36881-aux.rs b/src/test/ui/imports/auxiliary/issue-36881-aux.rs
new file mode 100644 (file)
index 0000000..e373b64
--- /dev/null
@@ -0,0 +1 @@
+pub trait Foo {}
diff --git a/src/test/ui/imports/auxiliary/issue-52891.rs b/src/test/ui/imports/auxiliary/issue-52891.rs
new file mode 100644 (file)
index 0000000..0759811
--- /dev/null
@@ -0,0 +1,33 @@
+pub mod a {
+    pub mod inner {
+    }
+}
+
+pub mod b {
+    pub mod inner {
+    }
+}
+
+pub mod c {}
+
+pub mod d {}
+
+pub mod e {}
+
+pub mod f {}
+
+pub mod g {}
+
+pub mod h {}
+
+pub mod i {}
+
+pub mod j {}
+
+pub mod k {}
+
+pub mod l {}
+
+pub mod m {}
+
+pub mod n {}
diff --git a/src/test/ui/imports/auxiliary/issue-59764.rs b/src/test/ui/imports/auxiliary/issue-59764.rs
new file mode 100644 (file)
index 0000000..a92eed9
--- /dev/null
@@ -0,0 +1,18 @@
+pub mod foo {
+    #[macro_export]
+    macro_rules! makro {
+        ($foo:ident) => {
+            fn $foo() { }
+        }
+    }
+
+    pub fn baz() {}
+
+    pub fn foobar() {}
+
+    pub mod barbaz {
+        pub fn barfoo() {}
+    }
+}
+
+pub fn foobaz() {}
diff --git a/src/test/ui/imports/double-import.rs b/src/test/ui/imports/double-import.rs
new file mode 100644 (file)
index 0000000..e732536
--- /dev/null
@@ -0,0 +1,15 @@
+// This tests that conflicting imports shows both `use` lines
+// when reporting the error.
+
+mod sub1 {
+    pub fn foo() {} // implementation 1
+}
+
+mod sub2 {
+    pub fn foo() {} // implementation 2
+}
+
+use sub1::foo;
+use sub2::foo; //~ ERROR the name `foo` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/double-import.stderr b/src/test/ui/imports/double-import.stderr
new file mode 100644 (file)
index 0000000..7a4e8e5
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0252]: the name `foo` is defined multiple times
+  --> $DIR/double-import.rs:13:5
+   |
+LL | use sub1::foo;
+   |     --------- previous import of the value `foo` here
+LL | use sub2::foo;
+   |     ^^^^^^^^^ `foo` reimported here
+   |
+   = note: `foo` must be defined only once in the value namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use sub2::foo as other_foo;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/export-glob-imports-target.rs b/src/test/ui/imports/export-glob-imports-target.rs
new file mode 100644 (file)
index 0000000..4df807e
--- /dev/null
@@ -0,0 +1,22 @@
+// run-pass
+
+#![allow(non_upper_case_globals)]
+#![allow(dead_code)]
+// Test that a glob-export functions as an import
+// when referenced within its own local scope.
+
+// Modified to not use export since it's going away. --pcw
+
+// pretty-expanded FIXME #23616
+
+mod foo {
+    use foo::bar::*;
+    pub mod bar {
+        pub static a : isize = 10;
+    }
+    pub fn zum() {
+        let _b = a;
+    }
+}
+
+pub fn main() { }
diff --git a/src/test/ui/imports/glob-resolve1.rs b/src/test/ui/imports/glob-resolve1.rs
new file mode 100644 (file)
index 0000000..32660fd
--- /dev/null
@@ -0,0 +1,35 @@
+// Make sure that globs only bring in public things.
+
+use bar::*;
+
+mod bar {
+    use self::fpriv as import;
+    fn fpriv() {}
+    extern {
+        fn epriv();
+    }
+    enum A { A1 }
+    pub enum B { B1 }
+
+    struct C;
+
+    type D = isize;
+}
+
+fn foo<T>() {}
+
+fn main() {
+    fpriv(); //~ ERROR cannot find function `fpriv` in this scope
+    epriv(); //~ ERROR cannot find function `epriv` in this scope
+    B; //~ ERROR expected value, found enum `B`
+    C; //~ ERROR cannot find value `C` in this scope
+    import(); //~ ERROR: cannot find function `import` in this scope
+
+    foo::<A>(); //~ ERROR: cannot find type `A` in this scope
+    foo::<C>(); //~ ERROR: cannot find type `C` in this scope
+    foo::<D>(); //~ ERROR: cannot find type `D` in this scope
+}
+
+mod other {
+    pub fn import() {}
+}
diff --git a/src/test/ui/imports/glob-resolve1.stderr b/src/test/ui/imports/glob-resolve1.stderr
new file mode 100644 (file)
index 0000000..cd128c1
--- /dev/null
@@ -0,0 +1,118 @@
+error[E0425]: cannot find function `fpriv` in this scope
+  --> $DIR/glob-resolve1.rs:22:5
+   |
+LL |     fpriv();
+   |     ^^^^^ not found in this scope
+   |
+help: consider importing this function
+   |
+LL | use bar::fpriv;
+   |
+
+error[E0425]: cannot find function `epriv` in this scope
+  --> $DIR/glob-resolve1.rs:23:5
+   |
+LL |     epriv();
+   |     ^^^^^ not found in this scope
+   |
+help: consider importing this function
+   |
+LL | use bar::epriv;
+   |
+
+error[E0423]: expected value, found enum `B`
+  --> $DIR/glob-resolve1.rs:24:5
+   |
+LL |     B;
+   |     ^
+   |
+note: the enum is defined here
+  --> $DIR/glob-resolve1.rs:12:5
+   |
+LL |     pub enum B { B1 }
+   |     ^^^^^^^^^^^^^^^^^
+help: you might have meant to use the following enum variant
+   |
+LL |     B::B1;
+   |     ^^^^^
+
+error[E0425]: cannot find value `C` in this scope
+  --> $DIR/glob-resolve1.rs:25:5
+   |
+LL |     C;
+   |     ^ not found in this scope
+   |
+help: consider importing this unit struct
+   |
+LL | use bar::C;
+   |
+
+error[E0425]: cannot find function `import` in this scope
+  --> $DIR/glob-resolve1.rs:26:5
+   |
+LL |     import();
+   |     ^^^^^^ not found in this scope
+   |
+help: consider importing this function
+   |
+LL | use other::import;
+   |
+
+error[E0412]: cannot find type `A` in this scope
+  --> $DIR/glob-resolve1.rs:28:11
+   |
+LL |     pub enum B { B1 }
+   |     ---------- similarly named enum `B` defined here
+...
+LL |     foo::<A>();
+   |           ^
+   |
+help: an enum with a similar name exists
+   |
+LL |     foo::<B>();
+   |           ^
+help: consider importing this enum
+   |
+LL | use bar::A;
+   |
+
+error[E0412]: cannot find type `C` in this scope
+  --> $DIR/glob-resolve1.rs:29:11
+   |
+LL |     pub enum B { B1 }
+   |     ---------- similarly named enum `B` defined here
+...
+LL |     foo::<C>();
+   |           ^
+   |
+help: an enum with a similar name exists
+   |
+LL |     foo::<B>();
+   |           ^
+help: consider importing this struct
+   |
+LL | use bar::C;
+   |
+
+error[E0412]: cannot find type `D` in this scope
+  --> $DIR/glob-resolve1.rs:30:11
+   |
+LL |     pub enum B { B1 }
+   |     ---------- similarly named enum `B` defined here
+...
+LL |     foo::<D>();
+   |           ^
+   |
+help: an enum with a similar name exists
+   |
+LL |     foo::<B>();
+   |           ^
+help: consider importing this type alias
+   |
+LL | use bar::D;
+   |
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0412, E0423, E0425.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/imports/import-rpass.rs b/src/test/ui/imports/import-rpass.rs
new file mode 100644 (file)
index 0000000..de8bf62
--- /dev/null
@@ -0,0 +1,12 @@
+// run-pass
+mod foo {
+    pub fn x(y: isize) { println!("{}", y); }
+}
+
+mod bar {
+    use foo::x;
+    use foo::x as z;
+    pub fn thing() { x(10); z(10); }
+}
+
+pub fn main() { bar::thing(); }
index de8bf62611416e101c15b69809add9e8702f4da4..3170dd2fae10824b9e338fc985ca203cd093909f 100644 (file)
@@ -1,12 +1,17 @@
-// run-pass
-mod foo {
-    pub fn x(y: isize) { println!("{}", y); }
-}
+use zed::bar;
+use zed::baz; //~ ERROR unresolved import `zed::baz` [E0432]
+              //~| no `baz` in `zed`
+              //~| HELP a similar name exists in the module
+              //~| SUGGESTION bar
+
 
-mod bar {
-    use foo::x;
-    use foo::x as z;
-    pub fn thing() { x(10); z(10); }
+mod zed {
+    pub fn bar() { println!("bar"); }
+    use foo; //~ ERROR unresolved import `foo` [E0432]
+             //~^ no `foo` in the root
 }
 
-pub fn main() { bar::thing(); }
+fn main() {
+    zed::foo(); //~ ERROR `foo` is private
+    bar();
+}
diff --git a/src/test/ui/imports/import.stderr b/src/test/ui/imports/import.stderr
new file mode 100644 (file)
index 0000000..797712e
--- /dev/null
@@ -0,0 +1,31 @@
+error[E0432]: unresolved import `zed::baz`
+  --> $DIR/import.rs:2:5
+   |
+LL | use zed::baz;
+   |     ^^^^^---
+   |     |    |
+   |     |    help: a similar name exists in the module: `bar`
+   |     no `baz` in `zed`
+
+error[E0432]: unresolved import `foo`
+  --> $DIR/import.rs:10:9
+   |
+LL |     use foo;
+   |         ^^^ no `foo` in the root
+
+error[E0603]: unresolved item import `foo` is private
+  --> $DIR/import.rs:15:10
+   |
+LL |     zed::foo();
+   |          ^^^ private unresolved item import
+   |
+note: the unresolved item import `foo` is defined here
+  --> $DIR/import.rs:10:9
+   |
+LL |     use foo;
+   |         ^^^
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0432, E0603.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/import2-rpass.rs b/src/test/ui/imports/import2-rpass.rs
new file mode 100644 (file)
index 0000000..7b70f79
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+
+use zed::bar;
+
+mod zed {
+    pub fn bar() { println!("bar"); }
+}
+
+pub fn main() { bar(); }
index 7b70f799ebf936fb1214c4aff442f3f76809b5ac..036d6bc07e281f2f258f36d6611d48be7c31c727 100644 (file)
@@ -1,9 +1,10 @@
-// run-pass
-
-use zed::bar;
+use baz::zed::bar; //~ ERROR unresolved import `baz::zed` [E0432]
+                   //~^ could not find `zed` in `baz`
 
+mod baz {}
 mod zed {
-    pub fn bar() { println!("bar"); }
+    pub fn bar() { println!("bar3"); }
+}
+fn main() {
+    bar();
 }
-
-pub fn main() { bar(); }
diff --git a/src/test/ui/imports/import2.stderr b/src/test/ui/imports/import2.stderr
new file mode 100644 (file)
index 0000000..da88897
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `baz::zed`
+  --> $DIR/import2.rs:1:10
+   |
+LL | use baz::zed::bar;
+   |          ^^^ could not find `zed` in `baz`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/import3-rpass.rs b/src/test/ui/imports/import3-rpass.rs
new file mode 100644 (file)
index 0000000..17797ae
--- /dev/null
@@ -0,0 +1,13 @@
+// run-pass
+#![allow(unused_imports)]
+
+use baz::zed;
+use baz::zed::bar;
+
+mod baz {
+    pub mod zed {
+        pub fn bar() { println!("bar2"); }
+    }
+}
+
+pub fn main() { bar(); }
index 17797aed3591dc0ef339f8091ae49c29cc0ac0ad..2c6ac9a00e10924d9acc7a206508f7d69b884365 100644 (file)
@@ -1,13 +1,4 @@
-// run-pass
-#![allow(unused_imports)]
+// error-pattern: unresolved
+use main::bar;
 
-use baz::zed;
-use baz::zed::bar;
-
-mod baz {
-    pub mod zed {
-        pub fn bar() { println!("bar2"); }
-    }
-}
-
-pub fn main() { bar(); }
+fn main() { println!("foo"); }
diff --git a/src/test/ui/imports/import3.stderr b/src/test/ui/imports/import3.stderr
new file mode 100644 (file)
index 0000000..7bb413b
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `main`
+  --> $DIR/import3.rs:2:5
+   |
+LL | use main::bar;
+   |     ^^^^ maybe a missing crate `main`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/import4-rpass.rs b/src/test/ui/imports/import4-rpass.rs
new file mode 100644 (file)
index 0000000..4fda538
--- /dev/null
@@ -0,0 +1,9 @@
+// run-pass
+
+use zed::bar;
+
+mod zed {
+    pub fn bar() { println!("bar"); }
+}
+
+pub fn main() { let _zed = 42; bar(); }
index 4fda5386112c0ad39fc4c85e00c8fd8e9e2cdc07..ba3b7fbf535596782c7c228ea51e84c6690c35d3 100644 (file)
@@ -1,9 +1,7 @@
-// run-pass
+// error-pattern: import
 
-use zed::bar;
 
-mod zed {
-    pub fn bar() { println!("bar"); }
-}
+mod a { pub use b::foo; }
+mod b { pub use a::foo; }
 
-pub fn main() { let _zed = 42; bar(); }
+fn main() { println!("loop"); }
diff --git a/src/test/ui/imports/import4.stderr b/src/test/ui/imports/import4.stderr
new file mode 100644 (file)
index 0000000..e0b478f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `a::foo`
+  --> $DIR/import4.rs:5:17
+   |
+LL | mod b { pub use a::foo; }
+   |                 ^^^^^^ no `foo` in `a`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-13404.rs b/src/test/ui/imports/issue-13404.rs
new file mode 100644 (file)
index 0000000..c5af827
--- /dev/null
@@ -0,0 +1,10 @@
+use a::f;
+use b::f; //~ ERROR: unresolved import `b::f` [E0432]
+          //~^ no `f` in `b`
+
+mod a { pub fn f() {} }
+mod b { }
+
+fn main() {
+    f();
+}
diff --git a/src/test/ui/imports/issue-13404.stderr b/src/test/ui/imports/issue-13404.stderr
new file mode 100644 (file)
index 0000000..1f50deb
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `b::f`
+  --> $DIR/issue-13404.rs:2:5
+   |
+LL | use b::f;
+   |     ^^^^ no `f` in `b`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-1697.rs b/src/test/ui/imports/issue-1697.rs
new file mode 100644 (file)
index 0000000..5cd76d2
--- /dev/null
@@ -0,0 +1,6 @@
+// Testing that we don't fail abnormally after hitting the errors
+
+use unresolved::*; //~ ERROR unresolved import `unresolved` [E0432]
+                   //~^ maybe a missing crate `unresolved`?
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-1697.stderr b/src/test/ui/imports/issue-1697.stderr
new file mode 100644 (file)
index 0000000..a76fd30
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `unresolved`
+  --> $DIR/issue-1697.rs:3:5
+   |
+LL | use unresolved::*;
+   |     ^^^^^^^^^^ maybe a missing crate `unresolved`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-18083.rs b/src/test/ui/imports/issue-18083.rs
new file mode 100644 (file)
index 0000000..36420ec
--- /dev/null
@@ -0,0 +1,25 @@
+// check-pass
+#![allow(dead_code)]
+#![allow(unused_imports)]
+// These crossed imports should resolve fine, and not block on
+// each other and be reported as unresolved.
+
+mod a {
+    use b::{B};
+    pub use self::inner::A;
+
+    mod inner {
+        pub struct A;
+    }
+}
+
+mod b {
+    use a::{A};
+    pub use self::inner::B;
+
+    mod inner {
+        pub struct B;
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-19498.rs b/src/test/ui/imports/issue-19498.rs
new file mode 100644 (file)
index 0000000..5fe6742
--- /dev/null
@@ -0,0 +1,13 @@
+use self::A;
+use self::B;
+mod A {} //~ ERROR the name `A` is defined multiple times
+//~| `A` redefined here
+pub mod B {} //~ ERROR the name `B` is defined multiple times
+//~| `B` redefined here
+mod C {
+    use C::D;
+    mod D {} //~ ERROR the name `D` is defined multiple times
+    //~| `D` redefined here
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-19498.stderr b/src/test/ui/imports/issue-19498.stderr
new file mode 100644 (file)
index 0000000..cc1d649
--- /dev/null
@@ -0,0 +1,47 @@
+error[E0255]: the name `A` is defined multiple times
+  --> $DIR/issue-19498.rs:3:1
+   |
+LL | use self::A;
+   |     ------- previous import of the module `A` here
+LL | use self::B;
+LL | mod A {}
+   | ^^^^^ `A` redefined here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use self::A as OtherA;
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `B` is defined multiple times
+  --> $DIR/issue-19498.rs:5:1
+   |
+LL | use self::B;
+   |     ------- previous import of the module `B` here
+...
+LL | pub mod B {}
+   | ^^^^^^^^^ `B` redefined here
+   |
+   = note: `B` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use self::B as OtherB;
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `D` is defined multiple times
+  --> $DIR/issue-19498.rs:9:5
+   |
+LL |     use C::D;
+   |         ---- previous import of the module `D` here
+LL |     mod D {}
+   |     ^^^^^ `D` redefined here
+   |
+   = note: `D` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL |     use C::D as OtherD;
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/imports/issue-24081.rs b/src/test/ui/imports/issue-24081.rs
new file mode 100644 (file)
index 0000000..10983ce
--- /dev/null
@@ -0,0 +1,18 @@
+use std::ops::Add;
+use std::ops::Sub;
+use std::ops::Mul;
+use std::ops::Div;
+use std::ops::Rem;
+
+type Add = bool; //~ ERROR the name `Add` is defined multiple times
+//~| `Add` redefined here
+struct Sub { x: f32 } //~ ERROR the name `Sub` is defined multiple times
+//~| `Sub` redefined here
+enum Mul { A, B } //~ ERROR the name `Mul` is defined multiple times
+//~| `Mul` redefined here
+mod Div { } //~ ERROR the name `Div` is defined multiple times
+//~| `Div` redefined here
+trait Rem {  } //~ ERROR the name `Rem` is defined multiple times
+//~| `Rem` redefined here
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-24081.stderr b/src/test/ui/imports/issue-24081.stderr
new file mode 100644 (file)
index 0000000..647048c
--- /dev/null
@@ -0,0 +1,78 @@
+error[E0255]: the name `Add` is defined multiple times
+  --> $DIR/issue-24081.rs:7:1
+   |
+LL | use std::ops::Add;
+   |     ------------- previous import of the trait `Add` here
+...
+LL | type Add = bool;
+   | ^^^^^^^^^^^^^^^^ `Add` redefined here
+   |
+   = note: `Add` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Add as OtherAdd;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Sub` is defined multiple times
+  --> $DIR/issue-24081.rs:9:1
+   |
+LL | use std::ops::Sub;
+   |     ------------- previous import of the trait `Sub` here
+...
+LL | struct Sub { x: f32 }
+   | ^^^^^^^^^^ `Sub` redefined here
+   |
+   = note: `Sub` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Sub as OtherSub;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Mul` is defined multiple times
+  --> $DIR/issue-24081.rs:11:1
+   |
+LL | use std::ops::Mul;
+   |     ------------- previous import of the trait `Mul` here
+...
+LL | enum Mul { A, B }
+   | ^^^^^^^^ `Mul` redefined here
+   |
+   = note: `Mul` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Mul as OtherMul;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Div` is defined multiple times
+  --> $DIR/issue-24081.rs:13:1
+   |
+LL | use std::ops::Div;
+   |     ------------- previous import of the trait `Div` here
+...
+LL | mod Div { }
+   | ^^^^^^^ `Div` redefined here
+   |
+   = note: `Div` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Div as OtherDiv;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `Rem` is defined multiple times
+  --> $DIR/issue-24081.rs:15:1
+   |
+LL | use std::ops::Rem;
+   |     ------------- previous import of the trait `Rem` here
+...
+LL | trait Rem {  }
+   | ^^^^^^^^^ `Rem` redefined here
+   |
+   = note: `Rem` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::ops::Rem as OtherRem;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/imports/issue-25396.rs b/src/test/ui/imports/issue-25396.rs
new file mode 100644 (file)
index 0000000..301658d
--- /dev/null
@@ -0,0 +1,29 @@
+#![allow(non_camel_case_types)]
+
+use foo::baz;
+use bar::baz; //~ ERROR the name `baz` is defined multiple times
+
+use foo::Quux;
+use bar::Quux; //~ ERROR the name `Quux` is defined multiple times
+
+use foo::blah;
+use bar::blah; //~ ERROR the name `blah` is defined multiple times
+
+use foo::WOMP;
+use bar::WOMP; //~ ERROR the name `WOMP` is defined multiple times
+
+fn main() {}
+
+mod foo {
+    pub mod baz {}
+    pub trait Quux { }
+    pub type blah = (f64, u32);
+    pub const WOMP: u8 = 5;
+}
+
+mod bar {
+    pub mod baz {}
+    pub type Quux = i32;
+    pub struct blah { x: i8 }
+    pub const WOMP: i8 = -5;
+}
diff --git a/src/test/ui/imports/issue-25396.stderr b/src/test/ui/imports/issue-25396.stderr
new file mode 100644 (file)
index 0000000..38dc9ef
--- /dev/null
@@ -0,0 +1,59 @@
+error[E0252]: the name `baz` is defined multiple times
+  --> $DIR/issue-25396.rs:4:5
+   |
+LL | use foo::baz;
+   |     -------- previous import of the module `baz` here
+LL | use bar::baz;
+   |     ^^^^^^^^ `baz` reimported here
+   |
+   = note: `baz` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::baz as other_baz;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error[E0252]: the name `Quux` is defined multiple times
+  --> $DIR/issue-25396.rs:7:5
+   |
+LL | use foo::Quux;
+   |     --------- previous import of the trait `Quux` here
+LL | use bar::Quux;
+   |     ^^^^^^^^^ `Quux` reimported here
+   |
+   = note: `Quux` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::Quux as OtherQuux;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0252]: the name `blah` is defined multiple times
+  --> $DIR/issue-25396.rs:10:5
+   |
+LL | use foo::blah;
+   |     --------- previous import of the type `blah` here
+LL | use bar::blah;
+   |     ^^^^^^^^^ `blah` reimported here
+   |
+   = note: `blah` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::blah as other_blah;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0252]: the name `WOMP` is defined multiple times
+  --> $DIR/issue-25396.rs:13:5
+   |
+LL | use foo::WOMP;
+   |     --------- previous import of the value `WOMP` here
+LL | use bar::WOMP;
+   |     ^^^^^^^^^ `WOMP` reimported here
+   |
+   = note: `WOMP` must be defined only once in the value namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use bar::WOMP as OtherWOMP;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-26886.rs b/src/test/ui/imports/issue-26886.rs
new file mode 100644 (file)
index 0000000..6e6d406
--- /dev/null
@@ -0,0 +1,8 @@
+use std::sync::{self, Arc};
+use std::sync::Arc; //~ ERROR the name `Arc` is defined multiple times
+                    //~| `Arc` must be defined only once in the type namespace of this module
+use std::sync; //~ ERROR the name `sync` is defined multiple times
+               //~| `sync` must be defined only once in the type namespace of this module
+
+fn main() {
+}
diff --git a/src/test/ui/imports/issue-26886.stderr b/src/test/ui/imports/issue-26886.stderr
new file mode 100644 (file)
index 0000000..e2b925e
--- /dev/null
@@ -0,0 +1,24 @@
+error[E0252]: the name `Arc` is defined multiple times
+  --> $DIR/issue-26886.rs:2:5
+   |
+LL | use std::sync::{self, Arc};
+   |                       --- previous import of the type `Arc` here
+LL | use std::sync::Arc;
+   |     ^^^^^^^^^^^^^^ `Arc` reimported here
+   |
+   = note: `Arc` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `sync` is defined multiple times
+  --> $DIR/issue-26886.rs:4:5
+   |
+LL | use std::sync::{self, Arc};
+   |                 ---- previous import of the module `sync` here
+...
+LL | use std::sync;
+   |     ^^^^^^^^^ `sync` reimported here
+   |
+   = note: `sync` must be defined only once in the type namespace of this module
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-28134.rs b/src/test/ui/imports/issue-28134.rs
new file mode 100644 (file)
index 0000000..1ed2d33
--- /dev/null
@@ -0,0 +1,4 @@
+// compile-flags: --test
+
+#![allow(soft_unstable)]
+#![test] //~ ERROR cannot determine resolution for the attribute macro `test`
diff --git a/src/test/ui/imports/issue-28134.stderr b/src/test/ui/imports/issue-28134.stderr
new file mode 100644 (file)
index 0000000..8ed4d01
--- /dev/null
@@ -0,0 +1,10 @@
+error: cannot determine resolution for the attribute macro `test`
+  --> $DIR/issue-28134.rs:4:4
+   |
+LL | #![test]
+   |    ^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/imports/issue-28388-1.rs b/src/test/ui/imports/issue-28388-1.rs
new file mode 100644 (file)
index 0000000..14de621
--- /dev/null
@@ -0,0 +1,5 @@
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+use foo::{}; //~ ERROR unresolved import `foo`
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-28388-1.stderr b/src/test/ui/imports/issue-28388-1.stderr
new file mode 100644 (file)
index 0000000..7f5e47a
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `foo`
+  --> $DIR/issue-28388-1.rs:3:5
+   |
+LL | use foo::{};
+   |     ^^^^^^^ no `foo` in the root
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-28388-2.rs b/src/test/ui/imports/issue-28388-2.rs
new file mode 100644 (file)
index 0000000..024b038
--- /dev/null
@@ -0,0 +1,10 @@
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+mod m {
+    mod n {}
+}
+
+use m::n::{};
+//~^ ERROR module `n` is private
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-28388-2.stderr b/src/test/ui/imports/issue-28388-2.stderr
new file mode 100644 (file)
index 0000000..1afaf62
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0603]: module `n` is private
+  --> $DIR/issue-28388-2.rs:7:8
+   |
+LL | use m::n::{};
+   |        ^ private module
+   |
+note: the module `n` is defined here
+  --> $DIR/issue-28388-2.rs:4:5
+   |
+LL |     mod n {}
+   |     ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/imports/issue-2937.rs b/src/test/ui/imports/issue-2937.rs
new file mode 100644 (file)
index 0000000..335df5c
--- /dev/null
@@ -0,0 +1,6 @@
+use m::f as x; //~ ERROR unresolved import `m::f` [E0432]
+               //~^ no `f` in `m`
+
+mod m {}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-2937.stderr b/src/test/ui/imports/issue-2937.stderr
new file mode 100644 (file)
index 0000000..4286348
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `m::f`
+  --> $DIR/issue-2937.rs:1:5
+   |
+LL | use m::f as x;
+   |     ^^^^^^^^^ no `f` in `m`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-30560.rs b/src/test/ui/imports/issue-30560.rs
new file mode 100644 (file)
index 0000000..d8d4ca6
--- /dev/null
@@ -0,0 +1,9 @@
+type Alias = ();
+use Alias::*; //~ ERROR unresolved import `Alias` [E0432]
+
+use std::io::Result::*; //~ ERROR unresolved import `std::io::Result` [E0432]
+
+trait T {}
+use T::*; //~ ERROR items in traits are not importable
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-30560.stderr b/src/test/ui/imports/issue-30560.stderr
new file mode 100644 (file)
index 0000000..b74134a
--- /dev/null
@@ -0,0 +1,21 @@
+error: items in traits are not importable.
+  --> $DIR/issue-30560.rs:7:5
+   |
+LL | use T::*;
+   |     ^^^^
+
+error[E0432]: unresolved import `Alias`
+  --> $DIR/issue-30560.rs:2:5
+   |
+LL | use Alias::*;
+   |     ^^^^^ `Alias` is a type alias, not a module
+
+error[E0432]: unresolved import `std::io::Result`
+  --> $DIR/issue-30560.rs:4:14
+   |
+LL | use std::io::Result::*;
+   |              ^^^^^^ `Result` is a type alias, not a module
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-31212.rs b/src/test/ui/imports/issue-31212.rs
new file mode 100644 (file)
index 0000000..556f0d1
--- /dev/null
@@ -0,0 +1,10 @@
+// This checks that a path that cannot be resolved because of an indeterminate import
+// does not trigger an ICE.
+
+mod foo {
+    pub use self::*; //~ ERROR unresolved
+}
+
+fn main() {
+    foo::f(); //~ ERROR cannot find function `f` in module `foo`
+}
diff --git a/src/test/ui/imports/issue-31212.stderr b/src/test/ui/imports/issue-31212.stderr
new file mode 100644 (file)
index 0000000..0bb56b3
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0432]: unresolved import `self::*`
+  --> $DIR/issue-31212.rs:5:13
+   |
+LL |     pub use self::*;
+   |             ^^^^^^^ cannot glob-import a module into itself
+
+error[E0425]: cannot find function `f` in module `foo`
+  --> $DIR/issue-31212.rs:9:10
+   |
+LL |     foo::f();
+   |          ^ not found in `foo`
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0425, E0432.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/imports/issue-32354-suggest-import-rename.fixed b/src/test/ui/imports/issue-32354-suggest-import-rename.fixed
new file mode 100644 (file)
index 0000000..27f1b89
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(unused_imports)]
+
+pub mod extension1 {
+    pub trait ConstructorExtension {}
+}
+
+pub mod extension2 {
+    pub trait ConstructorExtension {}
+}
+
+use extension1::ConstructorExtension;
+use extension2::ConstructorExtension as OtherConstructorExtension; //~ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-32354-suggest-import-rename.rs b/src/test/ui/imports/issue-32354-suggest-import-rename.rs
new file mode 100644 (file)
index 0000000..5a7f234
--- /dev/null
@@ -0,0 +1,16 @@
+// run-rustfix
+
+#![allow(unused_imports)]
+
+pub mod extension1 {
+    pub trait ConstructorExtension {}
+}
+
+pub mod extension2 {
+    pub trait ConstructorExtension {}
+}
+
+use extension1::ConstructorExtension;
+use extension2::ConstructorExtension; //~ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-32354-suggest-import-rename.stderr b/src/test/ui/imports/issue-32354-suggest-import-rename.stderr
new file mode 100644 (file)
index 0000000..9668430
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0252]: the name `ConstructorExtension` is defined multiple times
+  --> $DIR/issue-32354-suggest-import-rename.rs:14:5
+   |
+LL | use extension1::ConstructorExtension;
+   |     -------------------------------- previous import of the trait `ConstructorExtension` here
+LL | use extension2::ConstructorExtension;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ConstructorExtension` reimported here
+   |
+   = note: `ConstructorExtension` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use extension2::ConstructorExtension as OtherConstructorExtension;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-32833.rs b/src/test/ui/imports/issue-32833.rs
new file mode 100644 (file)
index 0000000..379eedd
--- /dev/null
@@ -0,0 +1,7 @@
+use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432]
+              //~^ no `Foo` in `bar`
+mod bar {
+    use Foo;
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-32833.stderr b/src/test/ui/imports/issue-32833.stderr
new file mode 100644 (file)
index 0000000..430cc0f
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `bar::Foo`
+  --> $DIR/issue-32833.rs:1:5
+   |
+LL | use bar::Foo;
+   |     ^^^^^^^^ no `Foo` in `bar`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-33464.rs b/src/test/ui/imports/issue-33464.rs
new file mode 100644 (file)
index 0000000..a0edb5f
--- /dev/null
@@ -0,0 +1,10 @@
+// Make sure that the spans of import errors are correct.
+
+use abc::one_el;
+//~^ ERROR
+use abc::{a, bbb, cccccc};
+//~^ ERROR
+use a_very_long_name::{el, el2};
+//~^ ERROR
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-33464.stderr b/src/test/ui/imports/issue-33464.stderr
new file mode 100644 (file)
index 0000000..d3bf404
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0432]: unresolved import `abc`
+  --> $DIR/issue-33464.rs:3:5
+   |
+LL | use abc::one_el;
+   |     ^^^ maybe a missing crate `abc`?
+
+error[E0432]: unresolved import `abc`
+  --> $DIR/issue-33464.rs:5:5
+   |
+LL | use abc::{a, bbb, cccccc};
+   |     ^^^ maybe a missing crate `abc`?
+
+error[E0432]: unresolved import `a_very_long_name`
+  --> $DIR/issue-33464.rs:7:5
+   |
+LL | use a_very_long_name::{el, el2};
+   |     ^^^^^^^^^^^^^^^^ maybe a missing crate `a_very_long_name`?
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-36881.rs b/src/test/ui/imports/issue-36881.rs
new file mode 100644 (file)
index 0000000..0431387
--- /dev/null
@@ -0,0 +1,6 @@
+// aux-build:issue-36881-aux.rs
+
+fn main() {
+    extern crate issue_36881_aux;
+    use issue_36881_aux::Foo; //~ ERROR unresolved import
+}
diff --git a/src/test/ui/imports/issue-36881.stderr b/src/test/ui/imports/issue-36881.stderr
new file mode 100644 (file)
index 0000000..caf9d5d
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0432]: unresolved import `issue_36881_aux`
+  --> $DIR/issue-36881.rs:5:9
+   |
+LL |     use issue_36881_aux::Foo;
+   |         ^^^^^^^^^^^^^^^ maybe a missing crate `issue_36881_aux`?
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-37887.rs b/src/test/ui/imports/issue-37887.rs
new file mode 100644 (file)
index 0000000..58f0c6b
--- /dev/null
@@ -0,0 +1,4 @@
+fn main() {
+    extern crate libc; //~ ERROR use of unstable
+    use libc::*; //~ ERROR unresolved import
+}
diff --git a/src/test/ui/imports/issue-37887.stderr b/src/test/ui/imports/issue-37887.stderr
new file mode 100644 (file)
index 0000000..944d544
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0432]: unresolved import `libc`
+  --> $DIR/issue-37887.rs:3:9
+   |
+LL |     use libc::*;
+   |         ^^^^ maybe a missing crate `libc`?
+
+error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
+  --> $DIR/issue-37887.rs:2:5
+   |
+LL |     extern crate libc;
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information
+   = help: add `#![feature(rustc_private)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0432, E0658.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-38293.rs b/src/test/ui/imports/issue-38293.rs
new file mode 100644 (file)
index 0000000..3b13936
--- /dev/null
@@ -0,0 +1,16 @@
+// Test that `fn foo::bar::{self}` only imports `bar` in the type namespace.
+
+mod foo {
+    pub fn f() { }
+}
+use foo::f::{self}; //~ ERROR unresolved import `foo::f`
+
+mod bar {
+    pub fn baz() {}
+    pub mod baz {}
+}
+use bar::baz::{self};
+
+fn main() {
+    baz(); //~ ERROR expected function, found module `baz`
+}
diff --git a/src/test/ui/imports/issue-38293.stderr b/src/test/ui/imports/issue-38293.stderr
new file mode 100644 (file)
index 0000000..d2450ab
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0432]: unresolved import `foo::f`
+  --> $DIR/issue-38293.rs:6:14
+   |
+LL | use foo::f::{self};
+   |              ^^^^ no `f` in `foo`
+
+error[E0423]: expected function, found module `baz`
+  --> $DIR/issue-38293.rs:15:5
+   |
+LL |     baz();
+   |     ^^^ not a function
+   |
+help: consider importing this function instead
+   |
+LL | use bar::baz;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0423, E0432.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/imports/issue-4366-2.rs b/src/test/ui/imports/issue-4366-2.rs
new file mode 100644 (file)
index 0000000..c777b75
--- /dev/null
@@ -0,0 +1,26 @@
+// ensures that 'use foo:*' doesn't import non-public item
+
+use m1::*;
+
+mod foo {
+    pub fn foo() {}
+}
+mod a {
+    pub mod b {
+        use foo::foo;
+        type Bar = isize;
+    }
+    pub mod sub {
+        use a::b::*;
+        fn sub() -> Bar { 1 }
+        //~^ ERROR cannot find type `Bar` in this scope
+    }
+}
+
+mod m1 {
+    fn foo() {}
+}
+
+fn main() {
+    foo(); //~ ERROR expected function, found module `foo`
+}
diff --git a/src/test/ui/imports/issue-4366-2.stderr b/src/test/ui/imports/issue-4366-2.stderr
new file mode 100644 (file)
index 0000000..a86ec7f
--- /dev/null
@@ -0,0 +1,26 @@
+error[E0412]: cannot find type `Bar` in this scope
+  --> $DIR/issue-4366-2.rs:15:21
+   |
+LL |         fn sub() -> Bar { 1 }
+   |                     ^^^ not found in this scope
+   |
+help: consider importing this type alias
+   |
+LL |         use a::b::Bar;
+   |
+
+error[E0423]: expected function, found module `foo`
+  --> $DIR/issue-4366-2.rs:25:5
+   |
+LL |     foo();
+   |     ^^^ not a function
+   |
+help: consider importing this function instead
+   |
+LL | use foo::foo;
+   |
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0412, E0423.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/imports/issue-4366.rs b/src/test/ui/imports/issue-4366.rs
new file mode 100644 (file)
index 0000000..9ec2e58
--- /dev/null
@@ -0,0 +1,26 @@
+// regression test for issue 4366
+
+// ensures that 'use foo:*' doesn't import non-public 'use' statements in the
+// module 'foo'
+
+use m1::*;
+
+mod foo {
+    pub fn foo() {}
+}
+mod a {
+    pub mod b {
+        use foo::foo;
+        type Bar = isize;
+    }
+    pub mod sub {
+        use a::b::*;
+        fn sub() -> isize { foo(); 1 } //~ ERROR cannot find function `foo` in this scope
+    }
+}
+
+mod m1 {
+    fn foo() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-4366.stderr b/src/test/ui/imports/issue-4366.stderr
new file mode 100644 (file)
index 0000000..469ea93
--- /dev/null
@@ -0,0 +1,14 @@
+error[E0425]: cannot find function `foo` in this scope
+  --> $DIR/issue-4366.rs:18:29
+   |
+LL |         fn sub() -> isize { foo(); 1 }
+   |                             ^^^ not found in this scope
+   |
+help: consider importing this function
+   |
+LL |         use foo::foo;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
new file mode 100644 (file)
index 0000000..b463848
--- /dev/null
@@ -0,0 +1,5 @@
+// run-rustfix
+
+extern crate std as other_std;
+fn main() {}
+//~^^ ERROR the name `std` is defined multiple times [E0259]
diff --git a/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
new file mode 100644 (file)
index 0000000..1b491ac
--- /dev/null
@@ -0,0 +1,5 @@
+// run-rustfix
+
+extern crate std;
+fn main() {}
+//~^^ ERROR the name `std` is defined multiple times [E0259]
diff --git a/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/imports/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
new file mode 100644 (file)
index 0000000..25aca4c
--- /dev/null
@@ -0,0 +1,15 @@
+error[E0259]: the name `std` is defined multiple times
+  --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:3:1
+   |
+LL | extern crate std;
+   | ^^^^^^^^^^^^^^^^^ `std` reimported here
+   |
+   = note: `std` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate std as other_std;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/imports/issue-45829/auxiliary/issue-45829-a.rs b/src/test/ui/imports/issue-45829/auxiliary/issue-45829-a.rs
new file mode 100644 (file)
index 0000000..e9f7fef
--- /dev/null
@@ -0,0 +1 @@
+pub const FOO: usize = *&0;
diff --git a/src/test/ui/imports/issue-45829/auxiliary/issue-45829-b.rs b/src/test/ui/imports/issue-45829/auxiliary/issue-45829-b.rs
new file mode 100644 (file)
index 0000000..e9f7fef
--- /dev/null
@@ -0,0 +1 @@
+pub const FOO: usize = *&0;
diff --git a/src/test/ui/imports/issue-45829/import-self.rs b/src/test/ui/imports/issue-45829/import-self.rs
new file mode 100644 (file)
index 0000000..2dc4331
--- /dev/null
@@ -0,0 +1,19 @@
+mod foo {
+    pub struct A;
+    pub struct B;
+}
+
+use foo::{self};
+//~^ ERROR is defined multiple times
+
+use foo as self;
+//~^ ERROR expected identifier
+
+use foo::self; //~ ERROR is defined multiple times
+//~^ ERROR `self` imports are only allowed within a { } list
+
+use foo::A;
+use foo::{self as A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-45829/import-self.stderr b/src/test/ui/imports/issue-45829/import-self.stderr
new file mode 100644 (file)
index 0000000..158e81c
--- /dev/null
@@ -0,0 +1,69 @@
+error: expected identifier, found keyword `self`
+  --> $DIR/import-self.rs:9:12
+   |
+LL | use foo as self;
+   |            ^^^^ expected identifier, found keyword
+
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/import-self.rs:12:8
+   |
+LL | use foo::self;
+   |        ^^^^^^
+   |
+help: consider importing the module directly
+   |
+LL | use foo;
+   |       --
+help: alternatively, use the multi-path `use` syntax to import `self`
+   |
+LL | use foo::{self};
+   |          ^    ^
+
+error[E0255]: the name `foo` is defined multiple times
+  --> $DIR/import-self.rs:6:11
+   |
+LL | mod foo {
+   | ------- previous definition of the module `foo` here
+...
+LL | use foo::{self};
+   |           ^^^^ `foo` reimported here
+   |
+   = note: `foo` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::{self as other_foo};
+   |           ^^^^^^^^^^^^^^^^^
+
+error[E0255]: the name `foo` is defined multiple times
+  --> $DIR/import-self.rs:12:5
+   |
+LL | mod foo {
+   | ------- previous definition of the module `foo` here
+...
+LL | use foo::self;
+   |     ^^^^^^^^^ `foo` reimported here
+   |
+   = note: `foo` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo as other_foo;
+   |     ^^^^^^^^^^^^^^^^
+
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/import-self.rs:16:11
+   |
+LL | use foo::A;
+   |     ------ previous import of the type `A` here
+LL | use foo::{self as A};
+   |           ^^^^^^^^^ `A` reimported here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::{self as OtherA};
+   |           ^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0252, E0255, E0429.
+For more information about an error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-45829/import-twice.rs b/src/test/ui/imports/issue-45829/import-twice.rs
new file mode 100644 (file)
index 0000000..e5a8bb7
--- /dev/null
@@ -0,0 +1,9 @@
+mod foo {
+    pub struct A;
+    pub struct B;
+}
+
+use foo::{A, A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-45829/import-twice.stderr b/src/test/ui/imports/issue-45829/import-twice.stderr
new file mode 100644 (file)
index 0000000..656b011
--- /dev/null
@@ -0,0 +1,13 @@
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/import-twice.rs:6:14
+   |
+LL | use foo::{A, A};
+   |           -  ^ `A` reimported here
+   |           |
+   |           previous import of the type `A` here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-45829/issue-45829.rs b/src/test/ui/imports/issue-45829/issue-45829.rs
new file mode 100644 (file)
index 0000000..1e76e4b
--- /dev/null
@@ -0,0 +1,9 @@
+mod foo {
+    pub struct A;
+    pub struct B;
+}
+
+use foo::{A, B as A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-45829/issue-45829.stderr b/src/test/ui/imports/issue-45829/issue-45829.stderr
new file mode 100644 (file)
index 0000000..a7ebc71
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/issue-45829.rs:6:14
+   |
+LL | use foo::{A, B as A};
+   |           -  ^^^^^^ `A` reimported here
+   |           |
+   |           previous import of the type `A` here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::{A, B as OtherA};
+   |              ^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-45829/rename-extern-vs-use.rs b/src/test/ui/imports/issue-45829/rename-extern-vs-use.rs
new file mode 100644 (file)
index 0000000..aef7aa3
--- /dev/null
@@ -0,0 +1,11 @@
+// aux-build:issue-45829-b.rs
+
+mod foo {
+    pub mod bar {}
+}
+
+use foo::bar;
+extern crate issue_45829_b as bar;
+//~^ ERROR the name `bar` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-45829/rename-extern-vs-use.stderr b/src/test/ui/imports/issue-45829/rename-extern-vs-use.stderr
new file mode 100644 (file)
index 0000000..98fd8a6
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0254]: the name `bar` is defined multiple times
+  --> $DIR/rename-extern-vs-use.rs:8:1
+   |
+LL | use foo::bar;
+   |     -------- previous import of the module `bar` here
+LL | extern crate issue_45829_b as bar;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` reimported here
+   |
+   = note: `bar` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate issue_45829_b as other_bar;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0254`.
diff --git a/src/test/ui/imports/issue-45829/rename-extern-with-tab.rs b/src/test/ui/imports/issue-45829/rename-extern-with-tab.rs
new file mode 100644 (file)
index 0000000..0da8b82
--- /dev/null
@@ -0,0 +1,8 @@
+// aux-build:issue-45829-a.rs
+// aux-build:issue-45829-b.rs
+
+extern crate issue_45829_a;
+extern  crate    issue_45829_b  as  issue_45829_a;
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-45829/rename-extern-with-tab.stderr b/src/test/ui/imports/issue-45829/rename-extern-with-tab.stderr
new file mode 100644 (file)
index 0000000..2c4e8ce
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0259]: the name `issue_45829_a` is defined multiple times
+  --> $DIR/rename-extern-with-tab.rs:5:1
+   |
+LL | extern crate issue_45829_a;
+   | --------------------------- previous import of the extern crate `issue_45829_a` here
+LL | extern  crate    issue_45829_b  as  issue_45829_a;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here
+   |
+   = note: `issue_45829_a` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate issue_45829_b as other_issue_45829_a;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/imports/issue-45829/rename-extern.rs b/src/test/ui/imports/issue-45829/rename-extern.rs
new file mode 100644 (file)
index 0000000..7dbda69
--- /dev/null
@@ -0,0 +1,8 @@
+// aux-build:issue-45829-a.rs
+// aux-build:issue-45829-b.rs
+
+extern crate issue_45829_a;
+extern crate issue_45829_b as issue_45829_a;
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-45829/rename-extern.stderr b/src/test/ui/imports/issue-45829/rename-extern.stderr
new file mode 100644 (file)
index 0000000..209ae22
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0259]: the name `issue_45829_a` is defined multiple times
+  --> $DIR/rename-extern.rs:5:1
+   |
+LL | extern crate issue_45829_a;
+   | --------------------------- previous import of the extern crate `issue_45829_a` here
+LL | extern crate issue_45829_b as issue_45829_a;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here
+   |
+   = note: `issue_45829_a` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | extern crate issue_45829_b as other_issue_45829_a;
+   |
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/imports/issue-45829/rename-use-vs-extern.rs b/src/test/ui/imports/issue-45829/rename-use-vs-extern.rs
new file mode 100644 (file)
index 0000000..0cf3a77
--- /dev/null
@@ -0,0 +1,7 @@
+// aux-build:issue-45829-b.rs
+
+extern crate issue_45829_b;
+use std as issue_45829_b;
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-45829/rename-use-vs-extern.stderr b/src/test/ui/imports/issue-45829/rename-use-vs-extern.stderr
new file mode 100644 (file)
index 0000000..6b917d5
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0254]: the name `issue_45829_b` is defined multiple times
+  --> $DIR/rename-use-vs-extern.rs:4:5
+   |
+LL | extern crate issue_45829_b;
+   | --------------------------- previous import of the extern crate `issue_45829_b` here
+LL | use std as issue_45829_b;
+   |     ^^^^^^^^^^^^^^^^^^^^ `issue_45829_b` reimported here
+   |
+   = note: `issue_45829_b` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std as other_issue_45829_b;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0254`.
diff --git a/src/test/ui/imports/issue-45829/rename-use-with-tabs.rs b/src/test/ui/imports/issue-45829/rename-use-with-tabs.rs
new file mode 100644 (file)
index 0000000..86c5fa0
--- /dev/null
@@ -0,0 +1,12 @@
+mod foo {
+    pub struct A;
+
+    pub mod bar {
+        pub struct B;
+    }
+}
+
+use foo::{A, bar::B    as    A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-45829/rename-use-with-tabs.stderr b/src/test/ui/imports/issue-45829/rename-use-with-tabs.stderr
new file mode 100644 (file)
index 0000000..3baad6c
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/rename-use-with-tabs.rs:9:14
+   |
+LL | use foo::{A, bar::B    as    A};
+   |           -  ^^^^^^^^^^^^^^^^^ `A` reimported here
+   |           |
+   |           previous import of the type `A` here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use foo::{A, bar::B as OtherA};
+   |              ^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-45829/rename-with-path.rs b/src/test/ui/imports/issue-45829/rename-with-path.rs
new file mode 100644 (file)
index 0000000..e278a87
--- /dev/null
@@ -0,0 +1,4 @@
+use std::{collections::HashMap as A, sync::Arc as A};
+//~^ ERROR is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-45829/rename-with-path.stderr b/src/test/ui/imports/issue-45829/rename-with-path.stderr
new file mode 100644 (file)
index 0000000..ba83eea
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0252]: the name `A` is defined multiple times
+  --> $DIR/rename-with-path.rs:1:38
+   |
+LL | use std::{collections::HashMap as A, sync::Arc as A};
+   |           -------------------------  ^^^^^^^^^^^^^^ `A` reimported here
+   |           |
+   |           previous import of the type `A` here
+   |
+   = note: `A` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std::{collections::HashMap as A, sync::Arc as OtherA};
+   |                                      ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-45829/rename.rs b/src/test/ui/imports/issue-45829/rename.rs
new file mode 100644 (file)
index 0000000..1c45956
--- /dev/null
@@ -0,0 +1,7 @@
+use core;
+use std as core;
+//~^ ERROR is defined multiple times
+
+fn main() {
+    1 + 1;
+}
diff --git a/src/test/ui/imports/issue-45829/rename.stderr b/src/test/ui/imports/issue-45829/rename.stderr
new file mode 100644 (file)
index 0000000..8f12d92
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0252]: the name `core` is defined multiple times
+  --> $DIR/rename.rs:2:5
+   |
+LL | use core;
+   |     ---- previous import of the module `core` here
+LL | use std as core;
+   |     ^^^^^^^^^^^ `core` reimported here
+   |
+   = note: `core` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use std as other_core;
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-47623.rs b/src/test/ui/imports/issue-47623.rs
new file mode 100644 (file)
index 0000000..ad8aa4c
--- /dev/null
@@ -0,0 +1,3 @@
+use self; //~ERROR `self` imports are only allowed within a { } list
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-47623.stderr b/src/test/ui/imports/issue-47623.stderr
new file mode 100644 (file)
index 0000000..53968a2
--- /dev/null
@@ -0,0 +1,9 @@
+error[E0429]: `self` imports are only allowed within a { } list
+  --> $DIR/issue-47623.rs:1:5
+   |
+LL | use self;
+   |     ^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0429`.
diff --git a/src/test/ui/imports/issue-4865-1.rs b/src/test/ui/imports/issue-4865-1.rs
new file mode 100644 (file)
index 0000000..68fbee3
--- /dev/null
@@ -0,0 +1,33 @@
+// run-pass
+#![allow(unused_imports)]
+// This should resolve fine.
+// Prior to fix, the crossed imports between a and b
+// would block on the glob import, itself never being resolved
+// because these previous imports were not resolved.
+
+pub mod a {
+    use b::fn_b;
+    use c::*;
+
+    pub fn fn_a(){
+    }
+}
+
+pub mod b {
+    use a::fn_a;
+    use c::*;
+
+    pub fn fn_b(){
+    }
+}
+
+pub mod c{
+    pub fn fn_c(){
+    }
+}
+
+use a::fn_a;
+use b::fn_b;
+
+fn main() {
+}
diff --git a/src/test/ui/imports/issue-4865-2.rs b/src/test/ui/imports/issue-4865-2.rs
new file mode 100644 (file)
index 0000000..cbe1d0d
--- /dev/null
@@ -0,0 +1,24 @@
+// run-pass
+// Previously, this would have failed to resolve due to the circular
+// block between `use say` and `pub use hello::*`.
+//
+// Now, as `use say` is not `pub`, the glob import can resolve
+// without any problem and this resolves fine.
+
+pub use hello::*;
+
+pub mod say {
+    pub fn hello() { println!("hello"); }
+}
+
+pub mod hello {
+    use say;
+
+    pub fn hello() {
+        say::hello();
+    }
+}
+
+fn main() {
+    hello();
+}
diff --git a/src/test/ui/imports/issue-4865-3.rs b/src/test/ui/imports/issue-4865-3.rs
new file mode 100644 (file)
index 0000000..12f9bba
--- /dev/null
@@ -0,0 +1,17 @@
+// run-pass
+#![allow(unused_imports)]
+// This should resolve fine even with the circular imports as
+// they are not `pub`.
+
+pub mod a {
+    use b::*;
+}
+
+pub mod b {
+    use a::*;
+}
+
+use a::*;
+
+fn main() {
+}
diff --git a/src/test/ui/imports/issue-52891.fixed b/src/test/ui/imports/issue-52891.fixed
new file mode 100644 (file)
index 0000000..e694b5c
--- /dev/null
@@ -0,0 +1,37 @@
+// aux-build:issue-52891.rs
+// run-rustfix
+
+#![allow(warnings)]
+
+extern crate issue_52891;
+
+// Check that we don't suggest renaming duplicate imports but instead
+// suggest removing one.
+
+use issue_52891::a;
+ //~ ERROR `a` is defined multiple times
+
+use issue_52891::{b, c}; //~ ERROR `a` is defined multiple times
+use issue_52891::{d, e}; //~ ERROR `a` is defined multiple times
+use issue_52891::{f, g}; //~ ERROR `a` is defined multiple times
+
+use issue_52891::{//~ ERROR `a` is defined multiple times
+    h,
+    i};
+use issue_52891::{j,
+    //~ ERROR `a` is defined multiple times
+    k};
+use issue_52891::{l,
+    m}; //~ ERROR `a` is defined multiple times
+
+use issue_52891::a::inner;
+use issue_52891::b::inner as other_inner; //~ ERROR `inner` is defined multiple times
+
+
+//~^ ERROR `issue_52891` is defined multiple times
+
+
+#[macro_use]
+use issue_52891::n; //~ ERROR `n` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-52891.rs b/src/test/ui/imports/issue-52891.rs
new file mode 100644 (file)
index 0000000..cd4b406
--- /dev/null
@@ -0,0 +1,38 @@
+// aux-build:issue-52891.rs
+// run-rustfix
+
+#![allow(warnings)]
+
+extern crate issue_52891;
+
+// Check that we don't suggest renaming duplicate imports but instead
+// suggest removing one.
+
+use issue_52891::a;
+use issue_52891::a; //~ ERROR `a` is defined multiple times
+
+use issue_52891::{a, b, c}; //~ ERROR `a` is defined multiple times
+use issue_52891::{d, a, e}; //~ ERROR `a` is defined multiple times
+use issue_52891::{f, g, a}; //~ ERROR `a` is defined multiple times
+
+use issue_52891::{a, //~ ERROR `a` is defined multiple times
+    h,
+    i};
+use issue_52891::{j,
+    a, //~ ERROR `a` is defined multiple times
+    k};
+use issue_52891::{l,
+    m,
+    a}; //~ ERROR `a` is defined multiple times
+
+use issue_52891::a::inner;
+use issue_52891::b::inner; //~ ERROR `inner` is defined multiple times
+
+use issue_52891::{self};
+//~^ ERROR `issue_52891` is defined multiple times
+
+use issue_52891::n;
+#[macro_use]
+use issue_52891::n; //~ ERROR `n` is defined multiple times
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-52891.stderr b/src/test/ui/imports/issue-52891.stderr
new file mode 100644 (file)
index 0000000..6e6e42d
--- /dev/null
@@ -0,0 +1,131 @@
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:12:5
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+LL | use issue_52891::a;
+   |     ^^^^^^^^^^^^^^ `a` reimported here
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:14:19
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL | use issue_52891::{a, b, c};
+   |                   ^--
+   |                   |
+   |                   `a` reimported here
+   |                   help: remove unnecessary import
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:15:22
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL | use issue_52891::{d, a, e};
+   |                      ^--
+   |                      |
+   |                      `a` reimported here
+   |                      help: remove unnecessary import
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:16:25
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL | use issue_52891::{f, g, a};
+   |                         ^ `a` reimported here
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:18:19
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL | use issue_52891::{a,
+   |                   ^--
+   |                   |
+   |                   `a` reimported here
+   |                   help: remove unnecessary import
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:22:5
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL |     a,
+   |     ^--
+   |     |
+   |     `a` reimported here
+   |     help: remove unnecessary import
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `a` is defined multiple times
+  --> $DIR/issue-52891.rs:26:5
+   |
+LL | use issue_52891::a;
+   |     -------------- previous import of the module `a` here
+...
+LL |     a};
+   |     ^ `a` reimported here
+   |
+   = note: `a` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `inner` is defined multiple times
+  --> $DIR/issue-52891.rs:29:5
+   |
+LL | use issue_52891::a::inner;
+   |     --------------------- previous import of the module `inner` here
+LL | use issue_52891::b::inner;
+   |     ^^^^^^^^^^^^^^^^^^^^^ `inner` reimported here
+   |
+   = note: `inner` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL | use issue_52891::b::inner as other_inner;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0254]: the name `issue_52891` is defined multiple times
+  --> $DIR/issue-52891.rs:31:19
+   |
+LL | extern crate issue_52891;
+   | ------------------------- previous import of the extern crate `issue_52891` here
+...
+LL | use issue_52891::{self};
+   | ------------------^^^^--
+   | |                 |
+   | |                 `issue_52891` reimported here
+   | help: remove unnecessary import
+   |
+   = note: `issue_52891` must be defined only once in the type namespace of this module
+
+error[E0252]: the name `n` is defined multiple times
+  --> $DIR/issue-52891.rs:36:5
+   |
+LL | use issue_52891::n;
+   |     -------------- previous import of the module `n` here
+LL | #[macro_use]
+LL | use issue_52891::n;
+   |     ^^^^^^^^^^^^^^ `n` reimported here
+   |
+   = note: `n` must be defined only once in the type namespace of this module
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0252, E0254.
+For more information about an error, try `rustc --explain E0252`.
diff --git a/src/test/ui/imports/issue-53565.rs b/src/test/ui/imports/issue-53565.rs
new file mode 100644 (file)
index 0000000..114a53a
--- /dev/null
@@ -0,0 +1,7 @@
+use std::time::{foo, bar, buzz};
+//~^ ERROR unresolved imports
+use std::time::{abc, def};
+//~^ ERROR unresolved imports
+fn main(){
+    println!("Hello World!");
+}
diff --git a/src/test/ui/imports/issue-53565.stderr b/src/test/ui/imports/issue-53565.stderr
new file mode 100644 (file)
index 0000000..71c3b2a
--- /dev/null
@@ -0,0 +1,20 @@
+error[E0432]: unresolved imports `std::time::foo`, `std::time::bar`, `std::time::buzz`
+  --> $DIR/issue-53565.rs:1:17
+   |
+LL | use std::time::{foo, bar, buzz};
+   |                 ^^^  ^^^  ^^^^ no `buzz` in `time`
+   |                 |    |
+   |                 |    no `bar` in `time`
+   |                 no `foo` in `time`
+
+error[E0432]: unresolved imports `std::time::abc`, `std::time::def`
+  --> $DIR/issue-53565.rs:3:17
+   |
+LL | use std::time::{abc, def};
+   |                 ^^^  ^^^ no `def` in `time`
+   |                 |
+   |                 no `abc` in `time`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-59764.rs b/src/test/ui/imports/issue-59764.rs
new file mode 100644 (file)
index 0000000..09dee8c
--- /dev/null
@@ -0,0 +1,136 @@
+// aux-build:issue-59764.rs
+// compile-flags:--extern issue_59764
+// edition:2018
+
+#![allow(warnings)]
+
+// This tests the suggestion to import macros from the root of a crate. This aims to capture
+// the case where a user attempts to import a macro from the definition location instead of the
+// root of the crate and the macro is annotated with `#![macro_export]`.
+
+// Edge cases..
+
+mod multiple_imports_same_line_at_end {
+    use issue_59764::foo::{baz, makro};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod multiple_imports_multiline_at_end_trailing_comma {
+    use issue_59764::foo::{
+        baz,
+        makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+    };
+}
+
+mod multiple_imports_multiline_at_end {
+    use issue_59764::foo::{
+        baz,
+        makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+    };
+}
+
+mod multiple_imports_same_line_in_middle {
+    use issue_59764::foo::{baz, makro, foobar};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod multiple_imports_multiline_in_middle_trailing_comma {
+    use issue_59764::foo::{
+        baz,
+        makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+        foobar,
+    };
+}
+
+mod multiple_imports_multiline_in_middle {
+    use issue_59764::foo::{
+        baz,
+        makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+        foobar
+    };
+}
+
+mod nested_imports {
+    use issue_59764::{foobaz, foo::makro};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod nested_multiple_imports {
+    use issue_59764::{foobaz, foo::{baz, makro}};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod nested_multiline_multiple_imports_trailing_comma {
+    use issue_59764::{
+        foobaz,
+        foo::{
+            baz,
+            makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+        },
+    };
+}
+
+mod nested_multiline_multiple_imports {
+    use issue_59764::{
+        foobaz,
+        foo::{
+            baz,
+            makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+        }
+    };
+}
+
+mod doubly_nested_multiple_imports {
+    use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod doubly_multiline_nested_multiple_imports {
+    use issue_59764::{
+        foobaz,
+        foo::{
+            baz,
+            makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+            barbaz::{
+                barfoo,
+            }
+        }
+    };
+}
+
+mod renamed_import {
+    use issue_59764::foo::makro as baz;
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod renamed_multiple_imports {
+    use issue_59764::foo::{baz, makro as foobar};
+    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+}
+
+mod lots_of_whitespace {
+    use
+        issue_59764::{
+
+            foobaz,
+
+
+            foo::{baz,
+
+                makro as foobar} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+
+        };
+}
+
+// Simple case..
+
+use issue_59764::foo::makro;
+//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
+
+makro!(bar);
+//~^ ERROR cannot determine resolution for the macro `makro`
+
+fn main() {
+    bar();
+    //~^ ERROR cannot find function `bar` in this scope [E0425]
+}
diff --git a/src/test/ui/imports/issue-59764.stderr b/src/test/ui/imports/issue-59764.stderr
new file mode 100644 (file)
index 0000000..f266e90
--- /dev/null
@@ -0,0 +1,241 @@
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:14:33
+   |
+LL |     use issue_59764::foo::{baz, makro};
+   |                                 ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{baz}};
+   |                      ^^^^^^^^^       --^^
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:21:9
+   |
+LL |         makro,
+   |         ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{
+LL |         baz,
+LL |
+LL |     }};
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:28:9
+   |
+LL |         makro
+   |         ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{
+LL |         baz,
+LL |
+LL |     }};
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:33:33
+   |
+LL |     use issue_59764::foo::{baz, makro, foobar};
+   |                                 ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{baz, foobar}};
+   |                      ^^^^^^^^^         --      ^^
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:40:9
+   |
+LL |         makro,
+   |         ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{
+LL |         baz,
+LL |
+LL |         foobar,
+LL |     }};
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:48:9
+   |
+LL |         makro,
+   |         ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foo::{
+LL |         baz,
+LL |
+LL |         foobar
+LL |     }};
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:54:31
+   |
+LL |     use issue_59764::{foobaz, foo::makro};
+   |                               ^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foobaz};
+   |                      ^^^^^^^      --
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:59:42
+   |
+LL |     use issue_59764::{foobaz, foo::{baz, makro}};
+   |                                          ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foobaz, foo::{baz}};
+   |                      ^^^^^^^                 --
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:68:13
+   |
+LL |             makro,
+   |             ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, 
+LL |         foobaz,
+LL |         foo::{
+LL |             baz,
+LL |
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:78:13
+   |
+LL |             makro
+   |             ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, 
+LL |         foobaz,
+LL |         foo::{
+LL |             baz,
+LL |
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:84:42
+   |
+LL |     use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
+   |                                          ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}};
+   |                      ^^^^^^^                   --
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:93:13
+   |
+LL |             makro,
+   |             ^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro, 
+LL |         foobaz,
+LL |         foo::{
+LL |             baz,
+LL |
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:102:9
+   |
+LL |     use issue_59764::foo::makro as baz;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::makro as baz;
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:107:33
+   |
+LL |     use issue_59764::foo::{baz, makro as foobar};
+   |                                 ^^^^^^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |     use issue_59764::{makro as foobar, foo::{baz}};
+   |                      ^^^^^^^^^^^^^^^^^^^       --^^
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:120:17
+   |
+LL |                 makro as foobar}
+   |                 ^^^^^^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL |         issue_59764::{makro as foobar, 
+LL | 
+LL |             foobaz,
+LL | 
+LL | 
+LL |             foo::{baz}
+   |
+
+error[E0432]: unresolved import `issue_59764::foo::makro`
+  --> $DIR/issue-59764.rs:127:5
+   |
+LL | use issue_59764::foo::makro;
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
+   |
+   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
+help: a macro with this name exists at the root of the crate
+   |
+LL | use issue_59764::makro;
+   |     ^^^^^^^^^^^^^^^^^^
+
+error: cannot determine resolution for the macro `makro`
+  --> $DIR/issue-59764.rs:130:1
+   |
+LL | makro!(bar);
+   | ^^^^^
+   |
+   = note: import resolution is stuck, try simplifying macro imports
+
+error[E0425]: cannot find function `bar` in this scope
+  --> $DIR/issue-59764.rs:134:5
+   |
+LL |     bar();
+   |     ^^^ not found in this scope
+
+error: aborting due to 18 previous errors
+
+Some errors have detailed explanations: E0425, E0432.
+For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/imports/issue-8208.rs b/src/test/ui/imports/issue-8208.rs
new file mode 100644 (file)
index 0000000..1c56693
--- /dev/null
@@ -0,0 +1,17 @@
+use self::*; //~ ERROR: unresolved import `self::*` [E0432]
+             //~^ cannot glob-import a module into itself
+
+mod foo {
+    use foo::*; //~ ERROR: unresolved import `foo::*` [E0432]
+                //~^ cannot glob-import a module into itself
+
+    mod bar {
+        use super::bar::*;
+        //~^ ERROR: unresolved import `super::bar::*` [E0432]
+        //~| cannot glob-import a module into itself
+    }
+
+}
+
+fn main() {
+}
diff --git a/src/test/ui/imports/issue-8208.stderr b/src/test/ui/imports/issue-8208.stderr
new file mode 100644 (file)
index 0000000..e59aea1
--- /dev/null
@@ -0,0 +1,21 @@
+error[E0432]: unresolved import `self::*`
+  --> $DIR/issue-8208.rs:1:5
+   |
+LL | use self::*;
+   |     ^^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `foo::*`
+  --> $DIR/issue-8208.rs:5:9
+   |
+LL |     use foo::*;
+   |         ^^^^^^ cannot glob-import a module into itself
+
+error[E0432]: unresolved import `super::bar::*`
+  --> $DIR/issue-8208.rs:9:13
+   |
+LL |         use super::bar::*;
+   |             ^^^^^^^^^^^^^ cannot glob-import a module into itself
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/imports/issue-8640.rs b/src/test/ui/imports/issue-8640.rs
new file mode 100644 (file)
index 0000000..51a02a3
--- /dev/null
@@ -0,0 +1,10 @@
+#[allow(unused_imports)]
+
+mod foo {
+    use baz::bar;
+    mod bar {}
+    //~^ ERROR the name `bar` is defined multiple times
+}
+mod baz { pub mod bar {} }
+
+fn main() {}
diff --git a/src/test/ui/imports/issue-8640.stderr b/src/test/ui/imports/issue-8640.stderr
new file mode 100644 (file)
index 0000000..4ce6394
--- /dev/null
@@ -0,0 +1,17 @@
+error[E0255]: the name `bar` is defined multiple times
+  --> $DIR/issue-8640.rs:5:5
+   |
+LL |     use baz::bar;
+   |         -------- previous import of the module `bar` here
+LL |     mod bar {}
+   |     ^^^^^^^ `bar` redefined here
+   |
+   = note: `bar` must be defined only once in the type namespace of this module
+help: you can use `as` to change the binding name of the import
+   |
+LL |     use baz::bar as other_bar;
+   |         ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/imports/resolve_self_super_hint.rs b/src/test/ui/imports/resolve_self_super_hint.rs
new file mode 100644 (file)
index 0000000..a14ec5b
--- /dev/null
@@ -0,0 +1,27 @@
+mod a {
+    extern crate alloc;
+    use alloc::HashMap;
+    //~^ ERROR unresolved import `alloc` [E0432]
+    //~| HELP a similar path exists
+    //~| SUGGESTION self::alloc
+    mod b {
+        use alloc::HashMap;
+        //~^ ERROR unresolved import `alloc` [E0432]
+        //~| HELP a similar path exists
+        //~| SUGGESTION super::alloc
+        mod c {
+            use alloc::HashMap;
+            //~^ ERROR unresolved import `alloc` [E0432]
+            //~| HELP a similar path exists
+            //~| SUGGESTION a::alloc
+            mod d {
+                use alloc::HashMap;
+                //~^ ERROR unresolved import `alloc` [E0432]
+                //~| HELP a similar path exists
+                //~| SUGGESTION a::alloc
+            }
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/imports/resolve_self_super_hint.stderr b/src/test/ui/imports/resolve_self_super_hint.stderr
new file mode 100644 (file)
index 0000000..bc86255
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0432]: unresolved import `alloc`
+  --> $DIR/resolve_self_super_hint.rs:3:9
+   |
+LL |     use alloc::HashMap;
+   |         ^^^^^ help: a similar path exists: `self::alloc`
+
+error[E0432]: unresolved import `alloc`
+  --> $DIR/resolve_self_super_hint.rs:8:13
+   |
+LL |         use alloc::HashMap;
+   |             ^^^^^ help: a similar path exists: `super::alloc`
+
+error[E0432]: unresolved import `alloc`
+  --> $DIR/resolve_self_super_hint.rs:13:17
+   |
+LL |             use alloc::HashMap;
+   |                 ^^^^^
+   |                 |
+   |                 unresolved import
+   |                 help: a similar path exists: `a::alloc`
+
+error[E0432]: unresolved import `alloc`
+  --> $DIR/resolve_self_super_hint.rs:18:21
+   |
+LL |                 use alloc::HashMap;
+   |                     ^^^^^
+   |                     |
+   |                     unresolved import
+   |                     help: a similar path exists: `a::alloc`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/auxiliary/issue-36881-aux.rs b/src/test/ui/issues/auxiliary/issue-36881-aux.rs
deleted file mode 100644 (file)
index e373b64..0000000
+++ /dev/null
@@ -1 +0,0 @@
-pub trait Foo {}
diff --git a/src/test/ui/issues/auxiliary/issue-52891.rs b/src/test/ui/issues/auxiliary/issue-52891.rs
deleted file mode 100644 (file)
index 0759811..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-pub mod a {
-    pub mod inner {
-    }
-}
-
-pub mod b {
-    pub mod inner {
-    }
-}
-
-pub mod c {}
-
-pub mod d {}
-
-pub mod e {}
-
-pub mod f {}
-
-pub mod g {}
-
-pub mod h {}
-
-pub mod i {}
-
-pub mod j {}
-
-pub mod k {}
-
-pub mod l {}
-
-pub mod m {}
-
-pub mod n {}
diff --git a/src/test/ui/issues/auxiliary/issue-59764.rs b/src/test/ui/issues/auxiliary/issue-59764.rs
deleted file mode 100644 (file)
index a92eed9..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-pub mod foo {
-    #[macro_export]
-    macro_rules! makro {
-        ($foo:ident) => {
-            fn $foo() { }
-        }
-    }
-
-    pub fn baz() {}
-
-    pub fn foobar() {}
-
-    pub mod barbaz {
-        pub fn barfoo() {}
-    }
-}
-
-pub fn foobaz() {}
diff --git a/src/test/ui/issues/auxiliary/lint-stability.rs b/src/test/ui/issues/auxiliary/lint-stability.rs
deleted file mode 100644 (file)
index de40588..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-#![crate_name="lint_stability"]
-#![crate_type = "lib"]
-#![feature(staged_api)]
-#![feature(associated_type_defaults)]
-#![stable(feature = "lint_stability", since = "1.0.0")]
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub fn deprecated() {}
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub fn deprecated_text() {}
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[rustc_deprecated(since = "99.99.99", reason = "text")]
-pub fn deprecated_future() {}
-
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub fn deprecated_unstable() {}
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub fn deprecated_unstable_text() {}
-
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-pub fn unstable() {}
-#[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
-pub fn unstable_text() {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn stable() {}
-#[stable(feature = "rust1", since = "1.0.0")]
-pub fn stable_text() {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct MethodTester;
-
-impl MethodTester {
-    #[stable(feature = "stable_test_feature", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    pub fn method_deprecated(&self) {}
-    #[stable(feature = "stable_test_feature", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    pub fn method_deprecated_text(&self) {}
-
-    #[unstable(feature = "unstable_test_feature", issue = "none")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    pub fn method_deprecated_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", issue = "none")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    pub fn method_deprecated_unstable_text(&self) {}
-
-    #[unstable(feature = "unstable_test_feature", issue = "none")]
-    pub fn method_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
-    pub fn method_unstable_text(&self) {}
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn method_stable(&self) {}
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn method_stable_text(&self) {}
-}
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-pub trait Trait {
-    #[stable(feature = "stable_test_feature", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    fn trait_deprecated(&self) {}
-    #[stable(feature = "stable_test_feature", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    fn trait_deprecated_text(&self) {}
-
-    #[unstable(feature = "unstable_test_feature", issue = "none")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    fn trait_deprecated_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", issue = "none")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    fn trait_deprecated_unstable_text(&self) {}
-
-    #[unstable(feature = "unstable_test_feature", issue = "none")]
-    fn trait_unstable(&self) {}
-    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
-    fn trait_unstable_text(&self) {}
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn trait_stable(&self) {}
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn trait_stable_text(&self) {}
-}
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-pub trait TraitWithAssociatedTypes {
-    #[unstable(feature = "unstable_test_feature", issue = "none")]
-    type TypeUnstable = u8;
-    #[stable(feature = "stable_test_feature", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    type TypeDeprecated = u8;
-}
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-impl Trait for MethodTester {}
-
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-pub trait UnstableTrait { fn dummy(&self) { } }
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub trait DeprecatedTrait {
-    #[stable(feature = "stable_test_feature", since = "1.0.0")] fn dummy(&self) { }
-}
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub struct DeprecatedStruct {
-    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
-}
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub struct DeprecatedUnstableStruct {
-    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
-}
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-pub struct UnstableStruct {
-    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
-}
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct StableStruct {
-    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
-}
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-pub enum UnstableEnum {}
-#[stable(feature = "rust1", since = "1.0.0")]
-pub enum StableEnum {}
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub struct DeprecatedUnitStruct;
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub struct DeprecatedUnstableUnitStruct;
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-pub struct UnstableUnitStruct;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct StableUnitStruct;
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-pub enum Enum {
-    #[stable(feature = "stable_test_feature", since = "1.0.0")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    DeprecatedVariant,
-    #[unstable(feature = "unstable_test_feature", issue = "none")]
-    #[rustc_deprecated(since = "1.0.0", reason = "text")]
-    DeprecatedUnstableVariant,
-    #[unstable(feature = "unstable_test_feature", issue = "none")]
-    UnstableVariant,
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    StableVariant,
-}
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-#[rustc_deprecated(since = "1.0.0", reason = "text")]
-pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
-#[unstable(feature = "unstable_test_feature", issue = "none")]
-pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[macro_export]
-macro_rules! macro_test {
-    () => (deprecated());
-}
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[macro_export]
-macro_rules! macro_test_arg {
-    ($func:expr) => ($func);
-}
-
-#[stable(feature = "stable_test_feature", since = "1.0.0")]
-#[macro_export]
-macro_rules! macro_test_arg_nested {
-    ($func:ident) => (macro_test_arg!($func()));
-}
diff --git a/src/test/ui/issues/issue-13404.rs b/src/test/ui/issues/issue-13404.rs
deleted file mode 100644 (file)
index c5af827..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-use a::f;
-use b::f; //~ ERROR: unresolved import `b::f` [E0432]
-          //~^ no `f` in `b`
-
-mod a { pub fn f() {} }
-mod b { }
-
-fn main() {
-    f();
-}
diff --git a/src/test/ui/issues/issue-13404.stderr b/src/test/ui/issues/issue-13404.stderr
deleted file mode 100644 (file)
index 1f50deb..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `b::f`
-  --> $DIR/issue-13404.rs:2:5
-   |
-LL | use b::f;
-   |     ^^^^ no `f` in `b`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-1697.rs b/src/test/ui/issues/issue-1697.rs
deleted file mode 100644 (file)
index 5cd76d2..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// Testing that we don't fail abnormally after hitting the errors
-
-use unresolved::*; //~ ERROR unresolved import `unresolved` [E0432]
-                   //~^ maybe a missing crate `unresolved`?
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-1697.stderr b/src/test/ui/issues/issue-1697.stderr
deleted file mode 100644 (file)
index a76fd30..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `unresolved`
-  --> $DIR/issue-1697.rs:3:5
-   |
-LL | use unresolved::*;
-   |     ^^^^^^^^^^ maybe a missing crate `unresolved`?
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-18083.rs b/src/test/ui/issues/issue-18083.rs
deleted file mode 100644 (file)
index 36420ec..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// check-pass
-#![allow(dead_code)]
-#![allow(unused_imports)]
-// These crossed imports should resolve fine, and not block on
-// each other and be reported as unresolved.
-
-mod a {
-    use b::{B};
-    pub use self::inner::A;
-
-    mod inner {
-        pub struct A;
-    }
-}
-
-mod b {
-    use a::{A};
-    pub use self::inner::B;
-
-    mod inner {
-        pub struct B;
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-19498.rs b/src/test/ui/issues/issue-19498.rs
deleted file mode 100644 (file)
index 5fe6742..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-use self::A;
-use self::B;
-mod A {} //~ ERROR the name `A` is defined multiple times
-//~| `A` redefined here
-pub mod B {} //~ ERROR the name `B` is defined multiple times
-//~| `B` redefined here
-mod C {
-    use C::D;
-    mod D {} //~ ERROR the name `D` is defined multiple times
-    //~| `D` redefined here
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-19498.stderr b/src/test/ui/issues/issue-19498.stderr
deleted file mode 100644 (file)
index cc1d649..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-error[E0255]: the name `A` is defined multiple times
-  --> $DIR/issue-19498.rs:3:1
-   |
-LL | use self::A;
-   |     ------- previous import of the module `A` here
-LL | use self::B;
-LL | mod A {}
-   | ^^^^^ `A` redefined here
-   |
-   = note: `A` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use self::A as OtherA;
-   |     ^^^^^^^^^^^^^^^^^
-
-error[E0255]: the name `B` is defined multiple times
-  --> $DIR/issue-19498.rs:5:1
-   |
-LL | use self::B;
-   |     ------- previous import of the module `B` here
-...
-LL | pub mod B {}
-   | ^^^^^^^^^ `B` redefined here
-   |
-   = note: `B` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use self::B as OtherB;
-   |     ^^^^^^^^^^^^^^^^^
-
-error[E0255]: the name `D` is defined multiple times
-  --> $DIR/issue-19498.rs:9:5
-   |
-LL |     use C::D;
-   |         ---- previous import of the module `D` here
-LL |     mod D {}
-   |     ^^^^^ `D` redefined here
-   |
-   = note: `D` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL |     use C::D as OtherD;
-   |         ^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0255`.
index 780038c11b8089aa2d9ad95e3b66ad5290bd8eea..b2371051c78f94eeaa31e69e21e30532c4e88840 100644 (file)
@@ -11,7 +11,7 @@
 
 
 type Type_3<T> = Box<T,,>;
-//~^ error: expected one of `>`, const, lifetime, or type, found `,`
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
 
 
 //type Type_4<T> = Type_1_<'static,, T>; // error: expected type, found `,`
index 2f8cf8a79ed9439544dcdf9ac33092d6ffc311d1..b535c7a3267d3bc000290dbcb32a47444f24f8a1 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, lifetime, or type, found `,`
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
   --> $DIR/issue-20616-3.rs:13:24
    |
 LL | type Type_3<T> = Box<T,,>;
-   |                        ^ expected one of `>`, const, lifetime, or type
+   |                        ^ expected one of `>`, a const expression, lifetime, or type
 
 error: aborting due to previous error
 
index 85aa9c1146d67982dbd11011eb3855493f494970..a71f47ca4bf933ce081ac6d214d203190ea2cea2 100644 (file)
@@ -14,7 +14,7 @@
 
 
 type Type_4<T> = Type_1_<'static,, T>;
-//~^ error: expected one of `>`, const, lifetime, or type, found `,`
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
 
 
 type Type_5_<'a> = Type_1_<'a, ()>;
index 3be6c2e78ced00995ffe0688224ea46312811da2..2b3b75f3119e3c42edff9015439cb4c886fdf4ac 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, lifetime, or type, found `,`
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
   --> $DIR/issue-20616-4.rs:16:34
    |
 LL | type Type_4<T> = Type_1_<'static,, T>;
-   |                                  ^ expected one of `>`, const, lifetime, or type
+   |                                  ^ expected one of `>`, a const expression, lifetime, or type
 
 error: aborting due to previous error
 
index c0c6bc6dd97fee24d90de55e7fb7cf1970628653..b96d09d59ae69c072fc6bcc6187812a82e149f79 100644 (file)
@@ -20,7 +20,7 @@
 
 
 type Type_5<'a> = Type_1_<'a, (),,>;
-//~^ error: expected one of `>`, const, lifetime, or type, found `,`
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
 
 
 //type Type_6 = Type_5_<'a,,>; // error: expected type, found `,`
index b90fbf60051476412dc84c36e55655a8e9ab7066..1ec1dbde69528e9e1cf48969331f8adc33bd36ab 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, lifetime, or type, found `,`
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
   --> $DIR/issue-20616-5.rs:22:34
    |
 LL | type Type_5<'a> = Type_1_<'a, (),,>;
-   |                                  ^ expected one of `>`, const, lifetime, or type
+   |                                  ^ expected one of `>`, a const expression, lifetime, or type
 
 error: aborting due to previous error
 
index 73c75bdc45fb1dc72f59e2e89acab98345b4a8a6..a2c45ecec7a4b21d6c7b8698bda4357713b64596 100644 (file)
@@ -23,7 +23,7 @@
 
 
 type Type_6 = Type_5_<'a,,>;
-//~^ error: expected one of `>`, const, lifetime, or type, found `,`
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
 
 
 //type Type_7 = Box<(),,>; // error: expected type, found `,`
index ea1c15ba4233773e7216ecc02fee562f7162ebff..7401abdd091e6e1e2de6c2a3d7bf2489cb1fb324 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, lifetime, or type, found `,`
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
   --> $DIR/issue-20616-6.rs:25:26
    |
 LL | type Type_6 = Type_5_<'a,,>;
-   |                          ^ expected one of `>`, const, lifetime, or type
+   |                          ^ expected one of `>`, a const expression, lifetime, or type
 
 error: aborting due to previous error
 
index 8beeebd7a9550f63341b519b78106a479066c9a4..67209c02adffbf8603a0eefcba5b8cffe00df33c 100644 (file)
@@ -26,7 +26,7 @@
 
 
 type Type_7 = Box<(),,>;
-//~^ error: expected one of `>`, const, lifetime, or type, found `,`
+//~^ error: expected one of `>`, a const expression, lifetime, or type, found `,`
 
 
 //type Type_8<'a,,> = &'a (); // error: expected ident, found `,`
index dcd199902fc0b5643710ad34e0a745c849298170..e2c3efe8447013e43f736ce60fcac6508744a51b 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, lifetime, or type, found `,`
+error: expected one of `>`, a const expression, lifetime, or type, found `,`
   --> $DIR/issue-20616-7.rs:28:22
    |
 LL | type Type_7 = Box<(),,>;
-   |                      ^ expected one of `>`, const, lifetime, or type
+   |                      ^ expected one of `>`, a const expression, lifetime, or type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-24081.rs b/src/test/ui/issues/issue-24081.rs
deleted file mode 100644 (file)
index 10983ce..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-use std::ops::Add;
-use std::ops::Sub;
-use std::ops::Mul;
-use std::ops::Div;
-use std::ops::Rem;
-
-type Add = bool; //~ ERROR the name `Add` is defined multiple times
-//~| `Add` redefined here
-struct Sub { x: f32 } //~ ERROR the name `Sub` is defined multiple times
-//~| `Sub` redefined here
-enum Mul { A, B } //~ ERROR the name `Mul` is defined multiple times
-//~| `Mul` redefined here
-mod Div { } //~ ERROR the name `Div` is defined multiple times
-//~| `Div` redefined here
-trait Rem {  } //~ ERROR the name `Rem` is defined multiple times
-//~| `Rem` redefined here
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-24081.stderr b/src/test/ui/issues/issue-24081.stderr
deleted file mode 100644 (file)
index 647048c..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-error[E0255]: the name `Add` is defined multiple times
-  --> $DIR/issue-24081.rs:7:1
-   |
-LL | use std::ops::Add;
-   |     ------------- previous import of the trait `Add` here
-...
-LL | type Add = bool;
-   | ^^^^^^^^^^^^^^^^ `Add` redefined here
-   |
-   = note: `Add` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use std::ops::Add as OtherAdd;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0255]: the name `Sub` is defined multiple times
-  --> $DIR/issue-24081.rs:9:1
-   |
-LL | use std::ops::Sub;
-   |     ------------- previous import of the trait `Sub` here
-...
-LL | struct Sub { x: f32 }
-   | ^^^^^^^^^^ `Sub` redefined here
-   |
-   = note: `Sub` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use std::ops::Sub as OtherSub;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0255]: the name `Mul` is defined multiple times
-  --> $DIR/issue-24081.rs:11:1
-   |
-LL | use std::ops::Mul;
-   |     ------------- previous import of the trait `Mul` here
-...
-LL | enum Mul { A, B }
-   | ^^^^^^^^ `Mul` redefined here
-   |
-   = note: `Mul` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use std::ops::Mul as OtherMul;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0255]: the name `Div` is defined multiple times
-  --> $DIR/issue-24081.rs:13:1
-   |
-LL | use std::ops::Div;
-   |     ------------- previous import of the trait `Div` here
-...
-LL | mod Div { }
-   | ^^^^^^^ `Div` redefined here
-   |
-   = note: `Div` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use std::ops::Div as OtherDiv;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0255]: the name `Rem` is defined multiple times
-  --> $DIR/issue-24081.rs:15:1
-   |
-LL | use std::ops::Rem;
-   |     ------------- previous import of the trait `Rem` here
-...
-LL | trait Rem {  }
-   | ^^^^^^^^^ `Rem` redefined here
-   |
-   = note: `Rem` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use std::ops::Rem as OtherRem;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 5 previous errors
-
-For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/issues/issue-25396.rs b/src/test/ui/issues/issue-25396.rs
deleted file mode 100644 (file)
index 301658d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#![allow(non_camel_case_types)]
-
-use foo::baz;
-use bar::baz; //~ ERROR the name `baz` is defined multiple times
-
-use foo::Quux;
-use bar::Quux; //~ ERROR the name `Quux` is defined multiple times
-
-use foo::blah;
-use bar::blah; //~ ERROR the name `blah` is defined multiple times
-
-use foo::WOMP;
-use bar::WOMP; //~ ERROR the name `WOMP` is defined multiple times
-
-fn main() {}
-
-mod foo {
-    pub mod baz {}
-    pub trait Quux { }
-    pub type blah = (f64, u32);
-    pub const WOMP: u8 = 5;
-}
-
-mod bar {
-    pub mod baz {}
-    pub type Quux = i32;
-    pub struct blah { x: i8 }
-    pub const WOMP: i8 = -5;
-}
diff --git a/src/test/ui/issues/issue-25396.stderr b/src/test/ui/issues/issue-25396.stderr
deleted file mode 100644 (file)
index 38dc9ef..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-error[E0252]: the name `baz` is defined multiple times
-  --> $DIR/issue-25396.rs:4:5
-   |
-LL | use foo::baz;
-   |     -------- previous import of the module `baz` here
-LL | use bar::baz;
-   |     ^^^^^^^^ `baz` reimported here
-   |
-   = note: `baz` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use bar::baz as other_baz;
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
-error[E0252]: the name `Quux` is defined multiple times
-  --> $DIR/issue-25396.rs:7:5
-   |
-LL | use foo::Quux;
-   |     --------- previous import of the trait `Quux` here
-LL | use bar::Quux;
-   |     ^^^^^^^^^ `Quux` reimported here
-   |
-   = note: `Quux` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use bar::Quux as OtherQuux;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0252]: the name `blah` is defined multiple times
-  --> $DIR/issue-25396.rs:10:5
-   |
-LL | use foo::blah;
-   |     --------- previous import of the type `blah` here
-LL | use bar::blah;
-   |     ^^^^^^^^^ `blah` reimported here
-   |
-   = note: `blah` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use bar::blah as other_blah;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0252]: the name `WOMP` is defined multiple times
-  --> $DIR/issue-25396.rs:13:5
-   |
-LL | use foo::WOMP;
-   |     --------- previous import of the value `WOMP` here
-LL | use bar::WOMP;
-   |     ^^^^^^^^^ `WOMP` reimported here
-   |
-   = note: `WOMP` must be defined only once in the value namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use bar::WOMP as OtherWOMP;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-26886.rs b/src/test/ui/issues/issue-26886.rs
deleted file mode 100644 (file)
index 6e6d406..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-use std::sync::{self, Arc};
-use std::sync::Arc; //~ ERROR the name `Arc` is defined multiple times
-                    //~| `Arc` must be defined only once in the type namespace of this module
-use std::sync; //~ ERROR the name `sync` is defined multiple times
-               //~| `sync` must be defined only once in the type namespace of this module
-
-fn main() {
-}
diff --git a/src/test/ui/issues/issue-26886.stderr b/src/test/ui/issues/issue-26886.stderr
deleted file mode 100644 (file)
index e2b925e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0252]: the name `Arc` is defined multiple times
-  --> $DIR/issue-26886.rs:2:5
-   |
-LL | use std::sync::{self, Arc};
-   |                       --- previous import of the type `Arc` here
-LL | use std::sync::Arc;
-   |     ^^^^^^^^^^^^^^ `Arc` reimported here
-   |
-   = note: `Arc` must be defined only once in the type namespace of this module
-
-error[E0252]: the name `sync` is defined multiple times
-  --> $DIR/issue-26886.rs:4:5
-   |
-LL | use std::sync::{self, Arc};
-   |                 ---- previous import of the module `sync` here
-...
-LL | use std::sync;
-   |     ^^^^^^^^^ `sync` reimported here
-   |
-   = note: `sync` must be defined only once in the type namespace of this module
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-28075.rs b/src/test/ui/issues/issue-28075.rs
deleted file mode 100644 (file)
index 6b4ea46..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Unstable entities should be caught in import lists
-
-// aux-build:lint-stability.rs
-
-#![allow(warnings)]
-
-extern crate lint_stability;
-
-use lint_stability::{unstable, deprecated};
-//~^ ERROR use of unstable library feature 'unstable_test_feature'
-
-fn main() {
-}
diff --git a/src/test/ui/issues/issue-28075.stderr b/src/test/ui/issues/issue-28075.stderr
deleted file mode 100644 (file)
index 7e53bb5..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
-  --> $DIR/issue-28075.rs:9:22
-   |
-LL | use lint_stability::{unstable, deprecated};
-   |                      ^^^^^^^^
-   |
-   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-28134.rs b/src/test/ui/issues/issue-28134.rs
deleted file mode 100644 (file)
index 1ed2d33..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-// compile-flags: --test
-
-#![allow(soft_unstable)]
-#![test] //~ ERROR cannot determine resolution for the attribute macro `test`
diff --git a/src/test/ui/issues/issue-28134.stderr b/src/test/ui/issues/issue-28134.stderr
deleted file mode 100644 (file)
index 8ed4d01..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: cannot determine resolution for the attribute macro `test`
-  --> $DIR/issue-28134.rs:4:4
-   |
-LL | #![test]
-   |    ^^^^
-   |
-   = note: import resolution is stuck, try simplifying macro imports
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-28388-1.rs b/src/test/ui/issues/issue-28388-1.rs
deleted file mode 100644 (file)
index 14de621..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
-
-use foo::{}; //~ ERROR unresolved import `foo`
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-28388-1.stderr b/src/test/ui/issues/issue-28388-1.stderr
deleted file mode 100644 (file)
index 7f5e47a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `foo`
-  --> $DIR/issue-28388-1.rs:3:5
-   |
-LL | use foo::{};
-   |     ^^^^^^^ no `foo` in the root
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-28388-2.rs b/src/test/ui/issues/issue-28388-2.rs
deleted file mode 100644 (file)
index 024b038..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
-
-mod m {
-    mod n {}
-}
-
-use m::n::{};
-//~^ ERROR module `n` is private
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-28388-2.stderr b/src/test/ui/issues/issue-28388-2.stderr
deleted file mode 100644 (file)
index 1afaf62..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0603]: module `n` is private
-  --> $DIR/issue-28388-2.rs:7:8
-   |
-LL | use m::n::{};
-   |        ^ private module
-   |
-note: the module `n` is defined here
-  --> $DIR/issue-28388-2.rs:4:5
-   |
-LL |     mod n {}
-   |     ^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0603`.
diff --git a/src/test/ui/issues/issue-28388-3.rs b/src/test/ui/issues/issue-28388-3.rs
deleted file mode 100644 (file)
index 7ba9935..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
-
-// aux-build:lint-stability.rs
-
-extern crate lint_stability;
-
-use lint_stability::UnstableEnum::{};
-//~^ ERROR use of unstable library feature 'unstable_test_feature'
-use lint_stability::StableEnum::{}; // OK
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-28388-3.stderr b/src/test/ui/issues/issue-28388-3.stderr
deleted file mode 100644 (file)
index d2e4668..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-error[E0658]: use of unstable library feature 'unstable_test_feature'
-  --> $DIR/issue-28388-3.rs:7:5
-   |
-LL | use lint_stability::UnstableEnum::{};
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/issues/issue-2937.rs b/src/test/ui/issues/issue-2937.rs
deleted file mode 100644 (file)
index 335df5c..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-use m::f as x; //~ ERROR unresolved import `m::f` [E0432]
-               //~^ no `f` in `m`
-
-mod m {}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-2937.stderr b/src/test/ui/issues/issue-2937.stderr
deleted file mode 100644 (file)
index 4286348..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `m::f`
-  --> $DIR/issue-2937.rs:1:5
-   |
-LL | use m::f as x;
-   |     ^^^^^^^^^ no `f` in `m`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-30560.rs b/src/test/ui/issues/issue-30560.rs
deleted file mode 100644 (file)
index d8d4ca6..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-type Alias = ();
-use Alias::*; //~ ERROR unresolved import `Alias` [E0432]
-
-use std::io::Result::*; //~ ERROR unresolved import `std::io::Result` [E0432]
-
-trait T {}
-use T::*; //~ ERROR items in traits are not importable
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-30560.stderr b/src/test/ui/issues/issue-30560.stderr
deleted file mode 100644 (file)
index b74134a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error: items in traits are not importable.
-  --> $DIR/issue-30560.rs:7:5
-   |
-LL | use T::*;
-   |     ^^^^
-
-error[E0432]: unresolved import `Alias`
-  --> $DIR/issue-30560.rs:2:5
-   |
-LL | use Alias::*;
-   |     ^^^^^ `Alias` is a type alias, not a module
-
-error[E0432]: unresolved import `std::io::Result`
-  --> $DIR/issue-30560.rs:4:14
-   |
-LL | use std::io::Result::*;
-   |              ^^^^^^ `Result` is a type alias, not a module
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-30730.rs b/src/test/ui/issues/issue-30730.rs
deleted file mode 100644 (file)
index d6be90c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-#![warn(unused)]
-#![deny(warnings)]
-use std::thread;
-//~^ ERROR: unused import
-fn main() {}
diff --git a/src/test/ui/issues/issue-30730.stderr b/src/test/ui/issues/issue-30730.stderr
deleted file mode 100644 (file)
index b299e99..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: unused import: `std::thread`
-  --> $DIR/issue-30730.rs:3:5
-   |
-LL | use std::thread;
-   |     ^^^^^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-30730.rs:2:9
-   |
-LL | #![deny(warnings)]
-   |         ^^^^^^^^
-   = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-31212.rs b/src/test/ui/issues/issue-31212.rs
deleted file mode 100644 (file)
index 556f0d1..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// This checks that a path that cannot be resolved because of an indeterminate import
-// does not trigger an ICE.
-
-mod foo {
-    pub use self::*; //~ ERROR unresolved
-}
-
-fn main() {
-    foo::f(); //~ ERROR cannot find function `f` in module `foo`
-}
diff --git a/src/test/ui/issues/issue-31212.stderr b/src/test/ui/issues/issue-31212.stderr
deleted file mode 100644 (file)
index 0bb56b3..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0432]: unresolved import `self::*`
-  --> $DIR/issue-31212.rs:5:13
-   |
-LL |     pub use self::*;
-   |             ^^^^^^^ cannot glob-import a module into itself
-
-error[E0425]: cannot find function `f` in module `foo`
-  --> $DIR/issue-31212.rs:9:10
-   |
-LL |     foo::f();
-   |          ^ not found in `foo`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0425, E0432.
-For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-32354-suggest-import-rename.fixed b/src/test/ui/issues/issue-32354-suggest-import-rename.fixed
deleted file mode 100644 (file)
index 27f1b89..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-rustfix
-
-#![allow(unused_imports)]
-
-pub mod extension1 {
-    pub trait ConstructorExtension {}
-}
-
-pub mod extension2 {
-    pub trait ConstructorExtension {}
-}
-
-use extension1::ConstructorExtension;
-use extension2::ConstructorExtension as OtherConstructorExtension; //~ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-32354-suggest-import-rename.rs b/src/test/ui/issues/issue-32354-suggest-import-rename.rs
deleted file mode 100644 (file)
index 5a7f234..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// run-rustfix
-
-#![allow(unused_imports)]
-
-pub mod extension1 {
-    pub trait ConstructorExtension {}
-}
-
-pub mod extension2 {
-    pub trait ConstructorExtension {}
-}
-
-use extension1::ConstructorExtension;
-use extension2::ConstructorExtension; //~ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-32354-suggest-import-rename.stderr b/src/test/ui/issues/issue-32354-suggest-import-rename.stderr
deleted file mode 100644 (file)
index 9668430..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0252]: the name `ConstructorExtension` is defined multiple times
-  --> $DIR/issue-32354-suggest-import-rename.rs:14:5
-   |
-LL | use extension1::ConstructorExtension;
-   |     -------------------------------- previous import of the trait `ConstructorExtension` here
-LL | use extension2::ConstructorExtension;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ConstructorExtension` reimported here
-   |
-   = note: `ConstructorExtension` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use extension2::ConstructorExtension as OtherConstructorExtension;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-32833.rs b/src/test/ui/issues/issue-32833.rs
deleted file mode 100644 (file)
index 379eedd..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-use bar::Foo; //~ ERROR unresolved import `bar::Foo` [E0432]
-              //~^ no `Foo` in `bar`
-mod bar {
-    use Foo;
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-32833.stderr b/src/test/ui/issues/issue-32833.stderr
deleted file mode 100644 (file)
index 430cc0f..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `bar::Foo`
-  --> $DIR/issue-32833.rs:1:5
-   |
-LL | use bar::Foo;
-   |     ^^^^^^^^ no `Foo` in `bar`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-33464.rs b/src/test/ui/issues/issue-33464.rs
deleted file mode 100644 (file)
index a0edb5f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// Make sure that the spans of import errors are correct.
-
-use abc::one_el;
-//~^ ERROR
-use abc::{a, bbb, cccccc};
-//~^ ERROR
-use a_very_long_name::{el, el2};
-//~^ ERROR
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-33464.stderr b/src/test/ui/issues/issue-33464.stderr
deleted file mode 100644 (file)
index d3bf404..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0432]: unresolved import `abc`
-  --> $DIR/issue-33464.rs:3:5
-   |
-LL | use abc::one_el;
-   |     ^^^ maybe a missing crate `abc`?
-
-error[E0432]: unresolved import `abc`
-  --> $DIR/issue-33464.rs:5:5
-   |
-LL | use abc::{a, bbb, cccccc};
-   |     ^^^ maybe a missing crate `abc`?
-
-error[E0432]: unresolved import `a_very_long_name`
-  --> $DIR/issue-33464.rs:7:5
-   |
-LL | use a_very_long_name::{el, el2};
-   |     ^^^^^^^^^^^^^^^^ maybe a missing crate `a_very_long_name`?
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-36617.rs b/src/test/ui/issues/issue-36617.rs
deleted file mode 100644 (file)
index 1102f3c..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#![derive(Copy)] //~ ERROR `derive` may only be applied to structs, enums and unions
-                 //~| ERROR cannot determine resolution for the derive macro `Copy`
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-36617.stderr b/src/test/ui/issues/issue-36617.stderr
deleted file mode 100644 (file)
index dc6ef16..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0774]: `derive` may only be applied to structs, enums and unions
-  --> $DIR/issue-36617.rs:1:1
-   |
-LL | #![derive(Copy)]
-   | ^^^^^^^^^^^^^^^^ help: try an outer attribute: `#[derive(Copy)]`
-
-error: cannot determine resolution for the derive macro `Copy`
-  --> $DIR/issue-36617.rs:1:11
-   |
-LL | #![derive(Copy)]
-   |           ^^^^
-   |
-   = note: import resolution is stuck, try simplifying macro imports
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0774`.
diff --git a/src/test/ui/issues/issue-36881.rs b/src/test/ui/issues/issue-36881.rs
deleted file mode 100644 (file)
index 0431387..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// aux-build:issue-36881-aux.rs
-
-fn main() {
-    extern crate issue_36881_aux;
-    use issue_36881_aux::Foo; //~ ERROR unresolved import
-}
diff --git a/src/test/ui/issues/issue-36881.stderr b/src/test/ui/issues/issue-36881.stderr
deleted file mode 100644 (file)
index caf9d5d..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0432]: unresolved import `issue_36881_aux`
-  --> $DIR/issue-36881.rs:5:9
-   |
-LL |     use issue_36881_aux::Foo;
-   |         ^^^^^^^^^^^^^^^ maybe a missing crate `issue_36881_aux`?
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-37887.rs b/src/test/ui/issues/issue-37887.rs
deleted file mode 100644 (file)
index 58f0c6b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-fn main() {
-    extern crate libc; //~ ERROR use of unstable
-    use libc::*; //~ ERROR unresolved import
-}
diff --git a/src/test/ui/issues/issue-37887.stderr b/src/test/ui/issues/issue-37887.stderr
deleted file mode 100644 (file)
index 944d544..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0432]: unresolved import `libc`
-  --> $DIR/issue-37887.rs:3:9
-   |
-LL |     use libc::*;
-   |         ^^^^ maybe a missing crate `libc`?
-
-error[E0658]: use of unstable library feature 'rustc_private': this crate is being loaded from the sysroot, an unstable location; did you mean to load this crate from crates.io via `Cargo.toml` instead?
-  --> $DIR/issue-37887.rs:2:5
-   |
-LL |     extern crate libc;
-   |     ^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #27812 <https://github.com/rust-lang/rust/issues/27812> for more information
-   = help: add `#![feature(rustc_private)]` to the crate attributes to enable
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0432, E0658.
-For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-38293.rs b/src/test/ui/issues/issue-38293.rs
deleted file mode 100644 (file)
index 3b13936..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Test that `fn foo::bar::{self}` only imports `bar` in the type namespace.
-
-mod foo {
-    pub fn f() { }
-}
-use foo::f::{self}; //~ ERROR unresolved import `foo::f`
-
-mod bar {
-    pub fn baz() {}
-    pub mod baz {}
-}
-use bar::baz::{self};
-
-fn main() {
-    baz(); //~ ERROR expected function, found module `baz`
-}
diff --git a/src/test/ui/issues/issue-38293.stderr b/src/test/ui/issues/issue-38293.stderr
deleted file mode 100644 (file)
index d2450ab..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0432]: unresolved import `foo::f`
-  --> $DIR/issue-38293.rs:6:14
-   |
-LL | use foo::f::{self};
-   |              ^^^^ no `f` in `foo`
-
-error[E0423]: expected function, found module `baz`
-  --> $DIR/issue-38293.rs:15:5
-   |
-LL |     baz();
-   |     ^^^ not a function
-   |
-help: consider importing this function instead
-   |
-LL | use bar::baz;
-   |
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0423, E0432.
-For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/issues/issue-4366-2.rs b/src/test/ui/issues/issue-4366-2.rs
deleted file mode 100644 (file)
index c777b75..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// ensures that 'use foo:*' doesn't import non-public item
-
-use m1::*;
-
-mod foo {
-    pub fn foo() {}
-}
-mod a {
-    pub mod b {
-        use foo::foo;
-        type Bar = isize;
-    }
-    pub mod sub {
-        use a::b::*;
-        fn sub() -> Bar { 1 }
-        //~^ ERROR cannot find type `Bar` in this scope
-    }
-}
-
-mod m1 {
-    fn foo() {}
-}
-
-fn main() {
-    foo(); //~ ERROR expected function, found module `foo`
-}
diff --git a/src/test/ui/issues/issue-4366-2.stderr b/src/test/ui/issues/issue-4366-2.stderr
deleted file mode 100644 (file)
index a86ec7f..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-error[E0412]: cannot find type `Bar` in this scope
-  --> $DIR/issue-4366-2.rs:15:21
-   |
-LL |         fn sub() -> Bar { 1 }
-   |                     ^^^ not found in this scope
-   |
-help: consider importing this type alias
-   |
-LL |         use a::b::Bar;
-   |
-
-error[E0423]: expected function, found module `foo`
-  --> $DIR/issue-4366-2.rs:25:5
-   |
-LL |     foo();
-   |     ^^^ not a function
-   |
-help: consider importing this function instead
-   |
-LL | use foo::foo;
-   |
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0412, E0423.
-For more information about an error, try `rustc --explain E0412`.
diff --git a/src/test/ui/issues/issue-4366.rs b/src/test/ui/issues/issue-4366.rs
deleted file mode 100644 (file)
index 9ec2e58..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// regression test for issue 4366
-
-// ensures that 'use foo:*' doesn't import non-public 'use' statements in the
-// module 'foo'
-
-use m1::*;
-
-mod foo {
-    pub fn foo() {}
-}
-mod a {
-    pub mod b {
-        use foo::foo;
-        type Bar = isize;
-    }
-    pub mod sub {
-        use a::b::*;
-        fn sub() -> isize { foo(); 1 } //~ ERROR cannot find function `foo` in this scope
-    }
-}
-
-mod m1 {
-    fn foo() {}
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-4366.stderr b/src/test/ui/issues/issue-4366.stderr
deleted file mode 100644 (file)
index 469ea93..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0425]: cannot find function `foo` in this scope
-  --> $DIR/issue-4366.rs:18:29
-   |
-LL |         fn sub() -> isize { foo(); 1 }
-   |                             ^^^ not found in this scope
-   |
-help: consider importing this function
-   |
-LL |         use foo::foo;
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.fixed
deleted file mode 100644 (file)
index b463848..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// run-rustfix
-
-extern crate std as other_std;
-fn main() {}
-//~^^ ERROR the name `std` is defined multiple times [E0259]
diff --git a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs
deleted file mode 100644 (file)
index 1b491ac..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// run-rustfix
-
-extern crate std;
-fn main() {}
-//~^^ ERROR the name `std` is defined multiple times [E0259]
diff --git a/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr b/src/test/ui/issues/issue-45799-bad-extern-crate-rename-suggestion-formatting.stderr
deleted file mode 100644 (file)
index 25aca4c..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error[E0259]: the name `std` is defined multiple times
-  --> $DIR/issue-45799-bad-extern-crate-rename-suggestion-formatting.rs:3:1
-   |
-LL | extern crate std;
-   | ^^^^^^^^^^^^^^^^^ `std` reimported here
-   |
-   = note: `std` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | extern crate std as other_std;
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/issues/issue-45829/auxiliary/issue-45829-a.rs b/src/test/ui/issues/issue-45829/auxiliary/issue-45829-a.rs
deleted file mode 100644 (file)
index e9f7fef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-pub const FOO: usize = *&0;
diff --git a/src/test/ui/issues/issue-45829/auxiliary/issue-45829-b.rs b/src/test/ui/issues/issue-45829/auxiliary/issue-45829-b.rs
deleted file mode 100644 (file)
index e9f7fef..0000000
+++ /dev/null
@@ -1 +0,0 @@
-pub const FOO: usize = *&0;
diff --git a/src/test/ui/issues/issue-45829/import-self.rs b/src/test/ui/issues/issue-45829/import-self.rs
deleted file mode 100644 (file)
index 2dc4331..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-mod foo {
-    pub struct A;
-    pub struct B;
-}
-
-use foo::{self};
-//~^ ERROR is defined multiple times
-
-use foo as self;
-//~^ ERROR expected identifier
-
-use foo::self; //~ ERROR is defined multiple times
-//~^ ERROR `self` imports are only allowed within a { } list
-
-use foo::A;
-use foo::{self as A};
-//~^ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-45829/import-self.stderr b/src/test/ui/issues/issue-45829/import-self.stderr
deleted file mode 100644 (file)
index 158e81c..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-error: expected identifier, found keyword `self`
-  --> $DIR/import-self.rs:9:12
-   |
-LL | use foo as self;
-   |            ^^^^ expected identifier, found keyword
-
-error[E0429]: `self` imports are only allowed within a { } list
-  --> $DIR/import-self.rs:12:8
-   |
-LL | use foo::self;
-   |        ^^^^^^
-   |
-help: consider importing the module directly
-   |
-LL | use foo;
-   |       --
-help: alternatively, use the multi-path `use` syntax to import `self`
-   |
-LL | use foo::{self};
-   |          ^    ^
-
-error[E0255]: the name `foo` is defined multiple times
-  --> $DIR/import-self.rs:6:11
-   |
-LL | mod foo {
-   | ------- previous definition of the module `foo` here
-...
-LL | use foo::{self};
-   |           ^^^^ `foo` reimported here
-   |
-   = note: `foo` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use foo::{self as other_foo};
-   |           ^^^^^^^^^^^^^^^^^
-
-error[E0255]: the name `foo` is defined multiple times
-  --> $DIR/import-self.rs:12:5
-   |
-LL | mod foo {
-   | ------- previous definition of the module `foo` here
-...
-LL | use foo::self;
-   |     ^^^^^^^^^ `foo` reimported here
-   |
-   = note: `foo` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use foo as other_foo;
-   |     ^^^^^^^^^^^^^^^^
-
-error[E0252]: the name `A` is defined multiple times
-  --> $DIR/import-self.rs:16:11
-   |
-LL | use foo::A;
-   |     ------ previous import of the type `A` here
-LL | use foo::{self as A};
-   |           ^^^^^^^^^ `A` reimported here
-   |
-   = note: `A` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use foo::{self as OtherA};
-   |           ^^^^^^^^^^^^^^
-
-error: aborting due to 5 previous errors
-
-Some errors have detailed explanations: E0252, E0255, E0429.
-For more information about an error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/import-twice.rs b/src/test/ui/issues/issue-45829/import-twice.rs
deleted file mode 100644 (file)
index e5a8bb7..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-mod foo {
-    pub struct A;
-    pub struct B;
-}
-
-use foo::{A, A};
-//~^ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-45829/import-twice.stderr b/src/test/ui/issues/issue-45829/import-twice.stderr
deleted file mode 100644 (file)
index 656b011..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-error[E0252]: the name `A` is defined multiple times
-  --> $DIR/import-twice.rs:6:14
-   |
-LL | use foo::{A, A};
-   |           -  ^ `A` reimported here
-   |           |
-   |           previous import of the type `A` here
-   |
-   = note: `A` must be defined only once in the type namespace of this module
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/issue-45829.rs b/src/test/ui/issues/issue-45829/issue-45829.rs
deleted file mode 100644 (file)
index 1e76e4b..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-mod foo {
-    pub struct A;
-    pub struct B;
-}
-
-use foo::{A, B as A};
-//~^ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-45829/issue-45829.stderr b/src/test/ui/issues/issue-45829/issue-45829.stderr
deleted file mode 100644 (file)
index a7ebc71..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0252]: the name `A` is defined multiple times
-  --> $DIR/issue-45829.rs:6:14
-   |
-LL | use foo::{A, B as A};
-   |           -  ^^^^^^ `A` reimported here
-   |           |
-   |           previous import of the type `A` here
-   |
-   = note: `A` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use foo::{A, B as OtherA};
-   |              ^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/rename-extern-vs-use.rs b/src/test/ui/issues/issue-45829/rename-extern-vs-use.rs
deleted file mode 100644 (file)
index aef7aa3..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// aux-build:issue-45829-b.rs
-
-mod foo {
-    pub mod bar {}
-}
-
-use foo::bar;
-extern crate issue_45829_b as bar;
-//~^ ERROR the name `bar` is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-extern-vs-use.stderr b/src/test/ui/issues/issue-45829/rename-extern-vs-use.stderr
deleted file mode 100644 (file)
index 98fd8a6..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0254]: the name `bar` is defined multiple times
-  --> $DIR/rename-extern-vs-use.rs:8:1
-   |
-LL | use foo::bar;
-   |     -------- previous import of the module `bar` here
-LL | extern crate issue_45829_b as bar;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `bar` reimported here
-   |
-   = note: `bar` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | extern crate issue_45829_b as other_bar;
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0254`.
diff --git a/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs b/src/test/ui/issues/issue-45829/rename-extern-with-tab.rs
deleted file mode 100644 (file)
index 0da8b82..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// aux-build:issue-45829-a.rs
-// aux-build:issue-45829-b.rs
-
-extern crate issue_45829_a;
-extern  crate    issue_45829_b  as  issue_45829_a;
-//~^ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr b/src/test/ui/issues/issue-45829/rename-extern-with-tab.stderr
deleted file mode 100644 (file)
index 2c4e8ce..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0259]: the name `issue_45829_a` is defined multiple times
-  --> $DIR/rename-extern-with-tab.rs:5:1
-   |
-LL | extern crate issue_45829_a;
-   | --------------------------- previous import of the extern crate `issue_45829_a` here
-LL | extern  crate    issue_45829_b  as  issue_45829_a;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here
-   |
-   = note: `issue_45829_a` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | extern crate issue_45829_b as other_issue_45829_a;
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/issues/issue-45829/rename-extern.rs b/src/test/ui/issues/issue-45829/rename-extern.rs
deleted file mode 100644 (file)
index 7dbda69..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-// aux-build:issue-45829-a.rs
-// aux-build:issue-45829-b.rs
-
-extern crate issue_45829_a;
-extern crate issue_45829_b as issue_45829_a;
-//~^ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-extern.stderr b/src/test/ui/issues/issue-45829/rename-extern.stderr
deleted file mode 100644 (file)
index 209ae22..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0259]: the name `issue_45829_a` is defined multiple times
-  --> $DIR/rename-extern.rs:5:1
-   |
-LL | extern crate issue_45829_a;
-   | --------------------------- previous import of the extern crate `issue_45829_a` here
-LL | extern crate issue_45829_b as issue_45829_a;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `issue_45829_a` reimported here
-   |
-   = note: `issue_45829_a` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | extern crate issue_45829_b as other_issue_45829_a;
-   |
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0259`.
diff --git a/src/test/ui/issues/issue-45829/rename-use-vs-extern.rs b/src/test/ui/issues/issue-45829/rename-use-vs-extern.rs
deleted file mode 100644 (file)
index 0cf3a77..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-// aux-build:issue-45829-b.rs
-
-extern crate issue_45829_b;
-use std as issue_45829_b;
-//~^ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-use-vs-extern.stderr b/src/test/ui/issues/issue-45829/rename-use-vs-extern.stderr
deleted file mode 100644 (file)
index 6b917d5..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0254]: the name `issue_45829_b` is defined multiple times
-  --> $DIR/rename-use-vs-extern.rs:4:5
-   |
-LL | extern crate issue_45829_b;
-   | --------------------------- previous import of the extern crate `issue_45829_b` here
-LL | use std as issue_45829_b;
-   |     ^^^^^^^^^^^^^^^^^^^^ `issue_45829_b` reimported here
-   |
-   = note: `issue_45829_b` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use std as other_issue_45829_b;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0254`.
diff --git a/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs b/src/test/ui/issues/issue-45829/rename-use-with-tabs.rs
deleted file mode 100644 (file)
index 86c5fa0..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-mod foo {
-    pub struct A;
-
-    pub mod bar {
-        pub struct B;
-    }
-}
-
-use foo::{A, bar::B    as    A};
-//~^ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr b/src/test/ui/issues/issue-45829/rename-use-with-tabs.stderr
deleted file mode 100644 (file)
index 3baad6c..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0252]: the name `A` is defined multiple times
-  --> $DIR/rename-use-with-tabs.rs:9:14
-   |
-LL | use foo::{A, bar::B    as    A};
-   |           -  ^^^^^^^^^^^^^^^^^ `A` reimported here
-   |           |
-   |           previous import of the type `A` here
-   |
-   = note: `A` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use foo::{A, bar::B as OtherA};
-   |              ^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/rename-with-path.rs b/src/test/ui/issues/issue-45829/rename-with-path.rs
deleted file mode 100644 (file)
index e278a87..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-use std::{collections::HashMap as A, sync::Arc as A};
-//~^ ERROR is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-45829/rename-with-path.stderr b/src/test/ui/issues/issue-45829/rename-with-path.stderr
deleted file mode 100644 (file)
index ba83eea..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0252]: the name `A` is defined multiple times
-  --> $DIR/rename-with-path.rs:1:38
-   |
-LL | use std::{collections::HashMap as A, sync::Arc as A};
-   |           -------------------------  ^^^^^^^^^^^^^^ `A` reimported here
-   |           |
-   |           previous import of the type `A` here
-   |
-   = note: `A` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use std::{collections::HashMap as A, sync::Arc as OtherA};
-   |                                      ^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-45829/rename.rs b/src/test/ui/issues/issue-45829/rename.rs
deleted file mode 100644 (file)
index 1c45956..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-use core;
-use std as core;
-//~^ ERROR is defined multiple times
-
-fn main() {
-    1 + 1;
-}
diff --git a/src/test/ui/issues/issue-45829/rename.stderr b/src/test/ui/issues/issue-45829/rename.stderr
deleted file mode 100644 (file)
index 8f12d92..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0252]: the name `core` is defined multiple times
-  --> $DIR/rename.rs:2:5
-   |
-LL | use core;
-   |     ---- previous import of the module `core` here
-LL | use std as core;
-   |     ^^^^^^^^^^^ `core` reimported here
-   |
-   = note: `core` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use std as other_core;
-   |     ^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-46576.rs b/src/test/ui/issues/issue-46576.rs
deleted file mode 100644 (file)
index 15f458f..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#![allow(dead_code)]
-#![deny(unused_imports)]
-
-use std::fs::File;
-use std::io::{BufRead, BufReader, Read};
-//~^ ERROR unused import: `BufRead`
-
-pub fn read_from_file(path: &str) {
-    let file = File::open(&path).unwrap();
-    let mut reader = BufReader::new(file);
-    let mut s = String::new();
-    reader.read_to_string(&mut s).unwrap();
-}
-
-pub fn read_lines(s: &str) {
-    for _line in s.lines() {
-
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-46576.stderr b/src/test/ui/issues/issue-46576.stderr
deleted file mode 100644 (file)
index 6f4d970..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-error: unused import: `BufRead`
-  --> $DIR/issue-46576.rs:5:15
-   |
-LL | use std::io::{BufRead, BufReader, Read};
-   |               ^^^^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-46576.rs:2:9
-   |
-LL | #![deny(unused_imports)]
-   |         ^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-47623.rs b/src/test/ui/issues/issue-47623.rs
deleted file mode 100644 (file)
index ad8aa4c..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-use self; //~ERROR `self` imports are only allowed within a { } list
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-47623.stderr b/src/test/ui/issues/issue-47623.stderr
deleted file mode 100644 (file)
index 53968a2..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0429]: `self` imports are only allowed within a { } list
-  --> $DIR/issue-47623.rs:1:5
-   |
-LL | use self;
-   |     ^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0429`.
diff --git a/src/test/ui/issues/issue-4865-1.rs b/src/test/ui/issues/issue-4865-1.rs
deleted file mode 100644 (file)
index 68fbee3..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-// run-pass
-#![allow(unused_imports)]
-// This should resolve fine.
-// Prior to fix, the crossed imports between a and b
-// would block on the glob import, itself never being resolved
-// because these previous imports were not resolved.
-
-pub mod a {
-    use b::fn_b;
-    use c::*;
-
-    pub fn fn_a(){
-    }
-}
-
-pub mod b {
-    use a::fn_a;
-    use c::*;
-
-    pub fn fn_b(){
-    }
-}
-
-pub mod c{
-    pub fn fn_c(){
-    }
-}
-
-use a::fn_a;
-use b::fn_b;
-
-fn main() {
-}
diff --git a/src/test/ui/issues/issue-4865-2.rs b/src/test/ui/issues/issue-4865-2.rs
deleted file mode 100644 (file)
index cbe1d0d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// run-pass
-// Previously, this would have failed to resolve due to the circular
-// block between `use say` and `pub use hello::*`.
-//
-// Now, as `use say` is not `pub`, the glob import can resolve
-// without any problem and this resolves fine.
-
-pub use hello::*;
-
-pub mod say {
-    pub fn hello() { println!("hello"); }
-}
-
-pub mod hello {
-    use say;
-
-    pub fn hello() {
-        say::hello();
-    }
-}
-
-fn main() {
-    hello();
-}
diff --git a/src/test/ui/issues/issue-4865-3.rs b/src/test/ui/issues/issue-4865-3.rs
deleted file mode 100644 (file)
index 12f9bba..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-// run-pass
-#![allow(unused_imports)]
-// This should resolve fine even with the circular imports as
-// they are not `pub`.
-
-pub mod a {
-    use b::*;
-}
-
-pub mod b {
-    use a::*;
-}
-
-use a::*;
-
-fn main() {
-}
diff --git a/src/test/ui/issues/issue-49074.rs b/src/test/ui/issues/issue-49074.rs
deleted file mode 100644 (file)
index 752bb34..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Check that unknown attribute error is shown even if there are unresolved macros.
-
-#[marco_use] // typo
-//~^ ERROR cannot find attribute `marco_use` in this scope
-mod foo {
-    macro_rules! bar {
-        () => ();
-    }
-}
-
-fn main() {
-   bar!(); //~ ERROR cannot find macro `bar` in this scope
-}
diff --git a/src/test/ui/issues/issue-49074.stderr b/src/test/ui/issues/issue-49074.stderr
deleted file mode 100644 (file)
index bbfeb4e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error: cannot find macro `bar` in this scope
-  --> $DIR/issue-49074.rs:12:4
-   |
-LL |    bar!();
-   |    ^^^
-   |
-   = help: have you added the `#[macro_use]` on the module/import?
-
-error: cannot find attribute `marco_use` in this scope
-  --> $DIR/issue-49074.rs:3:3
-   |
-LL | #[marco_use] // typo
-   |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use`
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/ui/issues/issue-52891.fixed b/src/test/ui/issues/issue-52891.fixed
deleted file mode 100644 (file)
index e694b5c..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-// aux-build:issue-52891.rs
-// run-rustfix
-
-#![allow(warnings)]
-
-extern crate issue_52891;
-
-// Check that we don't suggest renaming duplicate imports but instead
-// suggest removing one.
-
-use issue_52891::a;
- //~ ERROR `a` is defined multiple times
-
-use issue_52891::{b, c}; //~ ERROR `a` is defined multiple times
-use issue_52891::{d, e}; //~ ERROR `a` is defined multiple times
-use issue_52891::{f, g}; //~ ERROR `a` is defined multiple times
-
-use issue_52891::{//~ ERROR `a` is defined multiple times
-    h,
-    i};
-use issue_52891::{j,
-    //~ ERROR `a` is defined multiple times
-    k};
-use issue_52891::{l,
-    m}; //~ ERROR `a` is defined multiple times
-
-use issue_52891::a::inner;
-use issue_52891::b::inner as other_inner; //~ ERROR `inner` is defined multiple times
-
-
-//~^ ERROR `issue_52891` is defined multiple times
-
-
-#[macro_use]
-use issue_52891::n; //~ ERROR `n` is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-52891.rs b/src/test/ui/issues/issue-52891.rs
deleted file mode 100644 (file)
index cd4b406..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-// aux-build:issue-52891.rs
-// run-rustfix
-
-#![allow(warnings)]
-
-extern crate issue_52891;
-
-// Check that we don't suggest renaming duplicate imports but instead
-// suggest removing one.
-
-use issue_52891::a;
-use issue_52891::a; //~ ERROR `a` is defined multiple times
-
-use issue_52891::{a, b, c}; //~ ERROR `a` is defined multiple times
-use issue_52891::{d, a, e}; //~ ERROR `a` is defined multiple times
-use issue_52891::{f, g, a}; //~ ERROR `a` is defined multiple times
-
-use issue_52891::{a, //~ ERROR `a` is defined multiple times
-    h,
-    i};
-use issue_52891::{j,
-    a, //~ ERROR `a` is defined multiple times
-    k};
-use issue_52891::{l,
-    m,
-    a}; //~ ERROR `a` is defined multiple times
-
-use issue_52891::a::inner;
-use issue_52891::b::inner; //~ ERROR `inner` is defined multiple times
-
-use issue_52891::{self};
-//~^ ERROR `issue_52891` is defined multiple times
-
-use issue_52891::n;
-#[macro_use]
-use issue_52891::n; //~ ERROR `n` is defined multiple times
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-52891.stderr b/src/test/ui/issues/issue-52891.stderr
deleted file mode 100644 (file)
index 6e6e42d..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-error[E0252]: the name `a` is defined multiple times
-  --> $DIR/issue-52891.rs:12:5
-   |
-LL | use issue_52891::a;
-   |     -------------- previous import of the module `a` here
-LL | use issue_52891::a;
-   |     ^^^^^^^^^^^^^^ `a` reimported here
-   |
-   = note: `a` must be defined only once in the type namespace of this module
-
-error[E0252]: the name `a` is defined multiple times
-  --> $DIR/issue-52891.rs:14:19
-   |
-LL | use issue_52891::a;
-   |     -------------- previous import of the module `a` here
-...
-LL | use issue_52891::{a, b, c};
-   |                   ^--
-   |                   |
-   |                   `a` reimported here
-   |                   help: remove unnecessary import
-   |
-   = note: `a` must be defined only once in the type namespace of this module
-
-error[E0252]: the name `a` is defined multiple times
-  --> $DIR/issue-52891.rs:15:22
-   |
-LL | use issue_52891::a;
-   |     -------------- previous import of the module `a` here
-...
-LL | use issue_52891::{d, a, e};
-   |                      ^--
-   |                      |
-   |                      `a` reimported here
-   |                      help: remove unnecessary import
-   |
-   = note: `a` must be defined only once in the type namespace of this module
-
-error[E0252]: the name `a` is defined multiple times
-  --> $DIR/issue-52891.rs:16:25
-   |
-LL | use issue_52891::a;
-   |     -------------- previous import of the module `a` here
-...
-LL | use issue_52891::{f, g, a};
-   |                         ^ `a` reimported here
-   |
-   = note: `a` must be defined only once in the type namespace of this module
-
-error[E0252]: the name `a` is defined multiple times
-  --> $DIR/issue-52891.rs:18:19
-   |
-LL | use issue_52891::a;
-   |     -------------- previous import of the module `a` here
-...
-LL | use issue_52891::{a,
-   |                   ^--
-   |                   |
-   |                   `a` reimported here
-   |                   help: remove unnecessary import
-   |
-   = note: `a` must be defined only once in the type namespace of this module
-
-error[E0252]: the name `a` is defined multiple times
-  --> $DIR/issue-52891.rs:22:5
-   |
-LL | use issue_52891::a;
-   |     -------------- previous import of the module `a` here
-...
-LL |     a,
-   |     ^--
-   |     |
-   |     `a` reimported here
-   |     help: remove unnecessary import
-   |
-   = note: `a` must be defined only once in the type namespace of this module
-
-error[E0252]: the name `a` is defined multiple times
-  --> $DIR/issue-52891.rs:26:5
-   |
-LL | use issue_52891::a;
-   |     -------------- previous import of the module `a` here
-...
-LL |     a};
-   |     ^ `a` reimported here
-   |
-   = note: `a` must be defined only once in the type namespace of this module
-
-error[E0252]: the name `inner` is defined multiple times
-  --> $DIR/issue-52891.rs:29:5
-   |
-LL | use issue_52891::a::inner;
-   |     --------------------- previous import of the module `inner` here
-LL | use issue_52891::b::inner;
-   |     ^^^^^^^^^^^^^^^^^^^^^ `inner` reimported here
-   |
-   = note: `inner` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL | use issue_52891::b::inner as other_inner;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0254]: the name `issue_52891` is defined multiple times
-  --> $DIR/issue-52891.rs:31:19
-   |
-LL | extern crate issue_52891;
-   | ------------------------- previous import of the extern crate `issue_52891` here
-...
-LL | use issue_52891::{self};
-   | ------------------^^^^--
-   | |                 |
-   | |                 `issue_52891` reimported here
-   | help: remove unnecessary import
-   |
-   = note: `issue_52891` must be defined only once in the type namespace of this module
-
-error[E0252]: the name `n` is defined multiple times
-  --> $DIR/issue-52891.rs:36:5
-   |
-LL | use issue_52891::n;
-   |     -------------- previous import of the module `n` here
-LL | #[macro_use]
-LL | use issue_52891::n;
-   |     ^^^^^^^^^^^^^^ `n` reimported here
-   |
-   = note: `n` must be defined only once in the type namespace of this module
-
-error: aborting due to 10 previous errors
-
-Some errors have detailed explanations: E0252, E0254.
-For more information about an error, try `rustc --explain E0252`.
diff --git a/src/test/ui/issues/issue-53565.rs b/src/test/ui/issues/issue-53565.rs
deleted file mode 100644 (file)
index 114a53a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-use std::time::{foo, bar, buzz};
-//~^ ERROR unresolved imports
-use std::time::{abc, def};
-//~^ ERROR unresolved imports
-fn main(){
-    println!("Hello World!");
-}
diff --git a/src/test/ui/issues/issue-53565.stderr b/src/test/ui/issues/issue-53565.stderr
deleted file mode 100644 (file)
index 71c3b2a..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0432]: unresolved imports `std::time::foo`, `std::time::bar`, `std::time::buzz`
-  --> $DIR/issue-53565.rs:1:17
-   |
-LL | use std::time::{foo, bar, buzz};
-   |                 ^^^  ^^^  ^^^^ no `buzz` in `time`
-   |                 |    |
-   |                 |    no `bar` in `time`
-   |                 no `foo` in `time`
-
-error[E0432]: unresolved imports `std::time::abc`, `std::time::def`
-  --> $DIR/issue-53565.rs:3:17
-   |
-LL | use std::time::{abc, def};
-   |                 ^^^  ^^^ no `def` in `time`
-   |                 |
-   |                 no `abc` in `time`
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-56411-aux.rs b/src/test/ui/issues/issue-56411-aux.rs
deleted file mode 100644 (file)
index c8e5a05..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-// check-pass
-
-struct T {}
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-56411.rs b/src/test/ui/issues/issue-56411.rs
deleted file mode 100644 (file)
index 163651a..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-macro_rules! import {
-    ( $(($path:expr, $name:ident)),* ) => {
-        $(
-            #[path = $path]
-            mod $name;
-            pub use self::$name;
-            //~^ ERROR the name `issue_56411_aux` is defined multiple times
-            //~| ERROR `issue_56411_aux` is private, and cannot be re-exported
-
-        )*
-    }
-}
-
-import!(("issue-56411-aux.rs", issue_56411_aux));
-
-fn main() {
-    println!("Hello, world!");
-}
diff --git a/src/test/ui/issues/issue-56411.stderr b/src/test/ui/issues/issue-56411.stderr
deleted file mode 100644 (file)
index 3ac8dc5..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0255]: the name `issue_56411_aux` is defined multiple times
-  --> $DIR/issue-56411.rs:6:21
-   |
-LL |             mod $name;
-   |             ---------- previous definition of the module `issue_56411_aux` here
-LL |             pub use self::$name;
-   |                     ^^^^^^^^^^^
-   |                     |
-   |                     `issue_56411_aux` reimported here
-   |                     you can use `as` to change the binding name of the import
-...
-LL | import!(("issue-56411-aux.rs", issue_56411_aux));
-   | ------------------------------------------------- in this macro invocation
-   |
-   = note: `issue_56411_aux` must be defined only once in the type namespace of this module
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error[E0365]: `issue_56411_aux` is private, and cannot be re-exported
-  --> $DIR/issue-56411.rs:6:21
-   |
-LL |             pub use self::$name;
-   |                     ^^^^^^^^^^^ re-export of private `issue_56411_aux`
-...
-LL | import!(("issue-56411-aux.rs", issue_56411_aux));
-   | ------------------------------------------------- in this macro invocation
-   |
-   = note: consider declaring type or module `issue_56411_aux` with `pub`
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0255, E0365.
-For more information about an error, try `rustc --explain E0255`.
diff --git a/src/test/ui/issues/issue-59764.rs b/src/test/ui/issues/issue-59764.rs
deleted file mode 100644 (file)
index 09dee8c..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-// aux-build:issue-59764.rs
-// compile-flags:--extern issue_59764
-// edition:2018
-
-#![allow(warnings)]
-
-// This tests the suggestion to import macros from the root of a crate. This aims to capture
-// the case where a user attempts to import a macro from the definition location instead of the
-// root of the crate and the macro is annotated with `#![macro_export]`.
-
-// Edge cases..
-
-mod multiple_imports_same_line_at_end {
-    use issue_59764::foo::{baz, makro};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod multiple_imports_multiline_at_end_trailing_comma {
-    use issue_59764::foo::{
-        baz,
-        makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-    };
-}
-
-mod multiple_imports_multiline_at_end {
-    use issue_59764::foo::{
-        baz,
-        makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-    };
-}
-
-mod multiple_imports_same_line_in_middle {
-    use issue_59764::foo::{baz, makro, foobar};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod multiple_imports_multiline_in_middle_trailing_comma {
-    use issue_59764::foo::{
-        baz,
-        makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-        foobar,
-    };
-}
-
-mod multiple_imports_multiline_in_middle {
-    use issue_59764::foo::{
-        baz,
-        makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-        foobar
-    };
-}
-
-mod nested_imports {
-    use issue_59764::{foobaz, foo::makro};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod nested_multiple_imports {
-    use issue_59764::{foobaz, foo::{baz, makro}};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod nested_multiline_multiple_imports_trailing_comma {
-    use issue_59764::{
-        foobaz,
-        foo::{
-            baz,
-            makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-        },
-    };
-}
-
-mod nested_multiline_multiple_imports {
-    use issue_59764::{
-        foobaz,
-        foo::{
-            baz,
-            makro //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-        }
-    };
-}
-
-mod doubly_nested_multiple_imports {
-    use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod doubly_multiline_nested_multiple_imports {
-    use issue_59764::{
-        foobaz,
-        foo::{
-            baz,
-            makro, //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-            barbaz::{
-                barfoo,
-            }
-        }
-    };
-}
-
-mod renamed_import {
-    use issue_59764::foo::makro as baz;
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod renamed_multiple_imports {
-    use issue_59764::foo::{baz, makro as foobar};
-    //~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-}
-
-mod lots_of_whitespace {
-    use
-        issue_59764::{
-
-            foobaz,
-
-
-            foo::{baz,
-
-                makro as foobar} //~ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-
-        };
-}
-
-// Simple case..
-
-use issue_59764::foo::makro;
-//~^ ERROR unresolved import `issue_59764::foo::makro` [E0432]
-
-makro!(bar);
-//~^ ERROR cannot determine resolution for the macro `makro`
-
-fn main() {
-    bar();
-    //~^ ERROR cannot find function `bar` in this scope [E0425]
-}
diff --git a/src/test/ui/issues/issue-59764.stderr b/src/test/ui/issues/issue-59764.stderr
deleted file mode 100644 (file)
index f266e90..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:14:33
-   |
-LL |     use issue_59764::foo::{baz, makro};
-   |                                 ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, foo::{baz}};
-   |                      ^^^^^^^^^       --^^
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:21:9
-   |
-LL |         makro,
-   |         ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, foo::{
-LL |         baz,
-LL |
-LL |     }};
-   |
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:28:9
-   |
-LL |         makro
-   |         ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, foo::{
-LL |         baz,
-LL |
-LL |     }};
-   |
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:33:33
-   |
-LL |     use issue_59764::foo::{baz, makro, foobar};
-   |                                 ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, foo::{baz, foobar}};
-   |                      ^^^^^^^^^         --      ^^
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:40:9
-   |
-LL |         makro,
-   |         ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, foo::{
-LL |         baz,
-LL |
-LL |         foobar,
-LL |     }};
-   |
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:48:9
-   |
-LL |         makro,
-   |         ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, foo::{
-LL |         baz,
-LL |
-LL |         foobar
-LL |     }};
-   |
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:54:31
-   |
-LL |     use issue_59764::{foobaz, foo::makro};
-   |                               ^^^^^^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, foobaz};
-   |                      ^^^^^^^      --
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:59:42
-   |
-LL |     use issue_59764::{foobaz, foo::{baz, makro}};
-   |                                          ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, foobaz, foo::{baz}};
-   |                      ^^^^^^^                 --
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:68:13
-   |
-LL |             makro,
-   |             ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, 
-LL |         foobaz,
-LL |         foo::{
-LL |             baz,
-LL |
-   |
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:78:13
-   |
-LL |             makro
-   |             ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, 
-LL |         foobaz,
-LL |         foo::{
-LL |             baz,
-LL |
-   |
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:84:42
-   |
-LL |     use issue_59764::{foobaz, foo::{baz, makro, barbaz::{barfoo}}};
-   |                                          ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, foobaz, foo::{baz, barbaz::{barfoo}}};
-   |                      ^^^^^^^                   --
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:93:13
-   |
-LL |             makro,
-   |             ^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro, 
-LL |         foobaz,
-LL |         foo::{
-LL |             baz,
-LL |
-   |
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:102:9
-   |
-LL |     use issue_59764::foo::makro as baz;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::makro as baz;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:107:33
-   |
-LL |     use issue_59764::foo::{baz, makro as foobar};
-   |                                 ^^^^^^^^^^^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |     use issue_59764::{makro as foobar, foo::{baz}};
-   |                      ^^^^^^^^^^^^^^^^^^^       --^^
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:120:17
-   |
-LL |                 makro as foobar}
-   |                 ^^^^^^^^^^^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL |         issue_59764::{makro as foobar, 
-LL | 
-LL |             foobaz,
-LL | 
-LL | 
-LL |             foo::{baz}
-   |
-
-error[E0432]: unresolved import `issue_59764::foo::makro`
-  --> $DIR/issue-59764.rs:127:5
-   |
-LL | use issue_59764::foo::makro;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ no `makro` in `foo`
-   |
-   = note: this could be because a macro annotated with `#[macro_export]` will be exported at the root of the crate instead of the module where it is defined
-help: a macro with this name exists at the root of the crate
-   |
-LL | use issue_59764::makro;
-   |     ^^^^^^^^^^^^^^^^^^
-
-error: cannot determine resolution for the macro `makro`
-  --> $DIR/issue-59764.rs:130:1
-   |
-LL | makro!(bar);
-   | ^^^^^
-   |
-   = note: import resolution is stuck, try simplifying macro imports
-
-error[E0425]: cannot find function `bar` in this scope
-  --> $DIR/issue-59764.rs:134:5
-   |
-LL |     bar();
-   |     ^^^ not found in this scope
-
-error: aborting due to 18 previous errors
-
-Some errors have detailed explanations: E0425, E0432.
-For more information about an error, try `rustc --explain E0425`.
diff --git a/src/test/ui/issues/issue-59896.rs b/src/test/ui/issues/issue-59896.rs
deleted file mode 100644 (file)
index ff9f19a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#![deny(unused_imports)]
-
-struct S;
-
-fn main() {
-    use S;  //~ ERROR the item `S` is imported redundantly
-
-    let _s = S;
-}
diff --git a/src/test/ui/issues/issue-59896.stderr b/src/test/ui/issues/issue-59896.stderr
deleted file mode 100644 (file)
index 95b7938..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error: the item `S` is imported redundantly
-  --> $DIR/issue-59896.rs:6:9
-   |
-LL | struct S;
-   | --------- the item `S` is already defined here
-...
-LL |     use S;
-   |         ^
-   |
-note: the lint level is defined here
-  --> $DIR/issue-59896.rs:1:9
-   |
-LL | #![deny(unused_imports)]
-   |         ^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/issues/issue-70041.rs b/src/test/ui/issues/issue-70041.rs
deleted file mode 100644 (file)
index 22e4229..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// compile-flags: --edition=2018
-// run-pass
-
-macro_rules! regex {
-    //~^ WARN unused macro definition
-    () => {};
-}
-
-#[allow(dead_code)]
-use regex;
-//~^ WARN unused import
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-70041.stderr b/src/test/ui/issues/issue-70041.stderr
deleted file mode 100644 (file)
index ecd618e..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-warning: unused macro definition
-  --> $DIR/issue-70041.rs:4:1
-   |
-LL | / macro_rules! regex {
-LL | |
-LL | |     () => {};
-LL | | }
-   | |_^
-   |
-   = note: `#[warn(unused_macros)]` on by default
-
-warning: unused import: `regex`
-  --> $DIR/issue-70041.rs:10:5
-   |
-LL | use regex;
-   |     ^^^^^
-   |
-   = note: `#[warn(unused_imports)]` on by default
-
-warning: 2 warnings emitted
-
diff --git a/src/test/ui/issues/issue-8208.rs b/src/test/ui/issues/issue-8208.rs
deleted file mode 100644 (file)
index 1c56693..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-use self::*; //~ ERROR: unresolved import `self::*` [E0432]
-             //~^ cannot glob-import a module into itself
-
-mod foo {
-    use foo::*; //~ ERROR: unresolved import `foo::*` [E0432]
-                //~^ cannot glob-import a module into itself
-
-    mod bar {
-        use super::bar::*;
-        //~^ ERROR: unresolved import `super::bar::*` [E0432]
-        //~| cannot glob-import a module into itself
-    }
-
-}
-
-fn main() {
-}
diff --git a/src/test/ui/issues/issue-8208.stderr b/src/test/ui/issues/issue-8208.stderr
deleted file mode 100644 (file)
index e59aea1..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error[E0432]: unresolved import `self::*`
-  --> $DIR/issue-8208.rs:1:5
-   |
-LL | use self::*;
-   |     ^^^^^^^ cannot glob-import a module into itself
-
-error[E0432]: unresolved import `foo::*`
-  --> $DIR/issue-8208.rs:5:9
-   |
-LL |     use foo::*;
-   |         ^^^^^^ cannot glob-import a module into itself
-
-error[E0432]: unresolved import `super::bar::*`
-  --> $DIR/issue-8208.rs:9:13
-   |
-LL |         use super::bar::*;
-   |             ^^^^^^^^^^^^^ cannot glob-import a module into itself
-
-error: aborting due to 3 previous errors
-
-For more information about this error, try `rustc --explain E0432`.
diff --git a/src/test/ui/issues/issue-8640.rs b/src/test/ui/issues/issue-8640.rs
deleted file mode 100644 (file)
index 51a02a3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-#[allow(unused_imports)]
-
-mod foo {
-    use baz::bar;
-    mod bar {}
-    //~^ ERROR the name `bar` is defined multiple times
-}
-mod baz { pub mod bar {} }
-
-fn main() {}
diff --git a/src/test/ui/issues/issue-8640.stderr b/src/test/ui/issues/issue-8640.stderr
deleted file mode 100644 (file)
index 4ce6394..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0255]: the name `bar` is defined multiple times
-  --> $DIR/issue-8640.rs:5:5
-   |
-LL |     use baz::bar;
-   |         -------- previous import of the module `bar` here
-LL |     mod bar {}
-   |     ^^^^^^^ `bar` redefined here
-   |
-   = note: `bar` must be defined only once in the type namespace of this module
-help: you can use `as` to change the binding name of the import
-   |
-LL |     use baz::bar as other_bar;
-   |         ^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0255`.
diff --git a/src/test/ui/kinds-of-primitive-impl.rs b/src/test/ui/kinds-of-primitive-impl.rs
new file mode 100644 (file)
index 0000000..cbd4d7a
--- /dev/null
@@ -0,0 +1,23 @@
+// ignore-tidy-linelength
+
+
+impl u8 {
+//~^ error: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive
+    pub const B: u8 = 0;
+}
+
+impl str {
+//~^ error: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive
+    fn foo() {}
+    fn bar(self) {}
+}
+
+impl char {
+//~^ error: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive
+    pub const B: u8 = 0;
+    pub const C: u8 = 0;
+    fn foo() {}
+    fn bar(self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/kinds-of-primitive-impl.stderr b/src/test/ui/kinds-of-primitive-impl.stderr
new file mode 100644 (file)
index 0000000..d19c85b
--- /dev/null
@@ -0,0 +1,40 @@
+error[E0390]: only a single inherent implementation marked with `#[lang = "u8"]` is allowed for the `u8` primitive
+  --> $DIR/kinds-of-primitive-impl.rs:4:1
+   |
+LL | / impl u8 {
+LL | |
+LL | |     pub const B: u8 = 0;
+LL | | }
+   | |_^
+   |
+   = help: consider using a trait to implement this constant
+
+error[E0390]: only a single inherent implementation marked with `#[lang = "str"]` is allowed for the `str` primitive
+  --> $DIR/kinds-of-primitive-impl.rs:9:1
+   |
+LL | / impl str {
+LL | |
+LL | |     fn foo() {}
+LL | |     fn bar(self) {}
+LL | | }
+   | |_^
+   |
+   = help: consider using a trait to implement these methods
+
+error[E0390]: only a single inherent implementation marked with `#[lang = "char"]` is allowed for the `char` primitive
+  --> $DIR/kinds-of-primitive-impl.rs:15:1
+   |
+LL | / impl char {
+LL | |
+LL | |     pub const B: u8 = 0;
+LL | |     pub const C: u8 = 0;
+LL | |     fn foo() {}
+LL | |     fn bar(self) {}
+LL | | }
+   | |_^
+   |
+   = help: consider using a trait to implement these associated items
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0390`.
diff --git a/src/test/ui/modules/issue-56411-aux.rs b/src/test/ui/modules/issue-56411-aux.rs
new file mode 100644 (file)
index 0000000..c8e5a05
--- /dev/null
@@ -0,0 +1,5 @@
+// check-pass
+
+struct T {}
+
+fn main() {}
diff --git a/src/test/ui/modules/issue-56411.rs b/src/test/ui/modules/issue-56411.rs
new file mode 100644 (file)
index 0000000..163651a
--- /dev/null
@@ -0,0 +1,18 @@
+macro_rules! import {
+    ( $(($path:expr, $name:ident)),* ) => {
+        $(
+            #[path = $path]
+            mod $name;
+            pub use self::$name;
+            //~^ ERROR the name `issue_56411_aux` is defined multiple times
+            //~| ERROR `issue_56411_aux` is private, and cannot be re-exported
+
+        )*
+    }
+}
+
+import!(("issue-56411-aux.rs", issue_56411_aux));
+
+fn main() {
+    println!("Hello, world!");
+}
diff --git a/src/test/ui/modules/issue-56411.stderr b/src/test/ui/modules/issue-56411.stderr
new file mode 100644 (file)
index 0000000..3ac8dc5
--- /dev/null
@@ -0,0 +1,33 @@
+error[E0255]: the name `issue_56411_aux` is defined multiple times
+  --> $DIR/issue-56411.rs:6:21
+   |
+LL |             mod $name;
+   |             ---------- previous definition of the module `issue_56411_aux` here
+LL |             pub use self::$name;
+   |                     ^^^^^^^^^^^
+   |                     |
+   |                     `issue_56411_aux` reimported here
+   |                     you can use `as` to change the binding name of the import
+...
+LL | import!(("issue-56411-aux.rs", issue_56411_aux));
+   | ------------------------------------------------- in this macro invocation
+   |
+   = note: `issue_56411_aux` must be defined only once in the type namespace of this module
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0365]: `issue_56411_aux` is private, and cannot be re-exported
+  --> $DIR/issue-56411.rs:6:21
+   |
+LL |             pub use self::$name;
+   |                     ^^^^^^^^^^^ re-export of private `issue_56411_aux`
+...
+LL | import!(("issue-56411-aux.rs", issue_56411_aux));
+   | ------------------------------------------------- in this macro invocation
+   |
+   = note: consider declaring type or module `issue_56411_aux` with `pub`
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0255, E0365.
+For more information about an error, try `rustc --explain E0255`.
index f9a9d071a3d1b5c5263242d9cfd538d94da41b25..a8dee5bbda40a658bbeaf15296a0d08112f3690f 100644 (file)
@@ -1,2 +1,2 @@
 type mut_box = Box<mut isize>;
-//~^ ERROR expected one of `>`, const, lifetime, or type, found keyword `mut`
+//~^ ERROR expected one of `>`, a const expression, lifetime, or type, found keyword `mut`
index 0703caf5beddd11c18bd18e1a2c54af5eec57399..39db0be9fbbd6dc686b2dac8b6a3781990317ac7 100644 (file)
@@ -1,8 +1,8 @@
-error: expected one of `>`, const, lifetime, or type, found keyword `mut`
+error: expected one of `>`, a const expression, lifetime, or type, found keyword `mut`
   --> $DIR/removed-syntax-uniq-mut-ty.rs:1:20
    |
 LL | type mut_box = Box<mut isize>;
-   |                    ^^^ expected one of `>`, const, lifetime, or type
+   |                    ^^^ expected one of `>`, a const expression, lifetime, or type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/resolve-pseudo-shadowing.rs b/src/test/ui/resolve-pseudo-shadowing.rs
deleted file mode 100644 (file)
index 85c684c..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-// run-pass
-// check that type parameters can't "shadow" qualified paths.
-
-fn check<Clone>(_c: Clone) {
-    fn check2() {
-        let _ = <() as std::clone::Clone>::clone(&());
-    }
-    check2();
-}
-
-fn main() { check(()); }
diff --git a/src/test/ui/resolve/auxiliary/extern-prelude-vec.rs b/src/test/ui/resolve/auxiliary/extern-prelude-vec.rs
new file mode 100644 (file)
index 0000000..a643c88
--- /dev/null
@@ -0,0 +1,3 @@
+#![crate_name = "Vec"]
+
+pub fn new(arg1: f32, arg2: ()) {}
diff --git a/src/test/ui/resolve/auxiliary/extern-prelude.rs b/src/test/ui/resolve/auxiliary/extern-prelude.rs
new file mode 100644 (file)
index 0000000..2fdfd85
--- /dev/null
@@ -0,0 +1,5 @@
+pub struct S;
+
+impl S {
+    pub fn external(&self) {}
+}
diff --git a/src/test/ui/resolve/extern-prelude-fail.rs b/src/test/ui/resolve/extern-prelude-fail.rs
new file mode 100644 (file)
index 0000000..7d38702
--- /dev/null
@@ -0,0 +1,9 @@
+// compile-flags:--extern extern_prelude
+// aux-build:extern-prelude.rs
+
+// Extern prelude names are not available by absolute paths
+
+fn main() {
+    use extern_prelude::S; //~ ERROR unresolved import `extern_prelude`
+    let s = ::extern_prelude::S; //~ ERROR failed to resolve
+}
diff --git a/src/test/ui/resolve/extern-prelude-fail.stderr b/src/test/ui/resolve/extern-prelude-fail.stderr
new file mode 100644 (file)
index 0000000..a59f4c9
--- /dev/null
@@ -0,0 +1,16 @@
+error[E0432]: unresolved import `extern_prelude`
+  --> $DIR/extern-prelude-fail.rs:7:9
+   |
+LL |     use extern_prelude::S;
+   |         ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`?
+
+error[E0433]: failed to resolve: maybe a missing crate `extern_prelude`?
+  --> $DIR/extern-prelude-fail.rs:8:15
+   |
+LL |     let s = ::extern_prelude::S;
+   |               ^^^^^^^^^^^^^^ maybe a missing crate `extern_prelude`?
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/resolve/extern-prelude.rs b/src/test/ui/resolve/extern-prelude.rs
new file mode 100644 (file)
index 0000000..50fed60
--- /dev/null
@@ -0,0 +1,31 @@
+// build-pass (FIXME(62277): could be check-pass?)
+// compile-flags:--extern extern_prelude --extern Vec
+// aux-build:extern-prelude.rs
+// aux-build:extern-prelude-vec.rs
+
+fn basic() {
+    // It works
+    let s = extern_prelude::S;
+    s.external();
+}
+
+fn shadow_mod() {
+    // Local module shadows `extern_prelude` from extern prelude
+    mod extern_prelude {
+        pub struct S;
+
+        impl S {
+            pub fn internal(&self) {}
+        }
+    }
+
+    let s = extern_prelude::S;
+    s.internal(); // OK
+}
+
+fn shadow_prelude() {
+    // Extern prelude shadows standard library prelude
+    let x = Vec::new(0f32, ()); // OK
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/issue-49074.rs b/src/test/ui/resolve/issue-49074.rs
new file mode 100644 (file)
index 0000000..752bb34
--- /dev/null
@@ -0,0 +1,13 @@
+// Check that unknown attribute error is shown even if there are unresolved macros.
+
+#[marco_use] // typo
+//~^ ERROR cannot find attribute `marco_use` in this scope
+mod foo {
+    macro_rules! bar {
+        () => ();
+    }
+}
+
+fn main() {
+   bar!(); //~ ERROR cannot find macro `bar` in this scope
+}
diff --git a/src/test/ui/resolve/issue-49074.stderr b/src/test/ui/resolve/issue-49074.stderr
new file mode 100644 (file)
index 0000000..bbfeb4e
--- /dev/null
@@ -0,0 +1,16 @@
+error: cannot find macro `bar` in this scope
+  --> $DIR/issue-49074.rs:12:4
+   |
+LL |    bar!();
+   |    ^^^
+   |
+   = help: have you added the `#[macro_use]` on the module/import?
+
+error: cannot find attribute `marco_use` in this scope
+  --> $DIR/issue-49074.rs:3:3
+   |
+LL | #[marco_use] // typo
+   |   ^^^^^^^^^ help: a built-in attribute with a similar name exists: `macro_use`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/resolve/resolve-pseudo-shadowing.rs b/src/test/ui/resolve/resolve-pseudo-shadowing.rs
new file mode 100644 (file)
index 0000000..85c684c
--- /dev/null
@@ -0,0 +1,11 @@
+// run-pass
+// check that type parameters can't "shadow" qualified paths.
+
+fn check<Clone>(_c: Clone) {
+    fn check2() {
+        let _ = <() as std::clone::Clone>::clone(&());
+    }
+    check2();
+}
+
+fn main() { check(()); }
diff --git a/src/test/ui/resolve_self_super_hint.rs b/src/test/ui/resolve_self_super_hint.rs
deleted file mode 100644 (file)
index a14ec5b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-mod a {
-    extern crate alloc;
-    use alloc::HashMap;
-    //~^ ERROR unresolved import `alloc` [E0432]
-    //~| HELP a similar path exists
-    //~| SUGGESTION self::alloc
-    mod b {
-        use alloc::HashMap;
-        //~^ ERROR unresolved import `alloc` [E0432]
-        //~| HELP a similar path exists
-        //~| SUGGESTION super::alloc
-        mod c {
-            use alloc::HashMap;
-            //~^ ERROR unresolved import `alloc` [E0432]
-            //~| HELP a similar path exists
-            //~| SUGGESTION a::alloc
-            mod d {
-                use alloc::HashMap;
-                //~^ ERROR unresolved import `alloc` [E0432]
-                //~| HELP a similar path exists
-                //~| SUGGESTION a::alloc
-            }
-        }
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/resolve_self_super_hint.stderr b/src/test/ui/resolve_self_super_hint.stderr
deleted file mode 100644 (file)
index bc86255..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:3:9
-   |
-LL |     use alloc::HashMap;
-   |         ^^^^^ help: a similar path exists: `self::alloc`
-
-error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:8:13
-   |
-LL |         use alloc::HashMap;
-   |             ^^^^^ help: a similar path exists: `super::alloc`
-
-error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:13:17
-   |
-LL |             use alloc::HashMap;
-   |                 ^^^^^
-   |                 |
-   |                 unresolved import
-   |                 help: a similar path exists: `a::alloc`
-
-error[E0432]: unresolved import `alloc`
-  --> $DIR/resolve_self_super_hint.rs:18:21
-   |
-LL |                 use alloc::HashMap;
-   |                     ^^^^^
-   |                     |
-   |                     unresolved import
-   |                     help: a similar path exists: `a::alloc`
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0432`.
index c60ff7dc93449f30e470e1b304c577fc2f85c398..70ec0e3033c6f71b8d96eb78707027e5cf7d4fd6 100644 (file)
@@ -1,15 +1,19 @@
-#![feature(naked_functions)]
+#![feature(asm, naked_functions)]
 
 #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
 #[naked]
-fn f() {}
+extern "C" fn f() {
+    asm!("", options(noreturn));
+}
 
 struct S;
 
 impl S {
     #[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
     #[naked]
-    fn g() {}
+    extern "C" fn g() {
+        asm!("", options(noreturn));
+    }
 }
 
 fn main() {}
index 211cd3f16ba1b48ad3d9ecf62e0881c8afc2cd78..1b49148d629b2321f45c1eaae4ee8904eef71e82 100644 (file)
@@ -5,7 +5,7 @@ LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
 
 error[E0736]: cannot use `#[track_caller]` with `#[naked]`
-  --> $DIR/error-with-naked.rs:10:5
+  --> $DIR/error-with-naked.rs:12:5
    |
 LL |     #[track_caller]
    |     ^^^^^^^^^^^^^^^
index d357afa3b3841797e934dd172d92a343b02b61d9..50a0d5bef86d32d5da908db03c8162bf72e59765 100644 (file)
@@ -6,13 +6,7 @@ LL | |
 LL | | }
    | |_^
    |
-help: consider using a trait to implement these methods
-  --> $DIR/single-primitive-inherent-impl.rs:11:1
-   |
-LL | / impl str {
-LL | |
-LL | | }
-   | |_^
+   = help: consider using a trait
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/stability-attribute/auxiliary/lint-stability.rs b/src/test/ui/stability-attribute/auxiliary/lint-stability.rs
new file mode 100644 (file)
index 0000000..de40588
--- /dev/null
@@ -0,0 +1,188 @@
+#![crate_name="lint_stability"]
+#![crate_type = "lib"]
+#![feature(staged_api)]
+#![feature(associated_type_defaults)]
+#![stable(feature = "lint_stability", since = "1.0.0")]
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated() {}
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_text() {}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "99.99.99", reason = "text")]
+pub fn deprecated_future() {}
+
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_unstable() {}
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub fn deprecated_unstable_text() {}
+
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+pub fn unstable() {}
+#[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
+pub fn unstable_text() {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn stable() {}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn stable_text() {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct MethodTester;
+
+impl MethodTester {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated(&self) {}
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    pub fn method_deprecated_unstable_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    pub fn method_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
+    pub fn method_unstable_text(&self) {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn method_stable(&self) {}
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn method_stable_text(&self) {}
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub trait Trait {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated(&self) {}
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    fn trait_deprecated_unstable_text(&self) {}
+
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    fn trait_unstable(&self) {}
+    #[unstable(feature = "unstable_test_feature", reason = "text", issue = "none")]
+    fn trait_unstable_text(&self) {}
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn trait_stable(&self) {}
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn trait_stable_text(&self) {}
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub trait TraitWithAssociatedTypes {
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    type TypeUnstable = u8;
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    type TypeDeprecated = u8;
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+impl Trait for MethodTester {}
+
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+pub trait UnstableTrait { fn dummy(&self) { } }
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub trait DeprecatedTrait {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] fn dummy(&self) { }
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnstableStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+pub struct UnstableStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct StableStruct {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")] pub i: isize
+}
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+pub enum UnstableEnum {}
+#[stable(feature = "rust1", since = "1.0.0")]
+pub enum StableEnum {}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnitStruct;
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnstableUnitStruct;
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+pub struct UnstableUnitStruct;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct StableUnitStruct;
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+pub enum Enum {
+    #[stable(feature = "stable_test_feature", since = "1.0.0")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    DeprecatedVariant,
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    #[rustc_deprecated(since = "1.0.0", reason = "text")]
+    DeprecatedUnstableVariant,
+    #[unstable(feature = "unstable_test_feature", issue = "none")]
+    UnstableVariant,
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    StableVariant,
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+#[rustc_deprecated(since = "1.0.0", reason = "text")]
+pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+#[unstable(feature = "unstable_test_feature", issue = "none")]
+pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub isize);
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[macro_export]
+macro_rules! macro_test {
+    () => (deprecated());
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[macro_export]
+macro_rules! macro_test_arg {
+    ($func:expr) => ($func);
+}
+
+#[stable(feature = "stable_test_feature", since = "1.0.0")]
+#[macro_export]
+macro_rules! macro_test_arg_nested {
+    ($func:ident) => (macro_test_arg!($func()));
+}
diff --git a/src/test/ui/stability-attribute/issue-28075.rs b/src/test/ui/stability-attribute/issue-28075.rs
new file mode 100644 (file)
index 0000000..6b4ea46
--- /dev/null
@@ -0,0 +1,13 @@
+// Unstable entities should be caught in import lists
+
+// aux-build:lint-stability.rs
+
+#![allow(warnings)]
+
+extern crate lint_stability;
+
+use lint_stability::{unstable, deprecated};
+//~^ ERROR use of unstable library feature 'unstable_test_feature'
+
+fn main() {
+}
diff --git a/src/test/ui/stability-attribute/issue-28075.stderr b/src/test/ui/stability-attribute/issue-28075.stderr
new file mode 100644 (file)
index 0000000..7e53bb5
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/issue-28075.rs:9:22
+   |
+LL | use lint_stability::{unstable, deprecated};
+   |                      ^^^^^^^^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/stability-attribute/issue-28388-3.rs b/src/test/ui/stability-attribute/issue-28388-3.rs
new file mode 100644 (file)
index 0000000..7ba9935
--- /dev/null
@@ -0,0 +1,11 @@
+// Prefix in imports with empty braces should be resolved and checked privacy, stability, etc.
+
+// aux-build:lint-stability.rs
+
+extern crate lint_stability;
+
+use lint_stability::UnstableEnum::{};
+//~^ ERROR use of unstable library feature 'unstable_test_feature'
+use lint_stability::StableEnum::{}; // OK
+
+fn main() {}
diff --git a/src/test/ui/stability-attribute/issue-28388-3.stderr b/src/test/ui/stability-attribute/issue-28388-3.stderr
new file mode 100644 (file)
index 0000000..d2e4668
--- /dev/null
@@ -0,0 +1,11 @@
+error[E0658]: use of unstable library feature 'unstable_test_feature'
+  --> $DIR/issue-28388-3.rs:7:5
+   |
+LL | use lint_stability::UnstableEnum::{};
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(unstable_test_feature)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/unused/issue-30730.rs b/src/test/ui/unused/issue-30730.rs
new file mode 100644 (file)
index 0000000..d6be90c
--- /dev/null
@@ -0,0 +1,5 @@
+#![warn(unused)]
+#![deny(warnings)]
+use std::thread;
+//~^ ERROR: unused import
+fn main() {}
diff --git a/src/test/ui/unused/issue-30730.stderr b/src/test/ui/unused/issue-30730.stderr
new file mode 100644 (file)
index 0000000..b299e99
--- /dev/null
@@ -0,0 +1,15 @@
+error: unused import: `std::thread`
+  --> $DIR/issue-30730.rs:3:5
+   |
+LL | use std::thread;
+   |     ^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-30730.rs:2:9
+   |
+LL | #![deny(warnings)]
+   |         ^^^^^^^^
+   = note: `#[deny(unused_imports)]` implied by `#[deny(warnings)]`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unused/issue-46576.rs b/src/test/ui/unused/issue-46576.rs
new file mode 100644 (file)
index 0000000..15f458f
--- /dev/null
@@ -0,0 +1,21 @@
+#![allow(dead_code)]
+#![deny(unused_imports)]
+
+use std::fs::File;
+use std::io::{BufRead, BufReader, Read};
+//~^ ERROR unused import: `BufRead`
+
+pub fn read_from_file(path: &str) {
+    let file = File::open(&path).unwrap();
+    let mut reader = BufReader::new(file);
+    let mut s = String::new();
+    reader.read_to_string(&mut s).unwrap();
+}
+
+pub fn read_lines(s: &str) {
+    for _line in s.lines() {
+
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/unused/issue-46576.stderr b/src/test/ui/unused/issue-46576.stderr
new file mode 100644 (file)
index 0000000..6f4d970
--- /dev/null
@@ -0,0 +1,14 @@
+error: unused import: `BufRead`
+  --> $DIR/issue-46576.rs:5:15
+   |
+LL | use std::io::{BufRead, BufReader, Read};
+   |               ^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-46576.rs:2:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unused/issue-59896.rs b/src/test/ui/unused/issue-59896.rs
new file mode 100644 (file)
index 0000000..ff9f19a
--- /dev/null
@@ -0,0 +1,9 @@
+#![deny(unused_imports)]
+
+struct S;
+
+fn main() {
+    use S;  //~ ERROR the item `S` is imported redundantly
+
+    let _s = S;
+}
diff --git a/src/test/ui/unused/issue-59896.stderr b/src/test/ui/unused/issue-59896.stderr
new file mode 100644 (file)
index 0000000..95b7938
--- /dev/null
@@ -0,0 +1,17 @@
+error: the item `S` is imported redundantly
+  --> $DIR/issue-59896.rs:6:9
+   |
+LL | struct S;
+   | --------- the item `S` is already defined here
+...
+LL |     use S;
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/issue-59896.rs:1:9
+   |
+LL | #![deny(unused_imports)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/unused/issue-70041.rs b/src/test/ui/unused/issue-70041.rs
new file mode 100644 (file)
index 0000000..22e4229
--- /dev/null
@@ -0,0 +1,13 @@
+// compile-flags: --edition=2018
+// run-pass
+
+macro_rules! regex {
+    //~^ WARN unused macro definition
+    () => {};
+}
+
+#[allow(dead_code)]
+use regex;
+//~^ WARN unused import
+
+fn main() {}
diff --git a/src/test/ui/unused/issue-70041.stderr b/src/test/ui/unused/issue-70041.stderr
new file mode 100644 (file)
index 0000000..ecd618e
--- /dev/null
@@ -0,0 +1,21 @@
+warning: unused macro definition
+  --> $DIR/issue-70041.rs:4:1
+   |
+LL | / macro_rules! regex {
+LL | |
+LL | |     () => {};
+LL | | }
+   | |_^
+   |
+   = note: `#[warn(unused_macros)]` on by default
+
+warning: unused import: `regex`
+  --> $DIR/issue-70041.rs:10:5
+   |
+LL | use regex;
+   |     ^^^^^
+   |
+   = note: `#[warn(unused_imports)]` on by default
+
+warning: 2 warnings emitted
+
index 7509d90c6c2fcff29fee79d75c97ff54934a3e44..784463fe0df9e71a3e22b871c006c106329673ee 100644 (file)
@@ -128,14 +128,14 @@ jobs:
         SYSROOT=$(rustc --print sysroot)
         echo "$SYSROOT/bin" >> $GITHUB_PATH
 
-    - name: Build
-      run: cargo build --features deny-warnings
+    - name: Build with internal lints
+      run: cargo build --features deny-warnings,internal-lints
 
-    - name: Test
-      run: cargo test --features deny-warnings
+    - name: Test with internal lints
+      run: cargo test --features deny-warnings,internal-lints
 
-    - name: Test clippy_lints
-      run: cargo test --features deny-warnings
+    - name: Test clippy_lints with internal lints
+      run: cargo test --features deny-warnings,internal-lints
       working-directory: clippy_lints
 
     - name: Test rustc_tools_util
index b9e4b0e67040cc89a6b4c9d84b76c67e28737648..c7e02aaf4e188762a3dd12f87409458bb2596ca2 100644 (file)
@@ -1770,6 +1770,7 @@ Released 2018-09-13
 [`cmp_owned`]: https://rust-lang.github.io/rust-clippy/master/index.html#cmp_owned
 [`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity
 [`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
+[`collapsible_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_match
 [`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain
 [`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty
 [`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator
@@ -2056,6 +2057,7 @@ Released 2018-09-13
 [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop
 [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match
 [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else
+[`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count
 [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
 [`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
 [`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
@@ -2073,6 +2075,7 @@ Released 2018-09-13
 [`suspicious_else_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_else_formatting
 [`suspicious_map`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_map
 [`suspicious_op_assign_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_op_assign_impl
+[`suspicious_operation_groupings`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_operation_groupings
 [`suspicious_unary_op_formatting`]: https://rust-lang.github.io/rust-clippy/master/index.html#suspicious_unary_op_formatting
 [`tabs_in_doc_comments`]: https://rust-lang.github.io/rust-clippy/master/index.html#tabs_in_doc_comments
 [`temporary_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#temporary_assignment
index a8e2123656e97a478269ad68d88e8bd4ca0077e0..f8c26e2d456d73bdfa0512fdb76f59bdc58bd31d 100644 (file)
@@ -14,11 +14,16 @@ All contributors are expected to follow the [Rust Code of Conduct].
 
 - [Contributing to Clippy](#contributing-to-clippy)
   - [Getting started](#getting-started)
+    - [High level approach](#high-level-approach)
     - [Finding something to fix/improve](#finding-something-to-fiximprove)
   - [Writing code](#writing-code)
   - [Getting code-completion for rustc internals to work](#getting-code-completion-for-rustc-internals-to-work)
   - [How Clippy works](#how-clippy-works)
   - [Fixing build failures caused by Rust](#fixing-build-failures-caused-by-rust)
+    - [Patching git-subtree to work with big repos](#patching-git-subtree-to-work-with-big-repos)
+    - [Performing the sync](#performing-the-sync)
+    - [Syncing back changes in Clippy to [`rust-lang/rust`]](#syncing-back-changes-in-clippy-to-rust-langrust)
+    - [Defining remotes](#defining-remotes)
   - [Issue and PR triage](#issue-and-pr-triage)
   - [Bors and Homu](#bors-and-homu)
   - [Contributions](#contributions)
@@ -320,8 +325,8 @@ commands [here][homu_instructions].
 [l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash
 [l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug
 [homu]: https://github.com/rust-lang/homu
-[homu_instructions]: https://buildbot2.rust-lang.org/homu/
-[homu_queue]: https://buildbot2.rust-lang.org/homu/queue/clippy
+[homu_instructions]: https://bors.rust-lang.org/
+[homu_queue]: https://bors.rust-lang.org/queue/clippy
 
 ## Contributions
 
index 1ddcd18598dea83b4009d927cf031f9207ad7979..a765390c6032d4c83694367683988b4b1c5e3bc0 100644 (file)
@@ -32,7 +32,7 @@ path = "src/driver.rs"
 clippy_lints = { version = "0.0.212", path = "clippy_lints" }
 # end automatic update
 semver = "0.11"
-rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"}
+rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
 tempfile = { version = "3.1.0", optional = true }
 
 [dev-dependencies]
@@ -49,8 +49,9 @@ derive-new = "0.5"
 rustc-workspace-hack = "1.0.0"
 
 [build-dependencies]
-rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"}
+rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util" }
 
 [features]
 deny-warnings = []
 integration = ["tempfile"]
+internal-lints = ["clippy_lints/internal-lints"]
index 1da626b505dfb9e1da2978c909a392acba24dcc7..fddf0614a0b85d77b24dbb93c6463222e8d7bbce 100644 (file)
@@ -182,7 +182,7 @@ cargo clippy -- -W clippy::lint_name
 ```
 
 This also works with lint groups. For example you
-can run Clippy with warnings for all lints enabled: 
+can run Clippy with warnings for all lints enabled:
 ```terminal
 cargo clippy -- -W clippy::pedantic
 ```
@@ -194,6 +194,33 @@ cargo clippy -- -A clippy::all -W clippy::useless_format -W clippy::...
 ```
 Note that if you've run clippy before, this may only take effect after you've modified a file or ran `cargo clean`.
 
+### Specifying the minimum supported Rust version
+
+Projects that intend to support old versions of Rust can disable lints pertaining to newer features by
+specifying the minimum supported Rust version (MSRV) in the clippy configuration file.
+
+```toml
+msrv = "1.30.0"
+```
+
+The MSRV can also be specified as an inner attribute, like below.
+
+```rust
+#![feature(custom_inner_attributes)]
+#![clippy::msrv = "1.30.0"]
+
+fn main() {
+  ...
+}
+```
+
+You can also omit the patch version when specifying the MSRV, so `msrv = 1.30`
+is equivalent to `msrv = 1.30.0`.
+
+Note: `custom_inner_attributes` is an unstable feature so it has to be enabled explicitly.
+
+Lints that recognize this configuration option can be found [here](https://rust-lang.github.io/rust-clippy/master/index.html#msrv)
+
 ## Contributing
 
 If you want to contribute to Clippy, you can find more information in [CONTRIBUTING.md](https://github.com/rust-lang/rust-clippy/blob/master/CONTRIBUTING.md).
index 43cb2954b74b34f9705631b3d803b2e5bbb1023e..f51c45e9eb5931a170c16c0dd187364fc2d510c7 100644 (file)
@@ -146,16 +146,30 @@ pub fn gen_deprecated<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String>
 }
 
 #[must_use]
-pub fn gen_register_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> {
-    let pre = "    store.register_lints(&[".to_string();
-    let post = "    ]);".to_string();
-    let mut inner = lints
+pub fn gen_register_lint_list<'a>(
+    internal_lints: impl Iterator<Item = &'a Lint>,
+    usable_lints: impl Iterator<Item = &'a Lint>,
+) -> Vec<String> {
+    let header = "    store.register_lints(&[".to_string();
+    let footer = "    ]);".to_string();
+    let internal_lints = internal_lints
+        .sorted_by_key(|l| format!("        &{}::{},", l.module, l.name.to_uppercase()))
+        .map(|l| {
+            format!(
+                "        #[cfg(feature = \"internal-lints\")]\n        &{}::{},",
+                l.module,
+                l.name.to_uppercase()
+            )
+        });
+    let other_lints = usable_lints
+        .sorted_by_key(|l| format!("        &{}::{},", l.module, l.name.to_uppercase()))
         .map(|l| format!("        &{}::{},", l.module, l.name.to_uppercase()))
-        .sorted()
-        .collect::<Vec<String>>();
-    inner.insert(0, pre);
-    inner.push(post);
-    inner
+        .sorted();
+    let mut lint_list = vec![header];
+    lint_list.extend(internal_lints);
+    lint_list.extend(other_lints);
+    lint_list.push(footer);
+    lint_list
 }
 
 /// Gathers all files in `src/clippy_lints` and gathers all lints inside
index fcf093f8835d866f7a2059521999ab75dd58c065..edf6c5f57a49766d44f8a353c55937ac0b015354 100644 (file)
@@ -68,7 +68,7 @@ pub fn run(update_mode: UpdateMode) {
         "end register lints",
         false,
         update_mode == UpdateMode::Change,
-        || gen_register_lint_list(usable_lints.iter().chain(internal_lints.iter())),
+        || gen_register_lint_list(internal_lints.iter(), usable_lints.iter()),
     )
     .changed;
 
index d9471d251974456a8364698567b32ce3ee2d30a0..7697eba650aca9499c95b1adf6e885ec9f885797 100644 (file)
@@ -28,6 +28,7 @@ smallvec = { version = "1", features = ["union"] }
 toml = "0.5.3"
 unicode-normalization = "0.1"
 semver = "0.11"
+rustc-semver="1.1.0"
 # NOTE: cargo requires serde feat in its url dep
 # see <https://github.com/rust-lang/rust/pull/63587#issuecomment-522343864>
 url = { version =  "2.1.0", features = ["serde"] }
@@ -36,3 +37,5 @@ syn = { version = "1", features = ["full"] }
 
 [features]
 deny-warnings = []
+# build clippy with internal lints enabled, off by default
+internal-lints = []
index 15505fd79f4a1f6ac0c338de623b478c6b0c1268..3edbe723922f8343f67a653e2578af24d4ef32ff 100644 (file)
@@ -5,7 +5,6 @@
     span_lint_and_sugg, span_lint_and_then, without_block_comments,
 };
 use if_chain::if_chain;
-use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem};
 use rustc_errors::Applicability;
 use rustc_hir::{
@@ -15,6 +14,7 @@
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::source_map::Span;
 use rustc_span::sym;
 use rustc_span::symbol::{Symbol, SymbolStr};
diff --git a/src/tools/clippy/clippy_lints/src/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/collapsible_match.rs
new file mode 100644 (file)
index 0000000..a34ba2d
--- /dev/null
@@ -0,0 +1,172 @@
+use crate::utils::visitors::LocalUsedVisitor;
+use crate::utils::{span_lint_and_then, SpanlessEq};
+use if_chain::if_chain;
+use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
+use rustc_hir::{Arm, Expr, ExprKind, Guard, HirId, Pat, PatKind, QPath, StmtKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{DefIdTree, TyCtxt};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::{MultiSpan, Span};
+
+declare_clippy_lint! {
+    /// **What it does:** Finds nested `match` or `if let` expressions where the patterns may be "collapsed" together
+    /// without adding any branches.
+    ///
+    /// Note that this lint is not intended to find _all_ cases where nested match patterns can be merged, but only
+    /// cases where merging would most likely make the code more readable.
+    ///
+    /// **Why is this bad?** It is unnecessarily verbose and complex.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// fn func(opt: Option<Result<u64, String>>) {
+    ///     let n = match opt {
+    ///         Some(n) => match n {
+    ///             Ok(n) => n,
+    ///             _ => return,
+    ///         }
+    ///         None => return,
+    ///     };
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// fn func(opt: Option<Result<u64, String>>) {
+    ///     let n = match opt {
+    ///         Some(Ok(n)) => n,
+    ///         _ => return,
+    ///     };
+    /// }
+    /// ```
+    pub COLLAPSIBLE_MATCH,
+    style,
+    "Nested `match` or `if let` expressions where the patterns may be \"collapsed\" together."
+}
+
+declare_lint_pass!(CollapsibleMatch => [COLLAPSIBLE_MATCH]);
+
+impl<'tcx> LateLintPass<'tcx> for CollapsibleMatch {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
+        if let ExprKind::Match(_expr, arms, _source) = expr.kind {
+            if let Some(wild_arm) = arms.iter().rfind(|arm| arm_is_wild_like(arm, cx.tcx)) {
+                for arm in arms {
+                    check_arm(arm, wild_arm, cx);
+                }
+            }
+        }
+    }
+}
+
+fn check_arm(arm: &Arm<'_>, wild_outer_arm: &Arm<'_>, cx: &LateContext<'_>) {
+    if_chain! {
+        let expr = strip_singleton_blocks(arm.body);
+        if let ExprKind::Match(expr_in, arms_inner, _) = expr.kind;
+        // the outer arm pattern and the inner match
+        if expr_in.span.ctxt() == arm.pat.span.ctxt();
+        // there must be no more than two arms in the inner match for this lint
+        if arms_inner.len() == 2;
+        // no if guards on the inner match
+        if arms_inner.iter().all(|arm| arm.guard.is_none());
+        // match expression must be a local binding
+        // match <local> { .. }
+        if let ExprKind::Path(QPath::Resolved(None, path)) = expr_in.kind;
+        if let Res::Local(binding_id) = path.res;
+        // one of the branches must be "wild-like"
+        if let Some(wild_inner_arm_idx) = arms_inner.iter().rposition(|arm_inner| arm_is_wild_like(arm_inner, cx.tcx));
+        let (wild_inner_arm, non_wild_inner_arm) =
+            (&arms_inner[wild_inner_arm_idx], &arms_inner[1 - wild_inner_arm_idx]);
+        if !pat_contains_or(non_wild_inner_arm.pat);
+        // the binding must come from the pattern of the containing match arm
+        // ..<local>.. => match <local> { .. }
+        if let Some(binding_span) = find_pat_binding(arm.pat, binding_id);
+        // the "wild-like" branches must be equal
+        if SpanlessEq::new(cx).eq_expr(wild_inner_arm.body, wild_outer_arm.body);
+        // the binding must not be used in the if guard
+        if !matches!(arm.guard, Some(Guard::If(guard)) if LocalUsedVisitor::new(binding_id).check_expr(guard));
+        // ...or anywhere in the inner match
+        if !arms_inner.iter().any(|arm| LocalUsedVisitor::new(binding_id).check_arm(arm));
+        then {
+            span_lint_and_then(
+                cx,
+                COLLAPSIBLE_MATCH,
+                expr.span,
+                "Unnecessary nested match",
+                |diag| {
+                    let mut help_span = MultiSpan::from_spans(vec![binding_span, non_wild_inner_arm.pat.span]);
+                    help_span.push_span_label(binding_span, "Replace this binding".into());
+                    help_span.push_span_label(non_wild_inner_arm.pat.span, "with this pattern".into());
+                    diag.span_help(help_span, "The outer pattern can be modified to include the inner pattern.");
+                },
+            );
+        }
+    }
+}
+
+fn strip_singleton_blocks<'hir>(mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {
+    while let ExprKind::Block(block, _) = expr.kind {
+        match (block.stmts, block.expr) {
+            ([stmt], None) => match stmt.kind {
+                StmtKind::Expr(e) | StmtKind::Semi(e) => expr = e,
+                _ => break,
+            },
+            ([], Some(e)) => expr = e,
+            _ => break,
+        }
+    }
+    expr
+}
+
+/// A "wild-like" pattern is wild ("_") or `None`.
+/// For this lint to apply, both the outer and inner match expressions
+/// must have "wild-like" branches that can be combined.
+fn arm_is_wild_like(arm: &Arm<'_>, tcx: TyCtxt<'_>) -> bool {
+    if arm.guard.is_some() {
+        return false;
+    }
+    match arm.pat.kind {
+        PatKind::Binding(..) | PatKind::Wild => true,
+        PatKind::Path(QPath::Resolved(None, path)) if is_none_ctor(path.res, tcx) => true,
+        _ => false,
+    }
+}
+
+fn find_pat_binding(pat: &Pat<'_>, hir_id: HirId) -> Option<Span> {
+    let mut span = None;
+    pat.walk_short(|p| match &p.kind {
+        // ignore OR patterns
+        PatKind::Or(_) => false,
+        PatKind::Binding(_bm, _, _ident, _) => {
+            let found = p.hir_id == hir_id;
+            if found {
+                span = Some(p.span);
+            }
+            !found
+        },
+        _ => true,
+    });
+    span
+}
+
+fn pat_contains_or(pat: &Pat<'_>) -> bool {
+    let mut result = false;
+    pat.walk(|p| {
+        let is_or = matches!(p.kind, PatKind::Or(_));
+        result |= is_or;
+        !is_or
+    });
+    result
+}
+
+fn is_none_ctor(res: Res, tcx: TyCtxt<'_>) -> bool {
+    if let Some(none_id) = tcx.lang_items().option_none_variant() {
+        if let Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Const), id) = res {
+            if let Some(variant_id) = tcx.parent(id) {
+                return variant_id == none_id;
+            }
+        }
+    }
+    false
+}
index 99f161a0510f4286c7f682016562dd7e99439a6a..ae1143b2c50ce8fbbe5647c56f6d52e386b70155 100644 (file)
@@ -12,7 +12,8 @@
     /// **Why is this bad?** `if` is not guaranteed to be exhaustive and conditionals can get
     /// repetitive
     ///
-    /// **Known problems:** None.
+    /// **Known problems:** The match statement may be slower due to the compiler
+    /// not inlining the call to cmp. See issue #5354
     ///
     /// **Example:**
     /// ```rust,ignore
index 612c5355338a140f1ed371a01779fee6a4fbf20a..f69f6f1412af97d0c35cfc044b887dd6111def9e 100644 (file)
@@ -280,8 +280,7 @@ fn field_reassigned_by_stmt<'tcx>(this: &Stmt<'tcx>, binding_name: Symbol) -> Op
         // only take assignments to fields where the left-hand side field is a field of
         // the same binding as the previous statement
         if let ExprKind::Field(ref binding, field_ident) = assign_lhs.kind;
-        if let ExprKind::Path(ref qpath) = binding.kind;
-        if let QPath::Resolved(_, path) = qpath;
+        if let ExprKind::Path(QPath::Resolved(_, path)) = binding.kind;
         if let Some(second_binding_name) = path.segments.last();
         if second_binding_name.ident.name == binding_name;
         then {
index 1c3285ed701db19683379058e45f6a2c2453bd46..bec0c9f93a0d294d27f7dc025363daf37ae3abb3 100644 (file)
@@ -51,26 +51,6 @@ macro_rules! declare_deprecated_lint {
     "`Vec::as_mut_slice` has been stabilized in 1.7"
 }
 
-declare_deprecated_lint! {
-    /// **What it does:** Nothing. This lint has been deprecated.
-    ///
-    /// **Deprecation reason:** This used to check for `.to_string()` method calls on values
-    /// of type `&str`. This is not unidiomatic and with specialization coming, `to_string` could be
-    /// specialized to be as efficient as `to_owned`.
-    pub STR_TO_STRING,
-    "using `str::to_string` is common even today and specialization will likely happen soon"
-}
-
-declare_deprecated_lint! {
-    /// **What it does:** Nothing. This lint has been deprecated.
-    ///
-    /// **Deprecation reason:** This used to check for `.to_string()` method calls on values
-    /// of type `String`. This is not unidiomatic and with specialization coming, `to_string` could be
-    /// specialized to be as efficient as `clone`.
-    pub STRING_TO_STRING,
-    "using `string::to_string` is common even today and specialization will likely happen soon"
-}
-
 declare_deprecated_lint! {
     /// **What it does:** Nothing. This lint has been deprecated.
     ///
index 3201adbf9a0b60147bd8dd96cdb0025e082f9cbc..6308f6e2e7e9d6d8c825620ad644386dad8b5b6f 100644 (file)
@@ -1,10 +1,10 @@
 use crate::utils::{
-    eq_expr_value, higher, implements_trait, in_macro, is_copy, is_expn_of, multispan_sugg, snippet, span_lint,
-    span_lint_and_then,
+    ast_utils::is_useless_with_eq_exprs, eq_expr_value, higher, implements_trait, in_macro, is_copy, is_expn_of,
+    multispan_sugg, snippet, span_lint, span_lint_and_then,
 };
 use if_chain::if_chain;
 use rustc_errors::Applicability;
-use rustc_hir::{BinOp, BinOpKind, BorrowKind, Expr, ExprKind, StmtKind};
+use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, StmtKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
@@ -102,7 +102,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
             if macro_with_not_op(&left.kind) || macro_with_not_op(&right.kind) {
                 return;
             }
-            if is_valid_operator(op) && eq_expr_value(cx, left, right) {
+            if is_useless_with_eq_exprs(higher::binop(op.node)) && eq_expr_value(cx, left, right) {
                 span_lint(
                     cx,
                     EQ_OP,
@@ -245,22 +245,3 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         }
     }
 }
-
-fn is_valid_operator(op: BinOp) -> bool {
-    matches!(
-        op.node,
-        BinOpKind::Sub
-            | BinOpKind::Div
-            | BinOpKind::Eq
-            | BinOpKind::Lt
-            | BinOpKind::Le
-            | BinOpKind::Gt
-            | BinOpKind::Ge
-            | BinOpKind::Ne
-            | BinOpKind::And
-            | BinOpKind::Or
-            | BinOpKind::BitXor
-            | BinOpKind::BitAnd
-            | BinOpKind::BitOr
-    )
-}
index e0a1f4c5ca4f2cd25f0fbd7d5862a52bbaa3edc1..1194bd7e55e2566e5ad5c20f741d8888829e5e5f 100644 (file)
@@ -41,8 +41,7 @@
 impl<'tcx> LateLintPass<'tcx> for OkIfLet {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if_chain! { //begin checking variables
-            if let ExprKind::Match(ref op, ref body, source) = expr.kind; //test if expr is a match
-            if let MatchSource::IfLetDesugar { .. } = source; //test if it is an If Let
+            if let ExprKind::Match(ref op, ref body, MatchSource::IfLetDesugar { .. }) = expr.kind; //test if expr is if let
             if let ExprKind::MethodCall(_, ok_span, ref result_types, _) = op.kind; //check is expr.ok() has type Result<T,E>.ok(, _)
             if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _)  = body[0].pat.kind; //get operation
             if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized;
index ed7f3b9293dbf856904e597ba09e7e16012fa396..03e95c9e27f6ae241627945d537a629306da4d73 100644 (file)
@@ -68,8 +68,7 @@ fn expr_match(cx: &LateContext<'_>, expr: &Expr<'_>) {
                 if_chain! {
                     if let StmtKind::Semi(expr, ..) = &stmt.kind;
                     // make sure it's a break, otherwise we want to skip
-                    if let ExprKind::Break(.., break_expr) = &expr.kind;
-                    if let Some(break_expr) = break_expr;
+                    if let ExprKind::Break(.., Some(break_expr)) = &expr.kind;
                     then {
                             lint(cx, expr.span, break_expr.span, LINT_BREAK);
                     }
index b57fe8dc4269e341b7f6299cae07331aff409562..3a01acd8fdc97a94e779a93ce6b3123d43fd4662 100644 (file)
@@ -59,8 +59,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
             if let Some(target) = subtracts_one(cx, e);
 
             // Extracting out the variable name
-            if let ExprKind::Path(ref assign_path) = target.kind;
-            if let QPath::Resolved(_, ref ares_path) = assign_path;
+            if let ExprKind::Path(QPath::Resolved(_, ref ares_path)) = target.kind;
 
             then {
                 // Handle symmetric conditions in the if statement
index 8998fae09de31f38b50d79b48e8fab933bf3b63e..0927d218446ddb71c506d9cc19558c4fc265059e 100644 (file)
@@ -58,12 +58,12 @@ fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
             return;
         }
 
-        // skip initial items
+        // skip initial items and trailing semicolons
         let stmts = item
             .stmts
             .iter()
             .map(|stmt| &stmt.kind)
-            .skip_while(|s| matches!(**s, StmtKind::Item(..)));
+            .skip_while(|s| matches!(**s, StmtKind::Item(..) | StmtKind::Empty));
 
         // lint on all further items
         for stmt in stmts {
index 025ff86da39d8cc9fd6b117fce951e37f400ebcd..a76595ed0897dd85ffa73afc66bfe79211d4392b 100644 (file)
@@ -52,8 +52,7 @@ fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
             if let ItemKind::Const(hir_ty, _) = &item.kind;
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
             if let ty::Array(element_type, cst) = ty.kind();
-            if let ConstKind::Value(val) = cst.val;
-            if let ConstValue::Scalar(element_count) = val;
+            if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.val;
             if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
             if let Ok(element_size) = cx.layout_of(element_type).map(|l| l.size.bytes());
             if self.maximum_allowed_size < element_count * element_size;
index 9fd3780e14e04023423491d9c94cac1994de5b3a..9a448ab125686cf2ce405a7ca9c1a84416b800c7 100644 (file)
@@ -43,8 +43,7 @@ fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
         if_chain! {
             if let ExprKind::Repeat(_, _) = expr.kind;
             if let ty::Array(element_type, cst) = cx.typeck_results().expr_ty(expr).kind();
-            if let ConstKind::Value(val) = cst.val;
-            if let ConstValue::Scalar(element_count) = val;
+            if let ConstKind::Value(ConstValue::Scalar(element_count)) = cst.val;
             if let Ok(element_count) = element_count.to_machine_usize(&cx.tcx);
             if let Ok(element_size) = cx.layout_of(element_type).map(|l| l.size.bytes());
             if self.maximum_allowed_size < element_count * element_size;
index 8243b0a29bc68b3642828e3c7295b45f8627c614..0d2d95324c4f7556f400230f5b33e852f9b2099c 100644 (file)
@@ -1,12 +1,11 @@
+use crate::utils::visitors::LocalUsedVisitor;
 use crate::utils::{higher, qpath_res, snippet, span_lint_and_then};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
-use rustc_hir::intravisit;
 use rustc_hir::BindingAnnotation;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::hir::map::Map;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 
 declare_clippy_lint! {
@@ -66,10 +65,10 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
                 if let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind;
                 if let hir::StmtKind::Expr(ref if_) = expr.kind;
                 if let Some((ref cond, ref then, ref else_)) = higher::if_block(&if_);
-                if !used_in_expr(cx, canonical_id, cond);
+                if !LocalUsedVisitor::new(canonical_id).check_expr(cond);
                 if let hir::ExprKind::Block(ref then, _) = then.kind;
                 if let Some(value) = check_assign(cx, canonical_id, &*then);
-                if !used_in_expr(cx, canonical_id, value);
+                if !LocalUsedVisitor::new(canonical_id).check_expr(value);
                 then {
                     let span = stmt.span.to(if_.span);
 
@@ -136,32 +135,6 @@ fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx hir::Block<'_>) {
     }
 }
 
-struct UsedVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    id: hir::HirId,
-    used: bool,
-}
-
-impl<'a, 'tcx> intravisit::Visitor<'tcx> for UsedVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
-        if_chain! {
-            if let hir::ExprKind::Path(ref qpath) = expr.kind;
-            if let Res::Local(local_id) = qpath_res(self.cx, qpath, expr.hir_id);
-            if self.id == local_id;
-            then {
-                self.used = true;
-                return;
-            }
-        }
-        intravisit::walk_expr(self, expr);
-    }
-    fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-        intravisit::NestedVisitorMap::None
-    }
-}
-
 fn check_assign<'tcx>(
     cx: &LateContext<'tcx>,
     decl: hir::HirId,
@@ -176,18 +149,10 @@ fn check_assign<'tcx>(
         if let Res::Local(local_id) = qpath_res(cx, qpath, var.hir_id);
         if decl == local_id;
         then {
-            let mut v = UsedVisitor {
-                cx,
-                id: decl,
-                used: false,
-            };
-
-            for s in block.stmts.iter().take(block.stmts.len()-1) {
-                intravisit::walk_stmt(&mut v, s);
+            let mut v = LocalUsedVisitor::new(decl);
 
-                if v.used {
-                    return None;
-                }
+            if block.stmts.iter().take(block.stmts.len()-1).any(|stmt| v.check_stmt(stmt)) {
+                return None;
             }
 
             return Some(value);
@@ -196,9 +161,3 @@ fn check_assign<'tcx>(
 
     None
 }
-
-fn used_in_expr<'tcx>(cx: &LateContext<'tcx>, id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> bool {
-    let mut v = UsedVisitor { cx, id, used: false };
-    intravisit::walk_expr(&mut v, expr);
-    v.used
-}
index 7e8cbd00c22a146dadb04d454046ed3bb2ce1cfb..2b99ed570b14874dbe02b0ce127f06d4ade72a90 100644 (file)
@@ -44,6 +44,7 @@
 extern crate rustc_trait_selection;
 extern crate rustc_typeck;
 
+use crate::utils::parse_msrv;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_lint::LintId;
 use rustc_session::Session;
@@ -171,6 +172,7 @@ macro_rules! declare_clippy_lint {
 mod checked_conversions;
 mod cognitive_complexity;
 mod collapsible_if;
+mod collapsible_match;
 mod comparison_chain;
 mod copies;
 mod copy_iterator;
@@ -304,9 +306,11 @@ macro_rules! declare_clippy_lint {
 mod serde_api;
 mod shadow;
 mod single_component_path_imports;
+mod size_of_in_element_count;
 mod slow_vector_initialization;
 mod stable_sort_primitive;
 mod strings;
+mod suspicious_operation_groupings;
 mod suspicious_trait_impl;
 mod swap;
 mod tabs_in_doc_comments;
@@ -440,14 +444,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         "clippy::unstable_as_mut_slice",
         "`Vec::as_mut_slice` has been stabilized in 1.7",
     );
-    store.register_removed(
-        "clippy::str_to_string",
-        "using `str::to_string` is common even today and specialization will likely happen soon",
-    );
-    store.register_removed(
-        "clippy::string_to_string",
-        "using `string::to_string` is common even today and specialization will likely happen soon",
-    );
     store.register_removed(
         "clippy::misaligned_transmute",
         "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
@@ -504,6 +500,24 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
 
     // begin register lints, do not remove this comment, it’s used in `update_lints`
     store.register_lints(&[
+        #[cfg(feature = "internal-lints")]
+        &utils::internal_lints::CLIPPY_LINTS_INTERNAL,
+        #[cfg(feature = "internal-lints")]
+        &utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS,
+        #[cfg(feature = "internal-lints")]
+        &utils::internal_lints::COMPILER_LINT_FUNCTIONS,
+        #[cfg(feature = "internal-lints")]
+        &utils::internal_lints::DEFAULT_LINT,
+        #[cfg(feature = "internal-lints")]
+        &utils::internal_lints::INVALID_PATHS,
+        #[cfg(feature = "internal-lints")]
+        &utils::internal_lints::LINT_WITHOUT_LINT_PASS,
+        #[cfg(feature = "internal-lints")]
+        &utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
+        #[cfg(feature = "internal-lints")]
+        &utils::internal_lints::OUTER_EXPN_EXPN_DATA,
+        #[cfg(feature = "internal-lints")]
+        &utils::internal_lints::PRODUCE_ICE,
         &approx_const::APPROX_CONSTANT,
         &arithmetic::FLOAT_ARITHMETIC,
         &arithmetic::INTEGER_ARITHMETIC,
@@ -537,6 +551,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &checked_conversions::CHECKED_CONVERSIONS,
         &cognitive_complexity::COGNITIVE_COMPLEXITY,
         &collapsible_if::COLLAPSIBLE_IF,
+        &collapsible_match::COLLAPSIBLE_MATCH,
         &comparison_chain::COMPARISON_CHAIN,
         &copies::IFS_SAME_COND,
         &copies::IF_SAME_THEN_ELSE,
@@ -833,12 +848,16 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &shadow::SHADOW_SAME,
         &shadow::SHADOW_UNRELATED,
         &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS,
+        &size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
         &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
         &stable_sort_primitive::STABLE_SORT_PRIMITIVE,
         &strings::STRING_ADD,
         &strings::STRING_ADD_ASSIGN,
         &strings::STRING_FROM_UTF8_AS_BYTES,
         &strings::STRING_LIT_AS_BYTES,
+        &strings::STRING_TO_STRING,
+        &strings::STR_TO_STRING,
+        &suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS,
         &suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
         &suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
         &swap::ALMOST_SWAPPED,
@@ -907,15 +926,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &unwrap_in_result::UNWRAP_IN_RESULT,
         &use_self::USE_SELF,
         &useless_conversion::USELESS_CONVERSION,
-        &utils::internal_lints::CLIPPY_LINTS_INTERNAL,
-        &utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS,
-        &utils::internal_lints::COMPILER_LINT_FUNCTIONS,
-        &utils::internal_lints::DEFAULT_LINT,
-        &utils::internal_lints::INVALID_PATHS,
-        &utils::internal_lints::LINT_WITHOUT_LINT_PASS,
-        &utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
-        &utils::internal_lints::OUTER_EXPN_EXPN_DATA,
-        &utils::internal_lints::PRODUCE_ICE,
         &vec::USELESS_VEC,
         &vec_resize_to_zero::VEC_RESIZE_TO_ZERO,
         &verbose_file_reads::VERBOSE_FILE_READS,
@@ -934,14 +944,22 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     ]);
     // end register lints, do not remove this comment, it’s used in `update_lints`
 
+    // all the internal lints
+    #[cfg(feature = "internal-lints")]
+    {
+        store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal);
+        store.register_early_pass(|| box utils::internal_lints::ProduceIce);
+        store.register_late_pass(|| box utils::inspector::DeepCodeInspector);
+        store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls);
+        store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
+        store.register_late_pass(|| box utils::internal_lints::InvalidPaths);
+        store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default());
+        store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
+        store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass);
+    }
+    store.register_late_pass(|| box utils::author::Author);
     store.register_late_pass(|| box await_holding_invalid::AwaitHolding);
     store.register_late_pass(|| box serde_api::SerdeAPI);
-    store.register_late_pass(|| box utils::internal_lints::CompilerLintFunctions::new());
-    store.register_late_pass(|| box utils::internal_lints::LintWithoutLintPass::default());
-    store.register_late_pass(|| box utils::internal_lints::OuterExpnDataPass);
-    store.register_late_pass(|| box utils::internal_lints::InvalidPaths);
-    store.register_late_pass(|| box utils::inspector::DeepCodeInspector);
-    store.register_late_pass(|| box utils::author::Author);
     let vec_box_size_threshold = conf.vec_box_size_threshold;
     store.register_late_pass(move || box types::Types::new(vec_box_size_threshold));
     store.register_late_pass(|| box booleans::NonminimalBool);
@@ -964,12 +982,25 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box len_zero::LenZero);
     store.register_late_pass(|| box attrs::Attributes);
     store.register_late_pass(|| box blocks_in_if_conditions::BlocksInIfConditions);
+    store.register_late_pass(|| box collapsible_match::CollapsibleMatch);
     store.register_late_pass(|| box unicode::Unicode);
     store.register_late_pass(|| box unit_return_expecting_ord::UnitReturnExpectingOrd);
     store.register_late_pass(|| box strings::StringAdd);
     store.register_late_pass(|| box implicit_return::ImplicitReturn);
     store.register_late_pass(|| box implicit_saturating_sub::ImplicitSaturatingSub);
-    store.register_late_pass(|| box methods::Methods);
+
+    let msrv = conf.msrv.as_ref().and_then(|s| {
+        parse_msrv(s, None, None).or_else(|| {
+            sess.err(&format!("error reading Clippy's configuration file. `{}` is not a valid Rust version", s));
+            None
+        })
+    });
+
+    store.register_late_pass(move || box methods::Methods::new(msrv));
+    store.register_late_pass(move || box matches::Matches::new(msrv));
+    store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv));
+    store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv));
+    store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount);
     store.register_late_pass(|| box map_clone::MapClone);
     store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
     store.register_late_pass(|| box shadow::Shadow);
@@ -983,7 +1014,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box types::Casts);
     let type_complexity_threshold = conf.type_complexity_threshold;
     store.register_late_pass(move || box types::TypeComplexity::new(type_complexity_threshold));
-    store.register_late_pass(|| box matches::Matches::default());
     store.register_late_pass(|| box minmax::MinMaxPass);
     store.register_late_pass(|| box open_options::OpenOptions);
     store.register_late_pass(|| box zero_div_zero::ZeroDiv);
@@ -1057,6 +1087,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box types::UnitArg);
     store.register_late_pass(|| box double_comparison::DoubleComparisons);
     store.register_late_pass(|| box question_mark::QuestionMark);
+    store.register_early_pass(|| box suspicious_operation_groupings::SuspiciousOperationGroupings);
     store.register_late_pass(|| box suspicious_trait_impl::SuspiciousImpl);
     store.register_late_pass(|| box map_unit_fn::MapUnit);
     store.register_late_pass(|| box inherent_impl::MultipleInherentImpl::default());
@@ -1107,10 +1138,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box cargo_common_metadata::CargoCommonMetadata);
     store.register_late_pass(|| box multiple_crate_versions::MultipleCrateVersions);
     store.register_late_pass(|| box wildcard_dependencies::WildcardDependencies);
-    store.register_early_pass(|| box literal_representation::LiteralDigitGrouping);
+    let literal_representation_lint_fraction_readability = conf.unreadable_literal_lint_fractions;
+    store.register_early_pass(move || box literal_representation::LiteralDigitGrouping::new(literal_representation_lint_fraction_readability));
     let literal_representation_threshold = conf.literal_representation_threshold;
     store.register_early_pass(move || box literal_representation::DecimalLiteralRepresentation::new(literal_representation_threshold));
-    store.register_early_pass(|| box utils::internal_lints::ClippyLintsInternal);
     let enum_variant_name_threshold = conf.enum_variant_name_threshold;
     store.register_early_pass(move || box enum_variants::EnumVariantNames::new(enum_variant_name_threshold));
     store.register_early_pass(|| box tabs_in_doc_comments::TabsInDocComments);
@@ -1124,7 +1155,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move || box large_const_arrays::LargeConstArrays::new(array_size_threshold));
     store.register_late_pass(|| box floating_point_arithmetic::FloatingPointArithmetic);
     store.register_early_pass(|| box as_conversions::AsConversions);
-    store.register_early_pass(|| box utils::internal_lints::ProduceIce);
     store.register_late_pass(|| box let_underscore::LetUnderscore);
     store.register_late_pass(|| box atomic_ordering::AtomicOrdering);
     store.register_early_pass(|| box single_component_path_imports::SingleComponentPathImports);
@@ -1140,16 +1170,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box dereference::Dereferencing);
     store.register_late_pass(|| box option_if_let_else::OptionIfLetElse);
     store.register_late_pass(|| box future_not_send::FutureNotSend);
-    store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls);
     store.register_late_pass(|| box if_let_mutex::IfLetMutex);
     store.register_late_pass(|| box mut_mutex_lock::MutMutexLock);
     store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems);
-    store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive);
     store.register_late_pass(|| box manual_async_fn::ManualAsyncFn);
     store.register_early_pass(|| box redundant_field_names::RedundantFieldNames);
     store.register_late_pass(|| box vec_resize_to_zero::VecResizeToZero);
     store.register_late_pass(|| box panic_in_result_fn::PanicInResultFn);
-
     let single_char_binding_names_threshold = conf.single_char_binding_names_threshold;
     store.register_early_pass(move || box non_expressive_names::NonExpressiveNames {
         single_char_binding_names_threshold,
@@ -1166,14 +1193,13 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(|| box manual_ok_or::ManualOkOr);
     store.register_late_pass(|| box float_equality_without_abs::FloatEqualityWithoutAbs);
     store.register_late_pass(|| box async_yields_async::AsyncYieldsAsync);
-    store.register_late_pass(|| box manual_strip::ManualStrip);
-    store.register_late_pass(|| box utils::internal_lints::MatchTypeOnDiagItem);
     let disallowed_methods = conf.disallowed_methods.iter().cloned().collect::<FxHashSet<_>>();
     store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
     store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
     store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
     store.register_late_pass(|| box undropped_manually_drops::UndroppedManuallyDrops);
-
+    store.register_late_pass(|| box strings::StrToString);
+    store.register_late_pass(|| box strings::StringToString);
 
     store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
         LintId::of(&arithmetic::FLOAT_ARITHMETIC),
@@ -1192,6 +1218,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&integer_division::INTEGER_DIVISION),
         LintId::of(&let_underscore::LET_UNDERSCORE_MUST_USE),
         LintId::of(&literal_representation::DECIMAL_LITERAL_REPRESENTATION),
+        LintId::of(&map_err_ignore::MAP_ERR_IGNORE),
         LintId::of(&matches::REST_PAT_IN_FULLY_BOUND_STRUCTS),
         LintId::of(&matches::WILDCARD_ENUM_MATCH_ARM),
         LintId::of(&mem_forget::MEM_FORGET),
@@ -1215,6 +1242,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&shadow::SHADOW_REUSE),
         LintId::of(&shadow::SHADOW_SAME),
         LintId::of(&strings::STRING_ADD),
+        LintId::of(&strings::STRING_TO_STRING),
+        LintId::of(&strings::STR_TO_STRING),
         LintId::of(&types::RC_BUFFER),
         LintId::of(&unwrap_in_result::UNWRAP_IN_RESULT),
         LintId::of(&verbose_file_reads::VERBOSE_FILE_READS),
@@ -1256,7 +1285,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&loops::EXPLICIT_ITER_LOOP),
         LintId::of(&macro_use::MACRO_USE_IMPORTS),
         LintId::of(&manual_ok_or::MANUAL_OK_OR),
-        LintId::of(&map_err_ignore::MAP_ERR_IGNORE),
         LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS),
         LintId::of(&matches::MATCH_BOOL),
         LintId::of(&matches::MATCH_SAME_ARMS),
@@ -1304,6 +1332,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&wildcard_imports::WILDCARD_IMPORTS),
     ]);
 
+    #[cfg(feature = "internal-lints")]
     store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
         LintId::of(&utils::internal_lints::CLIPPY_LINTS_INTERNAL),
         LintId::of(&utils::internal_lints::COLLAPSIBLE_SPAN_LINT_CALLS),
@@ -1337,6 +1366,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&booleans::NONMINIMAL_BOOL),
         LintId::of(&bytecount::NAIVE_BYTECOUNT),
         LintId::of(&collapsible_if::COLLAPSIBLE_IF),
+        LintId::of(&collapsible_match::COLLAPSIBLE_MATCH),
         LintId::of(&comparison_chain::COMPARISON_CHAIN),
         LintId::of(&copies::IFS_SAME_COND),
         LintId::of(&copies::IF_SAME_THEN_ELSE),
@@ -1533,9 +1563,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&self_assignment::SELF_ASSIGNMENT),
         LintId::of(&serde_api::SERDE_API_MISUSE),
         LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
+        LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
         LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
         LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE),
         LintId::of(&strings::STRING_FROM_UTF8_AS_BYTES),
+        LintId::of(&suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
         LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
         LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
         LintId::of(&swap::ALMOST_SWAPPED),
@@ -1602,6 +1634,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&blacklisted_name::BLACKLISTED_NAME),
         LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
         LintId::of(&collapsible_if::COLLAPSIBLE_IF),
+        LintId::of(&collapsible_match::COLLAPSIBLE_MATCH),
         LintId::of(&comparison_chain::COMPARISON_CHAIN),
         LintId::of(&default::FIELD_REASSIGN_WITH_DEFAULT),
         LintId::of(&doc::MISSING_SAFETY_DOC),
@@ -1687,6 +1720,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&returns::LET_AND_RETURN),
         LintId::of(&returns::NEEDLESS_RETURN),
         LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
+        LintId::of(&suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS),
         LintId::of(&tabs_in_doc_comments::TABS_IN_DOC_COMMENTS),
         LintId::of(&to_digit_is_some::TO_DIGIT_IS_SOME),
         LintId::of(&try_err::TRY_ERR),
@@ -1839,6 +1873,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&regex::INVALID_REGEX),
         LintId::of(&self_assignment::SELF_ASSIGNMENT),
         LintId::of(&serde_api::SERDE_API_MISUSE),
+        LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
         LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
         LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
         LintId::of(&swap::ALMOST_SWAPPED),
@@ -1930,14 +1965,6 @@ fn register_removed_non_tool_lints(store: &mut rustc_lint::LintStore) {
         "unstable_as_mut_slice",
         "`Vec::as_mut_slice` has been stabilized in 1.7",
     );
-    store.register_removed(
-        "str_to_string",
-        "using `str::to_string` is common even today and specialization will likely happen soon",
-    );
-    store.register_removed(
-        "string_to_string",
-        "using `string::to_string` is common even today and specialization will likely happen soon",
-    );
     store.register_removed(
         "misaligned_transmute",
         "this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr",
index e8a741683dac12d7192a8e02562b3484e1599750..87a957a9bd241728bd01fbaedaf06f08ee5836a7 100644 (file)
@@ -11,7 +11,7 @@
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 
 declare_clippy_lint! {
     /// **What it does:** Warns if a long integral or floating-point constant does
@@ -32,7 +32,7 @@
     /// ```
     pub UNREADABLE_LITERAL,
     pedantic,
-    "long integer literal without underscores"
+    "long literal without underscores"
 }
 
 declare_clippy_lint! {
@@ -208,7 +208,13 @@ fn display(&self, suggested_format: String, cx: &EarlyContext<'_>, span: rustc_s
     }
 }
 
-declare_lint_pass!(LiteralDigitGrouping => [
+#[allow(clippy::module_name_repetitions)]
+#[derive(Copy, Clone)]
+pub struct LiteralDigitGrouping {
+    lint_fraction_readability: bool,
+}
+
+impl_lint_pass!(LiteralDigitGrouping => [
     UNREADABLE_LITERAL,
     INCONSISTENT_DIGIT_GROUPING,
     LARGE_DIGIT_GROUPS,
@@ -223,7 +229,7 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
         }
 
         if let ExprKind::Lit(ref lit) = expr.kind {
-            Self::check_lit(cx, lit)
+            self.check_lit(cx, lit)
         }
     }
 }
@@ -232,7 +238,13 @@ fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
 const UUID_GROUP_LENS: [usize; 5] = [8, 4, 4, 4, 12];
 
 impl LiteralDigitGrouping {
-    fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
+    pub fn new(lint_fraction_readability: bool) -> Self {
+        Self {
+            lint_fraction_readability,
+        }
+    }
+
+    fn check_lit(self, cx: &EarlyContext<'_>, lit: &Lit) {
         if_chain! {
             if let Some(src) = snippet_opt(cx, lit.span);
             if let Some(mut num_lit) = NumericLiteral::from_lit(&src, &lit);
@@ -247,9 +259,12 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) {
 
                 let result = (|| {
 
-                    let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix)?;
+                    let integral_group_size = Self::get_group_size(num_lit.integer.split('_'), num_lit.radix, true)?;
                     if let Some(fraction) = num_lit.fraction {
-                        let fractional_group_size = Self::get_group_size(fraction.rsplit('_'), num_lit.radix)?;
+                        let fractional_group_size = Self::get_group_size(
+                            fraction.rsplit('_'),
+                            num_lit.radix,
+                            self.lint_fraction_readability)?;
 
                         let consistent = Self::parts_consistent(integral_group_size,
                                                                 fractional_group_size,
@@ -363,7 +378,11 @@ fn parts_consistent(
 
     /// Returns the size of the digit groups (or None if ungrouped) if successful,
     /// otherwise returns a `WarningType` for linting.
-    fn get_group_size<'a>(groups: impl Iterator<Item = &'a str>, radix: Radix) -> Result<Option<usize>, WarningType> {
+    fn get_group_size<'a>(
+        groups: impl Iterator<Item = &'a str>,
+        radix: Radix,
+        lint_unreadable: bool,
+    ) -> Result<Option<usize>, WarningType> {
         let mut groups = groups.map(str::len);
 
         let first = groups.next().expect("At least one group");
@@ -380,7 +399,7 @@ fn get_group_size<'a>(groups: impl Iterator<Item = &'a str>, radix: Radix) -> Re
             } else {
                 Ok(Some(second))
             }
-        } else if first > 5 {
+        } else if first > 5 && lint_unreadable {
             Err(WarningType::UnreadableLiteral)
         } else {
             Ok(None)
index 0d31e9cfc3decb073691ca18766184563141b25f..1bd96b2b4c89beb3e433a3d8b416ac498cd42d6e 100644 (file)
@@ -2,6 +2,7 @@
 use crate::utils::paths;
 use crate::utils::sugg::Sugg;
 use crate::utils::usage::{is_unused, mutated_variables};
+use crate::utils::visitors::LocalUsedVisitor;
 use crate::utils::{
     contains_name, get_enclosing_block, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait,
     indent_of, is_in_panic_handler, is_integer_const, is_no_std_crate, is_refutable, is_type_diagnostic_item,
@@ -767,7 +768,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult {
         ExprKind::InlineAsm(ref asm) => asm
             .operands
             .iter()
-            .map(|o| match o {
+            .map(|(o, _)| match o {
                 InlineAsmOperand::In { expr, .. }
                 | InlineAsmOperand::InOut { expr, .. }
                 | InlineAsmOperand::Const { expr }
@@ -1919,8 +1920,7 @@ fn check_for_single_element_loop<'tcx>(
     if_chain! {
         if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg_expr) = arg.kind;
         if let PatKind::Binding(.., target, _) = pat.kind;
-        if let ExprKind::Array(ref arg_expr_list) = arg_expr.kind;
-        if let [arg_expression] = arg_expr_list;
+        if let ExprKind::Array([arg_expression]) = arg_expr.kind;
         if let ExprKind::Path(ref list_item) = arg_expression.kind;
         if let Some(list_item_name) = single_segment_path(list_item).map(|ps| ps.ident.name);
         if let ExprKind::Block(ref block, _) = body.kind;
@@ -2025,8 +2025,7 @@ fn check_for_mutability(cx: &LateContext<'_>, bound: &Expr<'_>) -> Option<HirId>
                 let node_str = cx.tcx.hir().get(hir_id);
                 if_chain! {
                     if let Node::Binding(pat) = node_str;
-                    if let PatKind::Binding(bind_ann, ..) = pat.kind;
-                    if let BindingAnnotation::Mutable = bind_ann;
+                    if let PatKind::Binding(BindingAnnotation::Mutable, ..) = pat.kind;
                     then {
                         return Some(hir_id);
                     }
@@ -2071,28 +2070,6 @@ fn pat_is_wild<'tcx>(pat: &'tcx PatKind<'_>, body: &'tcx Expr<'_>) -> bool {
     }
 }
 
-struct LocalUsedVisitor<'a, 'tcx> {
-    cx: &'a LateContext<'tcx>,
-    local: HirId,
-    used: bool,
-}
-
-impl<'a, 'tcx> Visitor<'tcx> for LocalUsedVisitor<'a, 'tcx> {
-    type Map = Map<'tcx>;
-
-    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if same_var(self.cx, expr, self.local) {
-            self.used = true;
-        } else {
-            walk_expr(self, expr);
-        }
-    }
-
-    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
-        NestedVisitorMap::None
-    }
-}
-
 struct VarVisitor<'a, 'tcx> {
     /// context reference
     cx: &'a LateContext<'tcx>,
@@ -2126,11 +2103,7 @@ fn check(&mut self, idx: &'tcx Expr<'_>, seqexpr: &'tcx Expr<'_>, expr: &'tcx Ex
             then {
                 let index_used_directly = same_var(self.cx, idx, self.var);
                 let indexed_indirectly = {
-                    let mut used_visitor = LocalUsedVisitor {
-                        cx: self.cx,
-                        local: self.var,
-                        used: false,
-                    };
+                    let mut used_visitor = LocalUsedVisitor::new(self.var);
                     walk_expr(&mut used_visitor, idx);
                     used_visitor.used
                 };
@@ -2950,7 +2923,7 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
         for ref stmt in block.stmts {
             if_chain! {
                 if let StmtKind::Local(
-                    Local { pat: Pat { kind: PatKind::Binding(_, _, ident, .. ), .. },
+                    Local { pat: Pat { hir_id: pat_id, kind: PatKind::Binding(_, _, ident, .. ), .. },
                     init: Some(ref init_expr), .. }
                 ) = stmt.kind;
                 if let ExprKind::MethodCall(ref method_name, _, &[ref iter_source], ..) = init_expr.kind;
@@ -2964,6 +2937,16 @@ fn check_needless_collect_indirect_usage<'tcx>(expr: &'tcx Expr<'_>, cx: &LateCo
                 if let Some(iter_calls) = detect_iter_and_into_iters(block, *ident);
                 if iter_calls.len() == 1;
                 then {
+                    let mut used_count_visitor = UsedCountVisitor {
+                        cx,
+                        id: *pat_id,
+                        count: 0,
+                    };
+                    walk_block(&mut used_count_visitor, block);
+                    if used_count_visitor.count > 1 {
+                        return;
+                    }
+
                     // Suggest replacing iter_call with iter_replacement, and removing stmt
                     let iter_call = &iter_calls[0];
                     span_lint_and_then(
@@ -3087,6 +3070,28 @@ fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
     }
 }
 
+struct UsedCountVisitor<'a, 'tcx> {
+    cx: &'a LateContext<'tcx>,
+    id: HirId,
+    count: usize,
+}
+
+impl<'a, 'tcx> Visitor<'tcx> for UsedCountVisitor<'a, 'tcx> {
+    type Map = Map<'tcx>;
+
+    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
+        if same_var(self.cx, expr, self.id) {
+            self.count += 1;
+        } else {
+            walk_expr(self, expr);
+        }
+    }
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
+    }
+}
+
 /// Detect the occurrences of calls to `iter` or `into_iter` for the
 /// given identifier
 fn detect_iter_and_into_iters<'tcx>(block: &'tcx Block<'tcx>, identifier: Ident) -> Option<Vec<IterFunction>> {
index a1450b0d5feaac4ba85e6eba11a5ddd550f39eb3..91849e748878f645b6453e1571cf8357f0fab61f 100644 (file)
@@ -1,12 +1,15 @@
-use crate::utils::{snippet_opt, span_lint_and_then};
+use crate::utils::{meets_msrv, snippet_opt, span_lint_and_then};
 use if_chain::if_chain;
 use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind};
 use rustc_attr as attr;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::{sym, Span};
 
+const MANUAL_NON_EXHAUSTIVE_MSRV: RustcVersion = RustcVersion::new(1, 40, 0);
+
 declare_clippy_lint! {
     /// **What it does:** Checks for manual implementations of the non-exhaustive pattern.
     ///
     "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]"
 }
 
-declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
+#[derive(Clone)]
+pub struct ManualNonExhaustive {
+    msrv: Option<RustcVersion>,
+}
+
+impl ManualNonExhaustive {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]);
 
 impl EarlyLintPass for ManualNonExhaustive {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
+        if !meets_msrv(self.msrv.as_ref(), &MANUAL_NON_EXHAUSTIVE_MSRV) {
+            return;
+        }
+
         match &item.kind {
             ItemKind::Enum(def, _) => {
                 check_manual_non_exhaustive_enum(cx, item, &def.variants);
@@ -73,6 +92,8 @@ fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
             _ => {},
         }
     }
+
+    extract_msrv_attr!(EarlyContext);
 }
 
 fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) {
index 4afb0ab3badb06a1a20e4d6678153192a17855d1..3c4368a3545a9f71b5a432b700a630e652b70250 100644 (file)
@@ -1,7 +1,7 @@
 use crate::consts::{constant, Constant};
 use crate::utils::usage::mutated_variables;
 use crate::utils::{
-    eq_expr_value, higher, match_def_path, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then,
+    eq_expr_value, higher, match_def_path, meets_msrv, multispan_sugg, paths, qpath_res, snippet, span_lint_and_then,
 };
 
 use if_chain::if_chain;
 use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
 use rustc_hir::BinOpKind;
 use rustc_hir::{BorrowKind, Expr, ExprKind};
-use rustc_lint::{LateContext, LateLintPass};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty;
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Spanned;
 use rustc_span::Span;
 
+const MANUAL_STRIP_MSRV: RustcVersion = RustcVersion::new(1, 45, 0);
+
 declare_clippy_lint! {
     /// **What it does:**
     /// Suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing using
     "suggests using `strip_{prefix,suffix}` over `str::{starts,ends}_with` and slicing"
 }
 
-declare_lint_pass!(ManualStrip => [MANUAL_STRIP]);
+pub struct ManualStrip {
+    msrv: Option<RustcVersion>,
+}
+
+impl ManualStrip {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(ManualStrip => [MANUAL_STRIP]);
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
 enum StripKind {
@@ -61,6 +75,10 @@ enum StripKind {
 
 impl<'tcx> LateLintPass<'tcx> for ManualStrip {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if !meets_msrv(self.msrv.as_ref(), &MANUAL_STRIP_MSRV) {
+            return;
+        }
+
         if_chain! {
             if let Some((cond, then, _)) = higher::if_block(&expr);
             if let ExprKind::MethodCall(_, _, [target_arg, pattern], _) = cond.kind;
@@ -114,6 +132,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             }
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
 
 // Returns `Some(arg)` if `expr` matches `arg.len()` and `None` otherwise.
@@ -199,8 +219,7 @@ fn visit_expr(&mut self, ex: &'tcx Expr<'_>) {
                 if is_ref_str(self.cx, ex);
                 let unref = peel_ref(ex);
                 if let ExprKind::Index(indexed, index) = &unref.kind;
-                if let Some(range) = higher::range(index);
-                if let higher::Range { start, end, .. } = range;
+                if let Some(higher::Range { start, end, .. }) = higher::range(index);
                 if let ExprKind::Path(path) = &indexed.kind;
                 if qpath_res(self.cx, path, ex.hir_id) == self.target;
                 then {
index 5298e16a04d9b7d3578edc82c111fb3984cfbf9b..f3c0515b9bcde0e9e4522a9a517dc03e93fa8d38 100644 (file)
@@ -99,7 +99,7 @@
     /// }
     /// ```
     pub MAP_ERR_IGNORE,
-    pedantic,
+    restriction,
     "`map_err` should not ignore the original error"
 }
 
@@ -133,9 +133,9 @@ fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) {
                                     cx,
                                     MAP_ERR_IGNORE,
                                     body_span,
-                                    "`map_err(|_|...` ignores the original error",
+                                    "`map_err(|_|...` wildcard pattern discards the original error",
                                     None,
-                                    "Consider wrapping the error in an enum variant",
+                                    "Consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)",
                                 );
                             }
                         }
index c6dca54e2509adbbf493114ffebfcff9b244361d..274d20cfa8005b772f3aabeb9866b524d67fed95 100644 (file)
@@ -3,8 +3,8 @@
 use crate::utils::usage::is_unused;
 use crate::utils::{
     expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable,
-    is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet,
-    snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
+    is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, meets_msrv, multispan_sugg, remove_blocks,
+    snippet, snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
     span_lint_and_then,
 };
 use crate::utils::{paths, search_same, SpanlessEq, SpanlessHash};
@@ -20,6 +20,7 @@
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, Ty, TyS};
+use rustc_semver::RustcVersion;
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::{Span, Spanned};
 use rustc_span::{sym, Symbol};
 }
 
 declare_clippy_lint! {
-    /// **What it does:** Lint for redundant pattern matching over `Result` or
-    /// `Option`
+    /// **What it does:** Lint for redundant pattern matching over `Result`, `Option`,
+    /// `std::task::Poll` or `std::net::IpAddr`
     ///
     /// **Why is this bad?** It's more concise and clear to just use the proper
     /// utility function
     /// **Example:**
     ///
     /// ```rust
+    /// # use std::task::Poll;
+    /// # use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
     /// if let Ok(_) = Ok::<i32, i32>(42) {}
     /// if let Err(_) = Err::<i32, i32>(42) {}
     /// if let None = None::<()> {}
     /// if let Some(_) = Some(42) {}
+    /// if let Poll::Pending = Poll::Pending::<()> {}
+    /// if let Poll::Ready(_) = Poll::Ready(42) {}
+    /// if let IpAddr::V4(_) = IpAddr::V4(Ipv4Addr::LOCALHOST) {}
+    /// if let IpAddr::V6(_) = IpAddr::V6(Ipv6Addr::LOCALHOST) {}
     /// match Ok::<i32, i32>(42) {
     ///     Ok(_) => true,
     ///     Err(_) => false,
     /// The more idiomatic use would be:
     ///
     /// ```rust
+    /// # use std::task::Poll;
+    /// # use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
     /// if Ok::<i32, i32>(42).is_ok() {}
     /// if Err::<i32, i32>(42).is_err() {}
     /// if None::<()>.is_none() {}
     /// if Some(42).is_some() {}
+    /// if Poll::Pending::<()>.is_pending() {}
+    /// if Poll::Ready(42).is_ready() {}
+    /// if IpAddr::V4(Ipv4Addr::LOCALHOST).is_ipv4() {}
+    /// if IpAddr::V6(Ipv6Addr::LOCALHOST).is_ipv6() {}
     /// Ok::<i32, i32>(42).is_ok();
     /// ```
     pub REDUNDANT_PATTERN_MATCHING,
     ///
     /// **Why is this bad?** Readability and needless complexity.
     ///
-    /// **Known problems:** None
+    /// **Known problems:** This lint falsely triggers, if there are arms with
+    /// `cfg` attributes that remove an arm evaluating to `false`.
     ///
     /// **Example:**
     /// ```rust
 
 #[derive(Default)]
 pub struct Matches {
+    msrv: Option<RustcVersion>,
     infallible_destructuring_match_linted: bool,
 }
 
+impl Matches {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self {
+            msrv,
+            ..Matches::default()
+        }
+    }
+}
+
 impl_lint_pass!(Matches => [
     SINGLE_MATCH,
     MATCH_REF_PATS,
@@ -543,6 +568,8 @@ pub struct Matches {
     MATCH_SAME_ARMS,
 ]);
 
+const MATCH_LIKE_MATCHES_MACRO_MSRV: RustcVersion = RustcVersion::new(1, 42, 0);
+
 impl<'tcx> LateLintPass<'tcx> for Matches {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if in_external_macro(cx.sess(), expr.span) || in_macro(expr.span) {
@@ -550,7 +577,12 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         }
 
         redundant_pattern_match::check(cx, expr);
-        if !check_match_like_matches(cx, expr) {
+
+        if meets_msrv(self.msrv.as_ref(), &MATCH_LIKE_MATCHES_MACRO_MSRV) {
+            if !check_match_like_matches(cx, expr) {
+                lint_match_arms(cx, expr);
+            }
+        } else {
             lint_match_arms(cx, expr);
         }
 
@@ -614,8 +646,7 @@ fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
         if_chain! {
             if !in_external_macro(cx.sess(), pat.span);
             if !in_macro(pat.span);
-            if let PatKind::Struct(ref qpath, fields, true) = pat.kind;
-            if let QPath::Resolved(_, ref path) = qpath;
+            if let PatKind::Struct(QPath::Resolved(_, ref path), fields, true) = pat.kind;
             if let Some(def_id) = path.res.opt_def_id();
             let ty = cx.tcx.type_of(def_id);
             if let ty::Adt(def, _) = ty.kind();
@@ -634,6 +665,8 @@ fn check_pat(&mut self, cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>) {
             }
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
 
 #[rustfmt::skip]
@@ -922,16 +955,14 @@ fn check_wild_enum_match(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>])
                 if let QPath::Resolved(_, p) = path {
                     missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
                 }
-            } else if let PatKind::TupleStruct(ref path, ref patterns, ..) = arm.pat.kind {
-                if let QPath::Resolved(_, p) = path {
-                    // Some simple checks for exhaustive patterns.
-                    // There is a room for improvements to detect more cases,
-                    // but it can be more expensive to do so.
-                    let is_pattern_exhaustive =
-                        |pat: &&Pat<'_>| matches!(pat.kind, PatKind::Wild | PatKind::Binding(.., None));
-                    if patterns.iter().all(is_pattern_exhaustive) {
-                        missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
-                    }
+            } else if let PatKind::TupleStruct(QPath::Resolved(_, p), ref patterns, ..) = arm.pat.kind {
+                // Some simple checks for exhaustive patterns.
+                // There is a room for improvements to detect more cases,
+                // but it can be more expensive to do so.
+                let is_pattern_exhaustive =
+                    |pat: &&Pat<'_>| matches!(pat.kind, PatKind::Wild | PatKind::Binding(.., None));
+                if patterns.iter().all(is_pattern_exhaustive) {
+                    missing_variants.retain(|e| e.ctor_def_id != Some(p.res.def_id()));
                 }
             }
         }
@@ -1134,13 +1165,16 @@ fn find_matches_sugg(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr
         if b0 != b1;
         let if_guard = &b0_arms[0].guard;
         if if_guard.is_none() || b0_arms.len() == 1;
+        if b0_arms[0].attrs.is_empty();
         if b0_arms[1..].iter()
             .all(|arm| {
                 find_bool_lit(&arm.body.kind, desugared).map_or(false, |b| b == b0) &&
-                arm.guard.is_none()
+                arm.guard.is_none() && arm.attrs.is_empty()
             });
         then {
-            let mut applicability = Applicability::MachineApplicable;
+            // The suggestion may be incorrect, because some arms can have `cfg` attributes
+            // evaluated into `false` and so such arms will be stripped before.
+            let mut applicability = Applicability::MaybeIncorrect;
             let pat = {
                 use itertools::Itertools as _;
                 b0_arms.iter()
@@ -1403,8 +1437,7 @@ fn is_ref_some_arm(arm: &Arm<'_>) -> Option<BindingAnnotation> {
         if let ExprKind::Call(ref e, ref args) = remove_blocks(&arm.body).kind;
         if let ExprKind::Path(ref some_path) = e.kind;
         if match_qpath(some_path, &paths::OPTION_SOME) && args.len() == 1;
-        if let ExprKind::Path(ref qpath) = args[0].kind;
-        if let &QPath::Resolved(_, ref path2) = qpath;
+        if let ExprKind::Path(QPath::Resolved(_, ref path2)) = args[0].kind;
         if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
         then {
             return Some(rb)
@@ -1538,6 +1571,12 @@ fn find_sugg_for_if_let<'tcx>(
                         "is_err()"
                     } else if match_qpath(path, &paths::OPTION_SOME) {
                         "is_some()"
+                    } else if match_qpath(path, &paths::POLL_READY) {
+                        "is_ready()"
+                    } else if match_qpath(path, &paths::IPADDR_V4) {
+                        "is_ipv4()"
+                    } else if match_qpath(path, &paths::IPADDR_V6) {
+                        "is_ipv6()"
                     } else {
                         return;
                     }
@@ -1545,7 +1584,15 @@ fn find_sugg_for_if_let<'tcx>(
                     return;
                 }
             },
-            PatKind::Path(ref path) if match_qpath(path, &paths::OPTION_NONE) => "is_none()",
+            PatKind::Path(ref path) => {
+                if match_qpath(path, &paths::OPTION_NONE) {
+                    "is_none()"
+                } else if match_qpath(path, &paths::POLL_PENDING) {
+                    "is_pending()"
+                } else {
+                    return;
+                }
+            },
             _ => return,
         };
 
@@ -1610,6 +1657,17 @@ fn find_sugg_for_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: &
                             "is_ok()",
                             "is_err()",
                         )
+                        .or_else(|| {
+                            find_good_method_for_match(
+                                arms,
+                                path_left,
+                                path_right,
+                                &paths::IPADDR_V4,
+                                &paths::IPADDR_V6,
+                                "is_ipv4()",
+                                "is_ipv6()",
+                            )
+                        })
                     } else {
                         None
                     }
@@ -1628,6 +1686,17 @@ fn find_sugg_for_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, op: &
                             "is_some()",
                             "is_none()",
                         )
+                        .or_else(|| {
+                            find_good_method_for_match(
+                                arms,
+                                path_left,
+                                path_right,
+                                &paths::POLL_READY,
+                                &paths::POLL_PENDING,
+                                "is_ready()",
+                                "is_pending()",
+                            )
+                        })
                     } else {
                         None
                     }
index 40a625758616455c3d0e174c7a6fc747fca11cf7..44c974b9d98577c2add2c02bedb8f8e1feea592e 100644 (file)
@@ -90,8 +90,7 @@ fn is_min_or_max<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) -> Option<M
     if_chain! {
         if let hir::ExprKind::Call(func, args) = &expr.kind;
         if args.is_empty();
-        if let hir::ExprKind::Path(path) = &func.kind;
-        if let hir::QPath::TypeRelative(_, segment) = path;
+        if let hir::ExprKind::Path(hir::QPath::TypeRelative(_, segment)) = &func.kind;
         then {
             match &*segment.ident.as_str() {
                 "max_value" => return Some(MinMax::Max),
index fa1744043657a2eee08d978616af231d4f73c706..8002c27a5e91b7e27b92818a5b51f47275832761 100644 (file)
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
-use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{TraitItem, TraitItemKind};
 use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
-use rustc_middle::hir::map::Map;
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, TraitRef, Ty, TyS};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_semver::RustcVersion;
+use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::source_map::Span;
 use rustc_span::symbol::{sym, SymbolStr};
 
 use crate::utils::eager_or_lazy::is_lazyness_candidate;
 use crate::utils::usage::mutated_variables;
 use crate::utils::{
-    contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro,
-    is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment, match_def_path, match_qpath,
-    match_trait_method, match_type, match_var, method_calls, method_chain_args, paths, remove_blocks, return_ty,
-    single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite, span_lint,
-    span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg, walk_ptrs_ty_depth, SpanlessEq,
+    contains_return, contains_ty, get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher,
+    implements_trait, in_macro, is_copy, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment,
+    match_def_path, match_qpath, match_trait_method, match_type, match_var, meets_msrv, method_calls,
+    method_chain_args, paths, remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability,
+    snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg, span_lint_and_then, sugg,
+    walk_ptrs_ty_depth, SpanlessEq,
 };
 
 declare_clippy_lint! {
     "use `.collect()` instead of `::from_iter()`"
 }
 
-declare_lint_pass!(Methods => [
+pub struct Methods {
+    msrv: Option<RustcVersion>,
+}
+
+impl Methods {
+    #[must_use]
+    pub fn new(msrv: Option<RustcVersion>) -> Self {
+        Self { msrv }
+    }
+}
+
+impl_lint_pass!(Methods => [
     UNWRAP_USED,
     EXPECT_USED,
     SHOULD_IMPLEMENT_TRAIT,
@@ -1531,8 +1542,12 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
                 check_pointer_offset(cx, expr, arg_lists[0])
             },
             ["is_file", ..] => lint_filetype_is_file(cx, expr, arg_lists[0]),
-            ["map", "as_ref"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false),
-            ["map", "as_mut"] => lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true),
+            ["map", "as_ref"] => {
+                lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], false, self.msrv.as_ref())
+            },
+            ["map", "as_mut"] => {
+                lint_option_as_ref_deref(cx, expr, arg_lists[1], arg_lists[0], true, self.msrv.as_ref())
+            },
             ["unwrap_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "unwrap_or"),
             ["get_or_insert_with", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "get_or_insert"),
             ["ok_or_else", ..] => unnecessary_lazy_eval::lint(cx, expr, arg_lists[0], "ok_or"),
@@ -1738,6 +1753,8 @@ fn check_trait_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx TraitItem<'_>
             }
         }
     }
+
+    extract_msrv_attr!(LateContext);
 }
 
 /// Checks for the `OR_FUN_CALL` lint.
@@ -3453,6 +3470,8 @@ fn lint_suspicious_map(cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
     );
 }
 
+const OPTION_AS_REF_DEREF_MSRV: RustcVersion = RustcVersion::new(1, 40, 0);
+
 /// lint use of `_.as_ref().map(Deref::deref)` for `Option`s
 fn lint_option_as_ref_deref<'tcx>(
     cx: &LateContext<'tcx>,
@@ -3460,7 +3479,12 @@ fn lint_option_as_ref_deref<'tcx>(
     as_ref_args: &[hir::Expr<'_>],
     map_args: &[hir::Expr<'_>],
     is_mut: bool,
+    msrv: Option<&RustcVersion>,
 ) {
+    if !meets_msrv(msrv, &OPTION_AS_REF_DEREF_MSRV) {
+        return;
+    }
+
     let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not);
 
     let option_ty = cx.typeck_results().expr_ty(&as_ref_args[0]);
@@ -3846,36 +3870,6 @@ fn is_bool(ty: &hir::Ty<'_>) -> bool {
     }
 }
 
-// Returns `true` if `expr` contains a return expression
-fn contains_return(expr: &hir::Expr<'_>) -> bool {
-    struct RetCallFinder {
-        found: bool,
-    }
-
-    impl<'tcx> intravisit::Visitor<'tcx> for RetCallFinder {
-        type Map = Map<'tcx>;
-
-        fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
-            if self.found {
-                return;
-            }
-            if let hir::ExprKind::Ret(..) = &expr.kind {
-                self.found = true;
-            } else {
-                intravisit::walk_expr(self, expr);
-            }
-        }
-
-        fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<Self::Map> {
-            intravisit::NestedVisitorMap::None
-        }
-    }
-
-    let mut visitor = RetCallFinder { found: false };
-    visitor.visit_expr(expr);
-    visitor.found
-}
-
 fn check_pointer_offset(cx: &LateContext<'_>, expr: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     if_chain! {
         if args.len() == 2;
index 308e92057b751cecf7f8e2c5f13fb54904c43ec2..0512d74c7b1c8350bd31ca5f039d84578d663b83 100644 (file)
@@ -18,7 +18,7 @@
 use crate::utils::{
     get_item_name, get_parent_expr, higher, implements_trait, in_constant, is_integer_const, iter_input_pats,
     last_path_segment, match_qpath, match_trait_method, paths, snippet, snippet_opt, span_lint, span_lint_and_sugg,
-    span_lint_and_then, span_lint_hir_and_then, SpanlessEq,
+    span_lint_and_then, span_lint_hir_and_then, unsext, SpanlessEq,
 };
 
 declare_clippy_lint! {
 }
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for getting the remainder of a division by one.
+    /// **What it does:** Checks for getting the remainder of a division by one or minus
+    /// one.
     ///
-    /// **Why is this bad?** The result can only ever be zero. No one will write
-    /// such code deliberately, unless trying to win an Underhanded Rust
-    /// Contest. Even for that contest, it's probably a bad idea. Use something more
-    /// underhanded.
+    /// **Why is this bad?** The result for a divisor of one can only ever be zero; for
+    /// minus one it can cause panic/overflow (if the left operand is the minimal value of
+    /// the respective integer type) or results in zero. No one will write such code
+    /// deliberately, unless trying to win an Underhanded Rust Contest. Even for that
+    /// contest, it's probably a bad idea. Use something more underhanded.
     ///
     /// **Known problems:** None.
     ///
     /// ```rust
     /// # let x = 1;
     /// let a = x % 1;
+    /// let a = x % -1;
     /// ```
     pub MODULO_ONE,
     correctness,
-    "taking a number modulo 1, which always returns 0"
+    "taking a number modulo +/-1, which can either panic/overflow or always returns 0"
 }
 
 declare_clippy_lint! {
@@ -378,60 +381,8 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 return;
             },
             ExprKind::Binary(ref cmp, ref left, ref right) => {
-                let op = cmp.node;
-                if op.is_comparison() {
-                    check_nan(cx, left, expr);
-                    check_nan(cx, right, expr);
-                    check_to_owned(cx, left, right, true);
-                    check_to_owned(cx, right, left, false);
-                }
-                if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
-                    if is_allowed(cx, left) || is_allowed(cx, right) {
-                        return;
-                    }
-
-                    // Allow comparing the results of signum()
-                    if is_signum(cx, left) && is_signum(cx, right) {
-                        return;
-                    }
-
-                    if let Some(name) = get_item_name(cx, expr) {
-                        let name = name.as_str();
-                        if name == "eq"
-                            || name == "ne"
-                            || name == "is_nan"
-                            || name.starts_with("eq_")
-                            || name.ends_with("_eq")
-                        {
-                            return;
-                        }
-                    }
-                    let is_comparing_arrays = is_array(cx, left) || is_array(cx, right);
-                    let (lint, msg) = get_lint_and_message(
-                        is_named_constant(cx, left) || is_named_constant(cx, right),
-                        is_comparing_arrays,
-                    );
-                    span_lint_and_then(cx, lint, expr.span, msg, |diag| {
-                        let lhs = Sugg::hir(cx, left, "..");
-                        let rhs = Sugg::hir(cx, right, "..");
-
-                        if !is_comparing_arrays {
-                            diag.span_suggestion(
-                                expr.span,
-                                "consider comparing them within some margin of error",
-                                format!(
-                                    "({}).abs() {} error_margin",
-                                    lhs - rhs,
-                                    if op == BinOpKind::Eq { '<' } else { '>' }
-                                ),
-                                Applicability::HasPlaceholders, // snippet
-                            );
-                        }
-                        diag.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`");
-                    });
-                } else if op == BinOpKind::Rem && is_integer_const(cx, right, 1) {
-                    span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0");
-                }
+                check_binary(cx, expr, cmp, left, right);
+                return;
             },
             _ => {},
         }
@@ -744,3 +695,74 @@ fn check_cast(cx: &LateContext<'_>, span: Span, e: &Expr<'_>, ty: &hir::Ty<'_>)
         }
     }
 }
+
+fn check_binary(
+    cx: &LateContext<'a>,
+    expr: &Expr<'_>,
+    cmp: &rustc_span::source_map::Spanned<rustc_hir::BinOpKind>,
+    left: &'a Expr<'_>,
+    right: &'a Expr<'_>,
+) {
+    let op = cmp.node;
+    if op.is_comparison() {
+        check_nan(cx, left, expr);
+        check_nan(cx, right, expr);
+        check_to_owned(cx, left, right, true);
+        check_to_owned(cx, right, left, false);
+    }
+    if (op == BinOpKind::Eq || op == BinOpKind::Ne) && (is_float(cx, left) || is_float(cx, right)) {
+        if is_allowed(cx, left) || is_allowed(cx, right) {
+            return;
+        }
+
+        // Allow comparing the results of signum()
+        if is_signum(cx, left) && is_signum(cx, right) {
+            return;
+        }
+
+        if let Some(name) = get_item_name(cx, expr) {
+            let name = name.as_str();
+            if name == "eq" || name == "ne" || name == "is_nan" || name.starts_with("eq_") || name.ends_with("_eq") {
+                return;
+            }
+        }
+        let is_comparing_arrays = is_array(cx, left) || is_array(cx, right);
+        let (lint, msg) = get_lint_and_message(
+            is_named_constant(cx, left) || is_named_constant(cx, right),
+            is_comparing_arrays,
+        );
+        span_lint_and_then(cx, lint, expr.span, msg, |diag| {
+            let lhs = Sugg::hir(cx, left, "..");
+            let rhs = Sugg::hir(cx, right, "..");
+
+            if !is_comparing_arrays {
+                diag.span_suggestion(
+                    expr.span,
+                    "consider comparing them within some margin of error",
+                    format!(
+                        "({}).abs() {} error_margin",
+                        lhs - rhs,
+                        if op == BinOpKind::Eq { '<' } else { '>' }
+                    ),
+                    Applicability::HasPlaceholders, // snippet
+                );
+            }
+            diag.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error_margin`");
+        });
+    } else if op == BinOpKind::Rem {
+        if is_integer_const(cx, right, 1) {
+            span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0");
+        }
+
+        if let ty::Int(ity) = cx.typeck_results().expr_ty(right).kind() {
+            if is_integer_const(cx, right, unsext(cx.tcx, -1, *ity)) {
+                span_lint(
+                    cx,
+                    MODULO_ONE,
+                    expr.span,
+                    "any number modulo -1 will panic/overflow or result in 0",
+                );
+            }
+        };
+    }
+}
index a799a644e970e1d3bce83435db28f6576bba5115..42f97b2ac497aa3151bda4f96da00c3a190b9930 100644 (file)
@@ -6,7 +6,6 @@
 use crate::utils::{
     higher, is_expn_of, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg,
 };
-use if_chain::if_chain;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp};
@@ -198,13 +197,9 @@ struct ExpressionInfoWithSpan {
 }
 
 fn is_unary_not(e: &Expr<'_>) -> (bool, Span) {
-    if_chain! {
-        if let ExprKind::Unary(unop, operand) = e.kind;
-        if let UnOp::UnNot = unop;
-        then {
-            return (true, operand.span);
-        }
-    };
+    if let ExprKind::Unary(UnOp::UnNot, operand) = e.kind {
+        return (true, operand.span);
+    }
     (false, e.span)
 }
 
index 31b03ecd101c09daaab92d96f992521fc3cb5166..359620cc079752b806be469b03505d40aa4a2e1f 100644 (file)
@@ -66,7 +66,7 @@
     /// ```
     pub UNREACHABLE,
     restriction,
-    "`unreachable!` should not be present in production code"
+    "usage of the `unreachable!` macro"
 }
 
 declare_lint_pass!(PanicUnimplemented => [UNIMPLEMENTED, UNREACHABLE, TODO, PANIC]);
@@ -85,12 +85,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
             } else if is_expn_of(expr.span, "todo").is_some() {
                 span_lint(cx, TODO, span, "`todo` should not be present in production code");
             } else if is_expn_of(expr.span, "unreachable").is_some() {
-                span_lint(
-                    cx,
-                    UNREACHABLE,
-                    span,
-                    "`unreachable` should not be present in production code",
-                );
+                span_lint(cx, UNREACHABLE, span, "usage of the `unreachable!` macro");
             } else if is_expn_of(expr.span, "panic").is_some() {
                 span_lint(cx, PANIC, span, "`panic` should not be present in production code");
             }
index d9b280b7a85970115456e222755b198428a5db02..b91233ac582808dd7916039fe4c219bf4862634d 100644 (file)
@@ -176,8 +176,7 @@ fn return_expression<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
             if block.stmts.len() == 1;
             if let Some(expr) = block.stmts.iter().last();
             if let StmtKind::Semi(ref expr) = expr.kind;
-            if let ExprKind::Ret(ret_expr) = expr.kind;
-            if let Some(ret_expr) = ret_expr;
+            if let ExprKind::Ret(Some(ret_expr)) = expr.kind;
 
             then {
                 return Some(ret_expr);
index 49cb2ffc4e372a3f765e89e1f9fe4bf0f7740a23..f398b3fff25a328ec6b5d94c249a9e78de88fef5 100644 (file)
@@ -104,7 +104,7 @@ struct ClosureUsageCount<'a, 'tcx> {
                 cx: &'a LateContext<'tcx>,
                 path: &'tcx hir::Path<'tcx>,
                 count: usize,
-            };
+            }
             impl<'a, 'tcx> hir_visit::Visitor<'tcx> for ClosureUsageCount<'a, 'tcx> {
                 type Map = Map<'tcx>;
 
@@ -124,7 +124,7 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
                 fn nested_visit_map(&mut self) -> hir_visit::NestedVisitorMap<Self::Map> {
                     hir_visit::NestedVisitorMap::OnlyBodies(self.cx.tcx.hir())
                 }
-            };
+            }
             let mut closure_usage_count = ClosureUsageCount { cx, path, count: 0 };
             closure_usage_count.visit_block(block);
             closure_usage_count.count
diff --git a/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs b/src/tools/clippy/clippy_lints/src/size_of_in_element_count.rs
new file mode 100644 (file)
index 0000000..ea7a761
--- /dev/null
@@ -0,0 +1,145 @@
+//! Lint on use of `size_of` or `size_of_val` of T in an expression
+//! expecting a count of T
+
+use crate::utils::{match_def_path, paths, span_lint_and_help};
+use if_chain::if_chain;
+use rustc_hir::BinOpKind;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, Ty, TyS, TypeAndMut};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// **What it does:** Detects expressions where
+    /// `size_of::<T>` or `size_of_val::<T>` is used as a
+    /// count of elements of type `T`
+    ///
+    /// **Why is this bad?** These functions expect a count
+    /// of `T` and not a number of bytes
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust,no_run
+    /// # use std::ptr::copy_nonoverlapping;
+    /// # use std::mem::size_of;
+    /// const SIZE: usize = 128;
+    /// let x = [2u8; SIZE];
+    /// let mut y = [2u8; SIZE];
+    /// unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+    /// ```
+    pub SIZE_OF_IN_ELEMENT_COUNT,
+    correctness,
+    "using `size_of::<T>` or `size_of_val::<T>` where a count of elements of `T` is expected"
+}
+
+declare_lint_pass!(SizeOfInElementCount => [SIZE_OF_IN_ELEMENT_COUNT]);
+
+fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Ty<'tcx>> {
+    match expr.kind {
+        ExprKind::Call(count_func, _func_args) => {
+            if_chain! {
+                if let ExprKind::Path(ref count_func_qpath) = count_func.kind;
+                if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id();
+                if match_def_path(cx, def_id, &paths::MEM_SIZE_OF)
+                    || match_def_path(cx, def_id, &paths::MEM_SIZE_OF_VAL);
+                then {
+                    cx.typeck_results().node_substs(count_func.hir_id).types().next()
+                } else {
+                    None
+                }
+            }
+        },
+        ExprKind::Binary(op, left, right) if BinOpKind::Mul == op.node || BinOpKind::Div == op.node => {
+            get_size_of_ty(cx, left).or_else(|| get_size_of_ty(cx, right))
+        },
+        ExprKind::Cast(expr, _) => get_size_of_ty(cx, expr),
+        _ => None,
+    }
+}
+
+fn get_pointee_ty_and_count_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> {
+    const FUNCTIONS: [&[&str]; 8] = [
+        &paths::COPY_NONOVERLAPPING,
+        &paths::COPY,
+        &paths::WRITE_BYTES,
+        &paths::PTR_SWAP_NONOVERLAPPING,
+        &paths::PTR_SLICE_FROM_RAW_PARTS,
+        &paths::PTR_SLICE_FROM_RAW_PARTS_MUT,
+        &paths::SLICE_FROM_RAW_PARTS,
+        &paths::SLICE_FROM_RAW_PARTS_MUT,
+    ];
+    const METHODS: [&str; 11] = [
+        "write_bytes",
+        "copy_to",
+        "copy_from",
+        "copy_to_nonoverlapping",
+        "copy_from_nonoverlapping",
+        "add",
+        "wrapping_add",
+        "sub",
+        "wrapping_sub",
+        "offset",
+        "wrapping_offset",
+    ];
+
+    if_chain! {
+        // Find calls to ptr::{copy, copy_nonoverlapping}
+        // and ptr::{swap_nonoverlapping, write_bytes},
+        if let ExprKind::Call(func, [.., count]) = expr.kind;
+        if let ExprKind::Path(ref func_qpath) = func.kind;
+        if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
+        if FUNCTIONS.iter().any(|func_path| match_def_path(cx, def_id, func_path));
+
+        // Get the pointee type
+        if let Some(pointee_ty) = cx.typeck_results().node_substs(func.hir_id).types().next();
+        then {
+            return Some((pointee_ty, count));
+        }
+    };
+    if_chain! {
+        // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
+        if let ExprKind::MethodCall(method_path, _, [ptr_self, .., count], _) = expr.kind;
+        let method_ident = method_path.ident.as_str();
+        if METHODS.iter().any(|m| *m == &*method_ident);
+
+        // Get the pointee type
+        if let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) =
+            cx.typeck_results().expr_ty(ptr_self).kind();
+        then {
+            return Some((pointee_ty, count));
+        }
+    };
+    None
+}
+
+impl<'tcx> LateLintPass<'tcx> for SizeOfInElementCount {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        const HELP_MSG: &str = "use a count of elements instead of a count of bytes\
+            , it already gets multiplied by the size of the type";
+
+        const LINT_MSG: &str = "found a count of bytes \
+             instead of a count of elements of `T`";
+
+        if_chain! {
+            // Find calls to functions with an element count parameter and get
+            // the pointee type and count parameter expression
+            if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr);
+
+            // Find a size_of call in the count parameter expression and
+            // check that it's the same type
+            if let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr);
+            if TyS::same_type(pointee_ty, ty_used_for_size_of);
+            then {
+                span_lint_and_help(
+                    cx,
+                    SIZE_OF_IN_ELEMENT_COUNT,
+                    count_expr.span,
+                    LINT_MSG,
+                    None,
+                    HELP_MSG
+                );
+            }
+        };
+    }
+}
index ede37624f71a4f1e7364cf4ae70af461c74dacf3..77e790733789c23c061436734afb9b15b5073d2c 100644 (file)
@@ -2,6 +2,7 @@
 use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, LangItem, QPath};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
+use rustc_middle::ty;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::source_map::Spanned;
 use rustc_span::sym;
@@ -11,7 +12,7 @@
 use crate::utils::SpanlessEq;
 use crate::utils::{
     get_parent_expr, is_allowed, is_type_diagnostic_item, match_function_call, method_calls, paths, span_lint,
-    span_lint_and_sugg,
+    span_lint_and_help, span_lint_and_sugg,
 };
 
 declare_clippy_lint! {
@@ -221,8 +222,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
             if method_names[0] == sym!(as_bytes);
 
             // Check for slicer
-            if let ExprKind::Struct(ref path, _, _) = right.kind;
-            if let QPath::LangItem(LangItem::Range, _) = path;
+            if let ExprKind::Struct(QPath::LangItem(LangItem::Range, _), _, _) = right.kind;
 
             then {
                 let mut applicability = Applicability::MachineApplicable;
@@ -289,3 +289,100 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         }
     }
 }
+
+declare_clippy_lint! {
+    /// **What it does:** This lint checks for `.to_string()` method calls on values of type `&str`.
+    ///
+    /// **Why is this bad?** The `to_string` method is also used on other types to convert them to a string.
+    /// When called on a `&str` it turns the `&str` into the owned variant `String`, which can be better
+    /// expressed with `.to_owned()`.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// // example code where clippy issues a warning
+    /// let _ = "str".to_string();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// // example code which does not raise clippy warning
+    /// let _ = "str".to_owned();
+    /// ```
+    pub STR_TO_STRING,
+    restriction,
+    "using `to_string()` on a `&str`, which should be `to_owned()`"
+}
+
+declare_lint_pass!(StrToString => [STR_TO_STRING]);
+
+impl LateLintPass<'_> for StrToString {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
+        if_chain! {
+            if let ExprKind::MethodCall(path, _, args, _) = &expr.kind;
+            if path.ident.name == sym!(to_string);
+            let ty = cx.typeck_results().expr_ty(&args[0]);
+            if let ty::Ref(_, ty, ..) = ty.kind();
+            if *ty.kind() == ty::Str;
+            then {
+                span_lint_and_help(
+                    cx,
+                    STR_TO_STRING,
+                    expr.span,
+                    "`to_string()` called on a `&str`",
+                    None,
+                    "consider using `.to_owned()`",
+                );
+            }
+        }
+    }
+}
+
+declare_clippy_lint! {
+    /// **What it does:** This lint checks for `.to_string()` method calls on values of type `String`.
+    ///
+    /// **Why is this bad?** The `to_string` method is also used on other types to convert them to a string.
+    /// When called on a `String` it only clones the `String`, which can be better expressed with `.clone()`.
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// // example code where clippy issues a warning
+    /// let msg = String::from("Hello World");
+    /// let _ = msg.to_string();
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// // example code which does not raise clippy warning
+    /// let msg = String::from("Hello World");
+    /// let _ = msg.clone();
+    /// ```
+    pub STRING_TO_STRING,
+    restriction,
+    "using `to_string()` on a `String`, which should be `clone()`"
+}
+
+declare_lint_pass!(StringToString => [STRING_TO_STRING]);
+
+impl LateLintPass<'_> for StringToString {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
+        if_chain! {
+            if let ExprKind::MethodCall(path, _, args, _) = &expr.kind;
+            if path.ident.name == sym!(to_string);
+            let ty = cx.typeck_results().expr_ty(&args[0]);
+            if is_type_diagnostic_item(cx, ty, sym!(string_type));
+            then {
+                span_lint_and_help(
+                    cx,
+                    STRING_TO_STRING,
+                    expr.span,
+                    "`to_string()` called on a `String`",
+                    None,
+                    "consider using `.clone()`",
+                );
+            }
+        }
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs b/src/tools/clippy/clippy_lints/src/suspicious_operation_groupings.rs
new file mode 100644 (file)
index 0000000..cccd24c
--- /dev/null
@@ -0,0 +1,693 @@
+use crate::utils::ast_utils::{eq_id, is_useless_with_eq_exprs, IdentIter};
+use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
+use core::ops::{Add, AddAssign};
+use if_chain::if_chain;
+use rustc_ast::ast::{BinOpKind, Expr, ExprKind, StmtKind};
+use rustc_data_structures::fx::FxHashSet;
+use rustc_errors::Applicability;
+use rustc_lint::{EarlyContext, EarlyLintPass};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::source_map::Spanned;
+use rustc_span::symbol::Ident;
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// **What it does:**
+    /// Checks for unlikely usages of binary operators that are almost
+    /// certainly typos and/or copy/paste errors, given the other usages
+    /// of binary operators nearby.
+    /// **Why is this bad?**
+    /// They are probably bugs and if they aren't then they look like bugs
+    /// and you should add a comment explaining why you are doing such an
+    /// odd set of operations.
+    /// **Known problems:**
+    /// There may be some false positives if you are trying to do something
+    /// unusual that happens to look like a typo.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust
+    /// struct Vec3 {
+    ///     x: f64,
+    ///     y: f64,
+    ///     z: f64,
+    /// }
+    ///
+    /// impl Eq for Vec3 {}
+    ///
+    /// impl PartialEq for Vec3 {
+    ///     fn eq(&self, other: &Self) -> bool {
+    ///         // This should trigger the lint because `self.x` is compared to `other.y`
+    ///         self.x == other.y && self.y == other.y && self.z == other.z
+    ///     }
+    /// }
+    /// ```
+    /// Use instead:
+    /// ```rust
+    /// # struct Vec3 {
+    /// #     x: f64,
+    /// #     y: f64,
+    /// #     z: f64,
+    /// # }
+    /// // same as above except:
+    /// impl PartialEq for Vec3 {
+    ///     fn eq(&self, other: &Self) -> bool {
+    ///         // Note we now compare other.x to self.x
+    ///         self.x == other.x && self.y == other.y && self.z == other.z
+    ///     }
+    /// }
+    /// ```
+    pub SUSPICIOUS_OPERATION_GROUPINGS,
+    style,
+    "groupings of binary operations that look suspiciously like typos"
+}
+
+declare_lint_pass!(SuspiciousOperationGroupings => [SUSPICIOUS_OPERATION_GROUPINGS]);
+
+impl EarlyLintPass for SuspiciousOperationGroupings {
+    fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
+        if expr.span.from_expansion() {
+            return;
+        }
+
+        if let Some(binops) = extract_related_binops(&expr.kind) {
+            check_binops(cx, &binops.iter().collect::<Vec<_>>());
+
+            let mut op_types = Vec::with_capacity(binops.len());
+            // We could use a hashmap, etc. to avoid being O(n*m) here, but
+            // we want the lints to be emitted in a consistent order. Besides,
+            // m, (the number of distinct `BinOpKind`s in `binops`)
+            // will often be small, and does have an upper limit.
+            binops.iter().map(|b| b.op).for_each(|op| {
+                if !op_types.contains(&op) {
+                    op_types.push(op);
+                }
+            });
+
+            for op_type in op_types {
+                let ops: Vec<_> = binops.iter().filter(|b| b.op == op_type).collect();
+
+                check_binops(cx, &ops);
+            }
+        }
+    }
+}
+
+fn check_binops(cx: &EarlyContext<'_>, binops: &[&BinaryOp<'_>]) {
+    let binop_count = binops.len();
+    if binop_count < 2 {
+        // Single binary operation expressions would likely be false
+        // positives.
+        return;
+    }
+
+    let mut one_ident_difference_count = 0;
+    let mut no_difference_info = None;
+    let mut double_difference_info = None;
+    let mut expected_ident_loc = None;
+
+    let mut paired_identifiers = FxHashSet::default();
+
+    for (i, BinaryOp { left, right, op, .. }) in binops.iter().enumerate() {
+        match ident_difference_expr(left, right) {
+            IdentDifference::NoDifference => {
+                if is_useless_with_eq_exprs(*op) {
+                    // The `eq_op` lint should catch this in this case.
+                    return;
+                }
+
+                no_difference_info = Some(i);
+            },
+            IdentDifference::Single(ident_loc) => {
+                one_ident_difference_count += 1;
+                if let Some(previous_expected) = expected_ident_loc {
+                    if previous_expected != ident_loc {
+                        // This expression doesn't match the form we're
+                        // looking for.
+                        return;
+                    }
+                } else {
+                    expected_ident_loc = Some(ident_loc);
+                }
+
+                // If there was only a single difference, all other idents
+                // must have been the same, and thus were paired.
+                for id in skip_index(IdentIter::from(*left), ident_loc.index) {
+                    paired_identifiers.insert(id);
+                }
+            },
+            IdentDifference::Double(ident_loc1, ident_loc2) => {
+                double_difference_info = Some((i, ident_loc1, ident_loc2));
+            },
+            IdentDifference::Multiple | IdentDifference::NonIdent => {
+                // It's too hard to know whether this is a bug or not.
+                return;
+            },
+        }
+    }
+
+    let mut applicability = Applicability::MachineApplicable;
+
+    if let Some(expected_loc) = expected_ident_loc {
+        match (no_difference_info, double_difference_info) {
+            (Some(i), None) => attempt_to_emit_no_difference_lint(cx, binops, i, expected_loc),
+            (None, Some((double_difference_index, ident_loc1, ident_loc2))) => {
+                if_chain! {
+                    if one_ident_difference_count == binop_count - 1;
+                    if let Some(binop) = binops.get(double_difference_index);
+                    then {
+                        let changed_loc = if ident_loc1 == expected_loc {
+                            ident_loc2
+                        } else if ident_loc2 == expected_loc {
+                            ident_loc1
+                        } else {
+                            // This expression doesn't match the form we're
+                            // looking for.
+                            return;
+                        };
+
+                        if let Some(sugg) = ident_swap_sugg(
+                            cx,
+                            &paired_identifiers,
+                            binop,
+                            changed_loc,
+                            &mut applicability,
+                        ) {
+                            emit_suggestion(
+                                cx,
+                                binop.span,
+                                sugg,
+                                applicability,
+                            );
+                        }
+                    }
+                }
+            },
+            _ => {},
+        }
+    }
+}
+
+fn attempt_to_emit_no_difference_lint(
+    cx: &EarlyContext<'_>,
+    binops: &[&BinaryOp<'_>],
+    i: usize,
+    expected_loc: IdentLocation,
+) {
+    if let Some(binop) = binops.get(i).cloned() {
+        // We need to try and figure out which identifier we should
+        // suggest using instead. Since there could be multiple
+        // replacement candidates in a given expression, and we're
+        // just taking the first one, we may get some bad lint
+        // messages.
+        let mut applicability = Applicability::MaybeIncorrect;
+
+        // We assume that the correct ident is one used elsewhere in
+        // the other binops, in a place that there was a single
+        // difference between idents before.
+        let old_left_ident = get_ident(binop.left, expected_loc);
+        let old_right_ident = get_ident(binop.right, expected_loc);
+
+        for b in skip_index(binops.iter(), i) {
+            if_chain! {
+                if let (Some(old_ident), Some(new_ident)) =
+                (old_left_ident, get_ident(b.left, expected_loc));
+                if old_ident != new_ident;
+                if let Some(sugg) = suggestion_with_swapped_ident(
+                    cx,
+                    binop.left,
+                    expected_loc,
+                    new_ident,
+                    &mut applicability,
+                );
+                then {
+                    emit_suggestion(
+                        cx,
+                        binop.span,
+                        replace_left_sugg(cx, &binop, &sugg, &mut applicability),
+                        applicability,
+                    );
+                    return;
+                }
+            }
+
+            if_chain! {
+                if let (Some(old_ident), Some(new_ident)) =
+                    (old_right_ident, get_ident(b.right, expected_loc));
+                if old_ident != new_ident;
+                if let Some(sugg) = suggestion_with_swapped_ident(
+                    cx,
+                    binop.right,
+                    expected_loc,
+                    new_ident,
+                    &mut applicability,
+                );
+                then {
+                    emit_suggestion(
+                        cx,
+                        binop.span,
+                        replace_right_sugg(cx, &binop, &sugg, &mut applicability),
+                        applicability,
+                    );
+                    return;
+                }
+            }
+        }
+    }
+}
+
+fn emit_suggestion(cx: &EarlyContext<'_>, span: Span, sugg: String, applicability: Applicability) {
+    span_lint_and_sugg(
+        cx,
+        SUSPICIOUS_OPERATION_GROUPINGS,
+        span,
+        "This sequence of operators looks suspiciously like a bug.",
+        "I think you meant",
+        sugg,
+        applicability,
+    )
+}
+
+fn ident_swap_sugg(
+    cx: &EarlyContext<'_>,
+    paired_identifiers: &FxHashSet<Ident>,
+    binop: &BinaryOp<'_>,
+    location: IdentLocation,
+    applicability: &mut Applicability,
+) -> Option<String> {
+    let left_ident = get_ident(&binop.left, location)?;
+    let right_ident = get_ident(&binop.right, location)?;
+
+    let sugg = match (
+        paired_identifiers.contains(&left_ident),
+        paired_identifiers.contains(&right_ident),
+    ) {
+        (true, true) | (false, false) => {
+            // We don't have a good guess of what ident should be
+            // used instead, in these cases.
+            *applicability = Applicability::MaybeIncorrect;
+
+            // We arbitraily choose one side to suggest changing,
+            // since we don't have a better guess. If the user
+            // ends up duplicating a clause, the `logic_bug` lint
+            // should catch it.
+
+            let right_suggestion =
+                suggestion_with_swapped_ident(cx, &binop.right, location, left_ident, applicability)?;
+
+            replace_right_sugg(cx, binop, &right_suggestion, applicability)
+        },
+        (false, true) => {
+            // We haven't seen a pair involving the left one, so
+            // it's probably what is wanted.
+
+            let right_suggestion =
+                suggestion_with_swapped_ident(cx, &binop.right, location, left_ident, applicability)?;
+
+            replace_right_sugg(cx, binop, &right_suggestion, applicability)
+        },
+        (true, false) => {
+            // We haven't seen a pair involving the right one, so
+            // it's probably what is wanted.
+            let left_suggestion = suggestion_with_swapped_ident(cx, &binop.left, location, right_ident, applicability)?;
+
+            replace_left_sugg(cx, binop, &left_suggestion, applicability)
+        },
+    };
+
+    Some(sugg)
+}
+
+fn replace_left_sugg(
+    cx: &EarlyContext<'_>,
+    binop: &BinaryOp<'_>,
+    left_suggestion: &str,
+    applicability: &mut Applicability,
+) -> String {
+    format!(
+        "{} {} {}",
+        left_suggestion,
+        binop.op.to_string(),
+        snippet_with_applicability(cx, binop.right.span, "..", applicability),
+    )
+}
+
+fn replace_right_sugg(
+    cx: &EarlyContext<'_>,
+    binop: &BinaryOp<'_>,
+    right_suggestion: &str,
+    applicability: &mut Applicability,
+) -> String {
+    format!(
+        "{} {} {}",
+        snippet_with_applicability(cx, binop.left.span, "..", applicability),
+        binop.op.to_string(),
+        right_suggestion,
+    )
+}
+
+#[derive(Clone, Debug)]
+struct BinaryOp<'exprs> {
+    op: BinOpKind,
+    span: Span,
+    left: &'exprs Expr,
+    right: &'exprs Expr,
+}
+
+impl BinaryOp<'exprs> {
+    fn new(op: BinOpKind, span: Span, (left, right): (&'exprs Expr, &'exprs Expr)) -> Self {
+        Self { op, span, left, right }
+    }
+}
+
+fn strip_non_ident_wrappers(expr: &Expr) -> &Expr {
+    let mut output = expr;
+    loop {
+        output = match &output.kind {
+            ExprKind::Paren(ref inner) | ExprKind::Unary(_, ref inner) => inner,
+            _ => {
+                return output;
+            },
+        };
+    }
+}
+
+fn extract_related_binops(kind: &ExprKind) -> Option<Vec<BinaryOp<'_>>> {
+    append_opt_vecs(chained_binops(kind), if_statment_binops(kind))
+}
+
+fn if_statment_binops(kind: &ExprKind) -> Option<Vec<BinaryOp<'_>>> {
+    match kind {
+        ExprKind::If(ref condition, _, _) => chained_binops(&condition.kind),
+        ExprKind::Paren(ref e) => if_statment_binops(&e.kind),
+        ExprKind::Block(ref block, _) => {
+            let mut output = None;
+            for stmt in &block.stmts {
+                match stmt.kind {
+                    StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => {
+                        output = append_opt_vecs(output, if_statment_binops(&e.kind));
+                    },
+                    _ => {},
+                }
+            }
+            output
+        },
+        _ => None,
+    }
+}
+
+fn append_opt_vecs<A>(target_opt: Option<Vec<A>>, source_opt: Option<Vec<A>>) -> Option<Vec<A>> {
+    match (target_opt, source_opt) {
+        (Some(mut target), Some(mut source)) => {
+            target.reserve(source.len());
+            for op in source.drain(..) {
+                target.push(op);
+            }
+            Some(target)
+        },
+        (Some(v), None) | (None, Some(v)) => Some(v),
+        (None, None) => None,
+    }
+}
+
+fn chained_binops(kind: &ExprKind) -> Option<Vec<BinaryOp<'_>>> {
+    match kind {
+        ExprKind::Binary(_, left_outer, right_outer) => chained_binops_helper(left_outer, right_outer),
+        ExprKind::Paren(ref e) | ExprKind::Unary(_, ref e) => chained_binops(&e.kind),
+        _ => None,
+    }
+}
+
+fn chained_binops_helper(left_outer: &'expr Expr, right_outer: &'expr Expr) -> Option<Vec<BinaryOp<'expr>>> {
+    match (&left_outer.kind, &right_outer.kind) {
+        (
+            ExprKind::Paren(ref left_e) | ExprKind::Unary(_, ref left_e),
+            ExprKind::Paren(ref right_e) | ExprKind::Unary(_, ref right_e),
+        ) => chained_binops_helper(left_e, right_e),
+        (ExprKind::Paren(ref left_e) | ExprKind::Unary(_, ref left_e), _) => chained_binops_helper(left_e, right_outer),
+        (_, ExprKind::Paren(ref right_e) | ExprKind::Unary(_, ref right_e)) => {
+            chained_binops_helper(left_outer, right_e)
+        },
+        (
+            ExprKind::Binary(Spanned { node: left_op, .. }, ref left_left, ref left_right),
+            ExprKind::Binary(Spanned { node: right_op, .. }, ref right_left, ref right_right),
+        ) => match (
+            chained_binops_helper(left_left, left_right),
+            chained_binops_helper(right_left, right_right),
+        ) {
+            (Some(mut left_ops), Some(mut right_ops)) => {
+                left_ops.reserve(right_ops.len());
+                for op in right_ops.drain(..) {
+                    left_ops.push(op);
+                }
+                Some(left_ops)
+            },
+            (Some(mut left_ops), _) => {
+                left_ops.push(BinaryOp::new(*right_op, right_outer.span, (right_left, right_right)));
+                Some(left_ops)
+            },
+            (_, Some(mut right_ops)) => {
+                right_ops.insert(0, BinaryOp::new(*left_op, left_outer.span, (left_left, left_right)));
+                Some(right_ops)
+            },
+            (None, None) => Some(vec![
+                BinaryOp::new(*left_op, left_outer.span, (left_left, left_right)),
+                BinaryOp::new(*right_op, right_outer.span, (right_left, right_right)),
+            ]),
+        },
+        _ => None,
+    }
+}
+
+#[derive(Clone, Copy, PartialEq, Eq, Default, Debug)]
+struct IdentLocation {
+    index: usize,
+}
+
+impl Add for IdentLocation {
+    type Output = IdentLocation;
+
+    fn add(self, other: Self) -> Self::Output {
+        Self {
+            index: self.index + other.index,
+        }
+    }
+}
+
+impl AddAssign for IdentLocation {
+    fn add_assign(&mut self, other: Self) {
+        *self = *self + other
+    }
+}
+
+#[derive(Clone, Copy, Debug)]
+enum IdentDifference {
+    NoDifference,
+    Single(IdentLocation),
+    Double(IdentLocation, IdentLocation),
+    Multiple,
+    NonIdent,
+}
+
+impl Add for IdentDifference {
+    type Output = IdentDifference;
+
+    fn add(self, other: Self) -> Self::Output {
+        match (self, other) {
+            (Self::NoDifference, output) | (output, Self::NoDifference) => output,
+            (Self::Multiple, _)
+            | (_, Self::Multiple)
+            | (Self::Double(_, _), Self::Single(_))
+            | (Self::Single(_) | Self::Double(_, _), Self::Double(_, _)) => Self::Multiple,
+            (Self::NonIdent, _) | (_, Self::NonIdent) => Self::NonIdent,
+            (Self::Single(il1), Self::Single(il2)) => Self::Double(il1, il2),
+        }
+    }
+}
+
+impl AddAssign for IdentDifference {
+    fn add_assign(&mut self, other: Self) {
+        *self = *self + other
+    }
+}
+
+impl IdentDifference {
+    /// Returns true if learning about more differences will not change the value
+    /// of this `IdentDifference`, and false otherwise.
+    fn is_complete(&self) -> bool {
+        match self {
+            Self::NoDifference | Self::Single(_) | Self::Double(_, _) => false,
+            Self::Multiple | Self::NonIdent => true,
+        }
+    }
+}
+
+fn ident_difference_expr(left: &Expr, right: &Expr) -> IdentDifference {
+    ident_difference_expr_with_base_location(left, right, IdentLocation::default()).0
+}
+
+fn ident_difference_expr_with_base_location(
+    left: &Expr,
+    right: &Expr,
+    mut base: IdentLocation,
+) -> (IdentDifference, IdentLocation) {
+    // Ideally, this function should not use IdentIter because it should return
+    // early if the expressions have any non-ident differences. We want that early
+    // return because if without that restriction the lint would lead to false
+    // positives.
+    //
+    // But, we cannot (easily?) use a `rustc_ast::visit::Visitor`, since we need
+    // the two expressions to be walked in lockstep. And without a `Visitor`, we'd
+    // have to do all the AST traversal ourselves, which is a lot of work, since to
+    // do it properly we'd need to be able to handle more or less every possible
+    // AST node since `Item`s can be written inside `Expr`s.
+    //
+    // In practice, it seems likely that expressions, above a certain size, that
+    // happen to use the exact same idents in the exact same order, and which are
+    // not structured the same, would be rare. Therefore it seems likely that if
+    // we do only the first layer of matching ourselves and eventually fallback on
+    // IdentIter, then the output of this function will be almost always be correct
+    // in practice.
+    //
+    // If it turns out that problematic cases are more prelavent than we assume,
+    // then we should be able to change this function to do the correct traversal,
+    // without needing to change the rest of the code.
+
+    #![allow(clippy::enum_glob_use)]
+    use ExprKind::*;
+
+    match (
+        &strip_non_ident_wrappers(left).kind,
+        &strip_non_ident_wrappers(right).kind,
+    ) {
+        (Yield(_), Yield(_))
+        | (Try(_), Try(_))
+        | (Paren(_), Paren(_))
+        | (Repeat(_, _), Repeat(_, _))
+        | (Struct(_, _, _), Struct(_, _, _))
+        | (MacCall(_), MacCall(_))
+        | (LlvmInlineAsm(_), LlvmInlineAsm(_))
+        | (InlineAsm(_), InlineAsm(_))
+        | (Ret(_), Ret(_))
+        | (Continue(_), Continue(_))
+        | (Break(_, _), Break(_, _))
+        | (AddrOf(_, _, _), AddrOf(_, _, _))
+        | (Path(_, _), Path(_, _))
+        | (Range(_, _, _), Range(_, _, _))
+        | (Index(_, _), Index(_, _))
+        | (Field(_, _), Field(_, _))
+        | (AssignOp(_, _, _), AssignOp(_, _, _))
+        | (Assign(_, _, _), Assign(_, _, _))
+        | (TryBlock(_), TryBlock(_))
+        | (Await(_), Await(_))
+        | (Async(_, _, _), Async(_, _, _))
+        | (Block(_, _), Block(_, _))
+        | (Closure(_, _, _, _, _, _), Closure(_, _, _, _, _, _))
+        | (Match(_, _), Match(_, _))
+        | (Loop(_, _), Loop(_, _))
+        | (ForLoop(_, _, _, _), ForLoop(_, _, _, _))
+        | (While(_, _, _), While(_, _, _))
+        | (If(_, _, _), If(_, _, _))
+        | (Let(_, _), Let(_, _))
+        | (Type(_, _), Type(_, _))
+        | (Cast(_, _), Cast(_, _))
+        | (Lit(_), Lit(_))
+        | (Unary(_, _), Unary(_, _))
+        | (Binary(_, _, _), Binary(_, _, _))
+        | (Tup(_), Tup(_))
+        | (MethodCall(_, _, _), MethodCall(_, _, _))
+        | (Call(_, _), Call(_, _))
+        | (ConstBlock(_), ConstBlock(_))
+        | (Array(_), Array(_))
+        | (Box(_), Box(_)) => {
+            // keep going
+        },
+        _ => {
+            return (IdentDifference::NonIdent, base);
+        },
+    }
+
+    let mut difference = IdentDifference::NoDifference;
+
+    for (left_attr, right_attr) in left.attrs.iter().zip(right.attrs.iter()) {
+        let (new_difference, new_base) =
+            ident_difference_via_ident_iter_with_base_location(left_attr, right_attr, base);
+        base = new_base;
+        difference += new_difference;
+        if difference.is_complete() {
+            return (difference, base);
+        }
+    }
+
+    let (new_difference, new_base) = ident_difference_via_ident_iter_with_base_location(left, right, base);
+    base = new_base;
+    difference += new_difference;
+
+    (difference, base)
+}
+
+fn ident_difference_via_ident_iter_with_base_location<Iterable: Into<IdentIter>>(
+    left: Iterable,
+    right: Iterable,
+    mut base: IdentLocation,
+) -> (IdentDifference, IdentLocation) {
+    // See the note in `ident_difference_expr_with_base_location` about `IdentIter`
+    let mut difference = IdentDifference::NoDifference;
+
+    let mut left_iterator = left.into();
+    let mut right_iterator = right.into();
+
+    loop {
+        match (left_iterator.next(), right_iterator.next()) {
+            (Some(left_ident), Some(right_ident)) => {
+                if !eq_id(left_ident, right_ident) {
+                    difference += IdentDifference::Single(base);
+                    if difference.is_complete() {
+                        return (difference, base);
+                    }
+                }
+            },
+            (Some(_), None) | (None, Some(_)) => {
+                return (IdentDifference::NonIdent, base);
+            },
+            (None, None) => {
+                return (difference, base);
+            },
+        }
+        base += IdentLocation { index: 1 };
+    }
+}
+
+fn get_ident(expr: &Expr, location: IdentLocation) -> Option<Ident> {
+    IdentIter::from(expr).nth(location.index)
+}
+
+fn suggestion_with_swapped_ident(
+    cx: &EarlyContext<'_>,
+    expr: &Expr,
+    location: IdentLocation,
+    new_ident: Ident,
+    applicability: &mut Applicability,
+) -> Option<String> {
+    get_ident(expr, location).and_then(|current_ident| {
+        if eq_id(current_ident, new_ident) {
+            // We never want to suggest a non-change
+            return None;
+        }
+
+        Some(format!(
+            "{}{}{}",
+            snippet_with_applicability(cx, expr.span.with_hi(current_ident.span.lo()), "..", applicability),
+            new_ident.to_string(),
+            snippet_with_applicability(cx, expr.span.with_lo(current_ident.span.hi()), "..", applicability),
+        ))
+    })
+}
+
+fn skip_index<A, Iter>(iter: Iter, index: usize) -> impl Iterator<Item = A>
+where
+    Iter: Iterator<Item = A>,
+{
+    iter.enumerate()
+        .filter_map(move |(i, a)| if i == index { None } else { Some(a) })
+}
index d4acf8df46d8a5323d64613c38de7ef7abbb8dd1..daff5f81e8c34c926a830089025eff5294a7d540 100644 (file)
@@ -168,8 +168,7 @@ fn check_trait_bound_duplication(cx: &LateContext<'_>, gen: &'_ Generics<'_>) {
         if_chain! {
             if let WherePredicate::BoundPredicate(ref bound_predicate) = predicate;
             if !in_macro(bound_predicate.span);
-            if let TyKind::Path(ref path) = bound_predicate.bounded_ty.kind;
-            if let QPath::Resolved(_, Path { ref segments, .. }) = path;
+            if let TyKind::Path(QPath::Resolved(_, Path { ref segments, .. })) = bound_predicate.bounded_ty.kind;
             if let Some(segment) = segments.first();
             if let Some(trait_resolutions_direct) = map.get(&segment.ident);
             then {
index d60306336c6e6a956d42d15f8d6a98f068eeddd0..6b171a0fa1af2ef2058f402837237f957153908f 100644 (file)
@@ -48,8 +48,7 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
                 if_chain! {
                     if let ExprKind::Path(ref _qpath) = args[0].kind;
                     let x = const_eval_context.expr(&args[0]);
-                    if let Some(constant) = x;
-                    if let Constant::RawPtr(0) = constant;
+                    if let Some(Constant::RawPtr(0)) = x;
                     then {
                         span_lint(cx, TRANSMUTING_NULL, expr.span, LINT_MSG)
                     }
index f0e10e374e1182bc472c3f54b0209371ccc4543d..74ba53e6a9a02fbd9c7f90b63ed72e8d58ea00c9 100644 (file)
@@ -8,6 +8,7 @@
 use rustc_ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy};
 use rustc_errors::{Applicability, DiagnosticBuilder};
 use rustc_hir as hir;
+use rustc_hir::def::Res;
 use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
 use rustc_hir::{
     BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericBounds, GenericParamKind, HirId,
@@ -737,8 +738,7 @@ fn is_any_trait(t: &hir::Ty<'_>) -> bool {
 fn get_bounds_if_impl_trait<'tcx>(cx: &LateContext<'tcx>, qpath: &QPath<'_>, id: HirId) -> Option<GenericBounds<'tcx>> {
     if_chain! {
         if let Some(did) = qpath_res(cx, qpath, id).opt_def_id();
-        if let Some(node) = cx.tcx.hir().get_if_local(did);
-        if let Node::GenericParam(generic_param) = node;
+        if let Some(Node::GenericParam(generic_param)) = cx.tcx.hir().get_if_local(did);
         if let GenericParamKind::Type { synthetic, .. } = generic_param.kind;
         if synthetic == Some(SyntheticTyParamKind::ImplTrait);
         then {
@@ -1469,8 +1469,7 @@ fn check_loss_of_sign(cx: &LateContext<'_>, expr: &Expr<'_>, op: &Expr<'_>, cast
     // don't lint for positive constants
     let const_val = constant(cx, &cx.typeck_results(), op);
     if_chain! {
-        if let Some((const_val, _)) = const_val;
-        if let Constant::Int(n) = const_val;
+        if let Some((Constant::Int(n), _)) = const_val;
         if let ty::Int(ity) = *cast_from.kind();
         if sext(cx.tcx, n, ity) >= 0;
         then {
@@ -1632,7 +1631,14 @@ fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
         if expr.span.from_expansion() {
             return;
         }
-        if let ExprKind::Cast(ref ex, _) = expr.kind {
+        if let ExprKind::Cast(ref ex, cast_to) = expr.kind {
+            if let TyKind::Path(QPath::Resolved(_, path)) = cast_to.kind {
+                if let Res::Def(_, def_id) = path.res {
+                    if cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr) {
+                        return;
+                    }
+                }
+            }
             let (cast_from, cast_to) = (cx.typeck_results().expr_ty(ex), cx.typeck_results().expr_ty(expr));
             lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to);
             if let Some(lit) = get_numeric_literal(ex) {
@@ -1711,7 +1717,7 @@ fn show_unnecessary_cast(cx: &LateContext<'_>, expr: &Expr<'_>, literal_str: &st
         expr.span,
         &format!("casting {} literal to `{}` is unnecessary", literal_kind_name, cast_to),
         "try",
-        format!("{}_{}", literal_str, cast_to),
+        format!("{}_{}", literal_str.trim_end_matches('.'), cast_to),
         Applicability::MachineApplicable,
     );
 }
index 25ecc7a82f18bfac868785558093879f5de0c2b6..5d801511a0b185b32af9e40816f1fc6a68cfd42c 100644 (file)
@@ -1,5 +1,5 @@
 use crate::utils::{
-    in_macro, is_type_diagnostic_item, match_qpath, paths, return_ty, snippet, span_lint_and_then,
+    contains_return, in_macro, is_type_diagnostic_item, match_qpath, paths, return_ty, snippet, span_lint_and_then,
     visitors::find_all_ret_expressions,
 };
 use if_chain::if_chain;
@@ -95,6 +95,7 @@ fn check_fn(
                 if let ExprKind::Path(ref qpath) = func.kind;
                 if match_qpath(qpath, path);
                 if args.len() == 1;
+                if !contains_return(&args[0]);
                 then {
                     suggs.push((ret_expr.span, snippet(cx, args[0].span.source_callsite(), "..").to_string()));
                     true
@@ -134,7 +135,7 @@ fn check_fn(
                     diag.multipart_suggestion(
                         "...and change the returning expressions",
                         suggs,
-                        Applicability::MachineApplicable,
+                        Applicability::MaybeIncorrect,
                     );
                 },
             );
index fcf7a4b1367e3c4086bf6edeabe3faa519e3f948..31b4e25411bd39ba24a2aa927d4c28259e24a405 100644 (file)
 use rustc_span::symbol::Ident;
 use std::mem;
 
+pub mod ident_iter;
+pub use ident_iter::IdentIter;
+
+pub fn is_useless_with_eq_exprs(kind: BinOpKind) -> bool {
+    use BinOpKind::*;
+    matches!(
+        kind,
+        Sub | Div | Eq | Lt | Le | Gt | Ge | Ne | And | Or | BitXor | BitAnd | BitOr
+    )
+}
+
 /// Checks if each element in the first slice is contained within the latter as per `eq_fn`.
 pub fn unordered_over<X>(left: &[X], right: &[X], mut eq_fn: impl FnMut(&X, &X) -> bool) -> bool {
     left.len() == right.len() && left.iter().all(|l| right.iter().any(|r| eq_fn(l, r)))
diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils/ident_iter.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils/ident_iter.rs
new file mode 100644 (file)
index 0000000..eefcbab
--- /dev/null
@@ -0,0 +1,45 @@
+use core::iter::FusedIterator;
+use rustc_ast::visit::{walk_attribute, walk_expr, Visitor};
+use rustc_ast::{Attribute, Expr};
+use rustc_span::symbol::Ident;
+
+pub struct IdentIter(std::vec::IntoIter<Ident>);
+
+impl Iterator for IdentIter {
+    type Item = Ident;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        self.0.next()
+    }
+}
+
+impl FusedIterator for IdentIter {}
+
+impl From<&Expr> for IdentIter {
+    fn from(expr: &Expr) -> Self {
+        let mut visitor = IdentCollector::default();
+
+        walk_expr(&mut visitor, expr);
+
+        IdentIter(visitor.0.into_iter())
+    }
+}
+
+impl From<&Attribute> for IdentIter {
+    fn from(attr: &Attribute) -> Self {
+        let mut visitor = IdentCollector::default();
+
+        walk_attribute(&mut visitor, attr);
+
+        IdentIter(visitor.0.into_iter())
+    }
+}
+
+#[derive(Default)]
+struct IdentCollector(Vec<Ident>);
+
+impl Visitor<'_> for IdentCollector {
+    fn visit_ident(&mut self, ident: Ident) {
+        self.0.push(ident);
+    }
+}
index e6d41341a55f3bbd5666eee9963afc849dec97cb..24052a243af8245bf8c86e0408e7db4366c71751 100644 (file)
@@ -21,6 +21,7 @@ pub enum DeprecationStatus {
         DeprecationStatus::Replaced("cognitive_complexity"),
     ),
     ("dump", DeprecationStatus::None),
+    ("msrv", DeprecationStatus::None),
 ];
 
 pub struct LimitStack {
@@ -123,6 +124,24 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &'
     }
 }
 
+pub fn get_unique_inner_attr(sess: &Session, attrs: &[ast::Attribute], name: &'static str) -> Option<ast::Attribute> {
+    let mut unique_attr = None;
+    for attr in get_attr(sess, attrs, name) {
+        match attr.style {
+            ast::AttrStyle::Inner if unique_attr.is_none() => unique_attr = Some(attr.clone()),
+            ast::AttrStyle::Inner => {
+                sess.struct_span_err(attr.span, &format!("`{}` is defined multiple times", name))
+                    .span_note(unique_attr.as_ref().unwrap().span, "first definition found here")
+                    .emit();
+            },
+            ast::AttrStyle::Outer => {
+                sess.span_err(attr.span, &format!("`{}` cannot be an outer attribute", name));
+            },
+        }
+    }
+    unique_attr
+}
+
 /// Return true if the attributes contain any of `proc_macro`,
 /// `proc_macro_derive` or `proc_macro_attribute`, false otherwise
 pub fn is_proc_macro(sess: &Session, attrs: &[ast::Attribute]) -> bool {
index 0ac8fff69f05742f241109b52959341813bb2922..6403ff6dad18561700b83f447ce6116935b1034b 100644 (file)
@@ -106,6 +106,8 @@ fn $config() -> $Ty {
 
 pub use self::helpers::Conf;
 define_Conf! {
+    /// Lint: MANUAL_NON_EXHAUSTIVE, MANUAL_STRIP, OPTION_AS_REF_DEREF, MATCH_LIKE_MATCHES_MACRO. The minimum rust version that the project supports
+    (msrv, "msrv": Option<String>, None),
     /// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about. NB: `bar` is not here since it has legitimate uses
     (blacklisted_names, "blacklisted_names": Vec<String>, ["foo", "baz", "quux"].iter().map(ToString::to_string).collect()),
     /// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have
@@ -168,6 +170,8 @@ fn $config() -> $Ty {
     (warn_on_all_wildcard_imports, "warn_on_all_wildcard_imports": bool, false),
     /// Lint: DISALLOWED_METHOD. The list of blacklisted methods to lint about. NB: `bar` is not here since it has legitimate uses
     (disallowed_methods, "disallowed_methods": Vec<String>, Vec::<String>::new()),
+    /// Lint: UNREADABLE_LITERAL. Should the fraction of a decimal be linted to include separators.
+    (unreadable_literal_lint_fractions, "unreadable_literal_lint_fractions": bool, true),
 }
 
 impl Default for Conf {
index 0a58231558ede21304bf1ecc9f4b7cd1e60d29b5..a7a6b5855b754948957f7ce187261ac685303f37 100644 (file)
@@ -186,7 +186,9 @@ pub fn span_lint_hir_and_then(
 ///     |
 ///     = note: `-D fold-any` implied by `-D warnings`
 /// ```
-#[allow(clippy::collapsible_span_lint_calls)]
+
+#[allow(clippy::unknown_clippy_lints)]
+#[cfg_attr(feature = "internal-lints", allow(clippy::collapsible_span_lint_calls))]
 pub fn span_lint_and_sugg<'a, T: LintContext>(
     cx: &'a T,
     lint: &'static Lint,
index 6d7c5058b4f30eee27114d4b532dec5e2a690af2..01ffac5b5599d547dee26056a8f549b574e3a799 100644 (file)
@@ -162,8 +162,7 @@ pub fn while_loop<'tcx>(expr: &'tcx hir::Expr<'tcx>) -> Option<(&'tcx hir::Expr<
         if let hir::Block { expr: Some(expr), .. } = &**block;
         if let hir::ExprKind::Match(cond, arms, hir::MatchSource::WhileDesugar) = &expr.kind;
         if let hir::ExprKind::DropTemps(cond) = &cond.kind;
-        if let [arm, ..] = &arms[..];
-        if let hir::Arm { body, .. } = arm;
+        if let [hir::Arm { body, .. }, ..] = &arms[..];
         then {
             return Some((cond, body));
         }
index e4ad105c3513e3f5c3539c4a5e23eb689544a465..d942d4e12b10629518cf54d5fac19c97281e1e37 100644 (file)
@@ -81,7 +81,7 @@ pub fn eq_expr(&mut self, left: &Expr<'_>, right: &Expr<'_>) -> bool {
             }
         }
 
-        match (&left.kind, &right.kind) {
+        match (&reduce_exprkind(&left.kind), &reduce_exprkind(&right.kind)) {
             (&ExprKind::AddrOf(lb, l_mut, ref le), &ExprKind::AddrOf(rb, r_mut, ref re)) => {
                 lb == rb && l_mut == r_mut && self.eq_expr(le, re)
             },
@@ -306,6 +306,32 @@ fn eq_type_binding(&mut self, left: &TypeBinding<'_>, right: &TypeBinding<'_>) -
     }
 }
 
+/// Some simple reductions like `{ return }` => `return`
+fn reduce_exprkind<'hir>(kind: &'hir ExprKind<'hir>) -> &ExprKind<'hir> {
+    if let ExprKind::Block(block, _) = kind {
+        match (block.stmts, block.expr) {
+            // `{}` => `()`
+            ([], None) => &ExprKind::Tup(&[]),
+            ([], Some(expr)) => match expr.kind {
+                // `{ return .. }` => `return ..`
+                ExprKind::Ret(..) => &expr.kind,
+                _ => kind,
+            },
+            ([stmt], None) => match stmt.kind {
+                StmtKind::Expr(expr) | StmtKind::Semi(expr) => match expr.kind {
+                    // `{ return ..; }` => `return ..`
+                    ExprKind::Ret(..) => &expr.kind,
+                    _ => kind,
+                },
+                _ => kind,
+            },
+            _ => kind,
+        }
+    } else {
+        kind
+    }
+}
+
 fn swap_binop<'a>(
     binop: BinOpKind,
     lhs: &'a Expr<'a>,
@@ -491,7 +517,7 @@ pub fn hash_expr(&mut self, e: &Expr<'_>) {
                     }
                 }
                 asm.options.hash(&mut self.s);
-                for op in asm.operands {
+                for (op, _op_sp) in asm.operands {
                     match op {
                         InlineAsmOperand::In { reg, expr } => {
                             reg.hash(&mut self.s);
index 8f0ef9150d4503824677526c68155c243d617b97..323d8745538859bf7e4e106bdec3ed0151d322f3 100644 (file)
@@ -293,7 +293,7 @@ fn print_expr(cx: &LateContext<'_>, expr: &hir::Expr<'_>, indent: usize) {
             println!("{}template: {}", ind, InlineAsmTemplatePiece::to_string(asm.template));
             println!("{}options: {:?}", ind, asm.options);
             println!("{}operands:", ind);
-            for op in asm.operands {
+            for (op, _op_sp) in asm.operands {
                 match op {
                     hir::InlineAsmOperand::In { expr, .. }
                     | hir::InlineAsmOperand::InOut { expr, .. }
index e9c71e23a670b2c2997dd4e6f2ebbd7760dd157a..3a6b64c90e8f65ef4634ecc7197f2275af7017c9 100644 (file)
@@ -14,6 +14,7 @@
 pub mod higher;
 mod hir_utils;
 pub mod inspector;
+#[cfg(feature = "internal-lints")]
 pub mod internal_lints;
 pub mod numeric_literal;
 pub mod paths;
@@ -51,6 +52,8 @@
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
 use rustc_middle::ty::{self, layout::IntegerExt, Ty, TyCtxt, TypeFoldable};
+use rustc_semver::RustcVersion;
+use rustc_session::Session;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::original_sp;
 use rustc_span::sym as rustc_sym;
 
 use crate::consts::{constant, Constant};
 
+pub fn parse_msrv(msrv: &str, sess: Option<&Session>, span: Option<Span>) -> Option<RustcVersion> {
+    if let Ok(version) = RustcVersion::parse(msrv) {
+        return Some(version);
+    } else if let Some(sess) = sess {
+        if let Some(span) = span {
+            sess.span_err(span, &format!("`{}` is not a valid Rust version", msrv));
+        }
+    }
+    None
+}
+
+pub fn meets_msrv(msrv: Option<&RustcVersion>, lint_msrv: &RustcVersion) -> bool {
+    msrv.map_or(true, |msrv| msrv.meets(*lint_msrv))
+}
+
+macro_rules! extract_msrv_attr {
+    (LateContext) => {
+        extract_msrv_attr!(@LateContext, ());
+    };
+    (EarlyContext) => {
+        extract_msrv_attr!(@EarlyContext);
+    };
+    (@$context:ident$(, $call:tt)?) => {
+        fn enter_lint_attrs(&mut self, cx: &rustc_lint::$context<'tcx>, attrs: &'tcx [rustc_ast::ast::Attribute]) {
+            use $crate::utils::get_unique_inner_attr;
+            match get_unique_inner_attr(cx.sess$($call)?, attrs, "msrv") {
+                Some(msrv_attr) => {
+                    if let Some(msrv) = msrv_attr.value_str() {
+                        self.msrv = $crate::utils::parse_msrv(
+                            &msrv.to_string(),
+                            Some(cx.sess$($call)?),
+                            Some(msrv_attr.span),
+                        );
+                    } else {
+                        cx.sess$($call)?.span_err(msrv_attr.span, "bad clippy attribute");
+                    }
+                },
+                _ => (),
+            }
+        }
+    };
+}
+
 /// Returns `true` if the two spans come from differing expansions (i.e., one is
 /// from a macro and one isn't).
 #[must_use]
@@ -527,6 +573,36 @@ pub fn contains_name(name: Symbol, expr: &Expr<'_>) -> bool {
     cn.result
 }
 
+/// Returns `true` if `expr` contains a return expression
+pub fn contains_return(expr: &hir::Expr<'_>) -> bool {
+    struct RetCallFinder {
+        found: bool,
+    }
+
+    impl<'tcx> hir::intravisit::Visitor<'tcx> for RetCallFinder {
+        type Map = Map<'tcx>;
+
+        fn visit_expr(&mut self, expr: &'tcx hir::Expr<'_>) {
+            if self.found {
+                return;
+            }
+            if let hir::ExprKind::Ret(..) = &expr.kind {
+                self.found = true;
+            } else {
+                hir::intravisit::walk_expr(self, expr);
+            }
+        }
+
+        fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
+            hir::intravisit::NestedVisitorMap::None
+        }
+    }
+
+    let mut visitor = RetCallFinder { found: false };
+    visitor.visit_expr(expr);
+    visitor.found
+}
+
 /// Converts a span to a code snippet if available, otherwise use default.
 ///
 /// This is useful if you want to provide suggestions for your lint or more generally, if you want
index 137f5d18b6649d0ae26d8694b863e9e907e72b6d..6fdc7b4587f049c207f4fff45760fd5cd3e17419 100644 (file)
@@ -20,6 +20,8 @@
 pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
 pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"];
 pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"];
+pub const COPY: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
+pub const COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy"];
 pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
 pub const CSTRING_AS_C_STR: [&str; 5] = ["std", "ffi", "c_str", "CString", "as_c_str"];
 pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
@@ -31,6 +33,7 @@
 pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleEndedIterator"];
 pub const DROP: [&str; 3] = ["core", "mem", "drop"];
 pub const DURATION: [&str; 3] = ["core", "time", "Duration"];
+#[cfg(feature = "internal-lints")]
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 pub const EXIT: [&str; 3] = ["std", "process", "exit"];
 pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
 pub const INTO_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "IntoIterator"];
 pub const IO_READ: [&str; 3] = ["std", "io", "Read"];
 pub const IO_WRITE: [&str; 3] = ["std", "io", "Write"];
+pub const IPADDR_V4: [&str; 4] = ["std", "net", "IpAddr", "V4"];
+pub const IPADDR_V6: [&str; 4] = ["std", "net", "IpAddr", "V6"];
 pub const ITERATOR: [&str; 5] = ["core", "iter", "traits", "iterator", "Iterator"];
+#[cfg(feature = "internal-lints")]
 pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
 pub const LINKED_LIST: [&str; 4] = ["alloc", "collections", "linked_list", "LinkedList"];
+#[cfg(feature = "internal-lints")]
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
 pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"];
 pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"];
@@ -68,6 +75,8 @@
 pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"];
 pub const MEM_MAYBEUNINIT_UNINIT: [&str; 5] = ["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"];
 pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"];
+pub const MEM_SIZE_OF: [&str; 3] = ["core", "mem", "size_of"];
+pub const MEM_SIZE_OF_VAL: [&str; 3] = ["core", "mem", "size_of_val"];
 pub const MUTEX_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"];
 pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
 pub const OPS_MODULE: [&str; 2] = ["core", "ops"];
 pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
 pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
 pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"];
+pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"];
+pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];
 pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
 pub const PTR_NULL: [&str; 3] = ["core", "ptr", "null"];
 pub const PTR_NULL_MUT: [&str; 3] = ["core", "ptr", "null_mut"];
+pub const PTR_SLICE_FROM_RAW_PARTS: [&str; 3] = ["core", "ptr", "slice_from_raw_parts"];
+pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_raw_parts_mut"];
+pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"];
 pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
 pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
 pub const RC: [&str; 3] = ["alloc", "rc", "Rc"];
 pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"];
 pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
+pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
+pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"];
 pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
 pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"];
 pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
 pub const STR_FROM_UTF8: [&str; 4] = ["core", "str", "converts", "from_utf8"];
 pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
 pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
+#[cfg(feature = "internal-lints")]
 pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
 pub const TO_OWNED: [&str; 3] = ["alloc", "borrow", "ToOwned"];
 pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"];
 pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"];
 pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"];
 pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"];
+pub const WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"];
index b0837b6c43e76dc3f9bbdaf80ad15bc7bf0039c6..28b3e79d7a6d6d9646edbb7804d1ddf6fad3a3d3 100644 (file)
@@ -1,5 +1,7 @@
 use rustc_hir as hir;
-use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::def::Res;
+use rustc_hir::intravisit::{self, walk_expr, NestedVisitorMap, Visitor};
+use rustc_hir::{Arm, Expr, ExprKind, HirId, QPath, Stmt};
 use rustc_lint::LateContext;
 use rustc_middle::hir::map::Map;
 
@@ -123,3 +125,54 @@ fn visit_expr(&mut self, expr: &'hir hir::Expr<'_>) {
         !ret_finder.failed
     }
 }
+
+pub struct LocalUsedVisitor {
+    pub local_hir_id: HirId,
+    pub used: bool,
+}
+
+impl LocalUsedVisitor {
+    pub fn new(local_hir_id: HirId) -> Self {
+        Self {
+            local_hir_id,
+            used: false,
+        }
+    }
+
+    fn check<T>(&mut self, t: T, visit: fn(&mut Self, T)) -> bool {
+        visit(self, t);
+        std::mem::replace(&mut self.used, false)
+    }
+
+    pub fn check_arm(&mut self, arm: &Arm<'_>) -> bool {
+        self.check(arm, Self::visit_arm)
+    }
+
+    pub fn check_expr(&mut self, expr: &Expr<'_>) -> bool {
+        self.check(expr, Self::visit_expr)
+    }
+
+    pub fn check_stmt(&mut self, stmt: &Stmt<'_>) -> bool {
+        self.check(stmt, Self::visit_stmt)
+    }
+}
+
+impl<'v> Visitor<'v> for LocalUsedVisitor {
+    type Map = Map<'v>;
+
+    fn visit_expr(&mut self, expr: &'v Expr<'v>) {
+        if let ExprKind::Path(QPath::Resolved(None, path)) = expr.kind {
+            if let Res::Local(id) = path.res {
+                if id == self.local_hir_id {
+                    self.used = true;
+                    return;
+                }
+            }
+        }
+        walk_expr(self, expr);
+    }
+
+    fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
+        NestedVisitorMap::None
+    }
+}
index 0e8f7683103d61296a99190414cc52ae4e3a5ec6..ec3af94b9ca910dd293b807638ddd015f49dd336 100644 (file)
@@ -12,6 +12,9 @@
 
 mod cargo;
 
+// whether to run internal tests or not
+const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal-lints");
+
 fn host_lib() -> PathBuf {
     option_env!("HOST_LIBS").map_or(cargo::CARGO_TARGET_DIR.join(env!("PROFILE")), PathBuf::from)
 }
@@ -96,6 +99,16 @@ fn run_mode(cfg: &mut compiletest::Config) {
     compiletest::run_tests(&cfg);
 }
 
+fn run_internal_tests(cfg: &mut compiletest::Config) {
+    // only run internal tests with the internal-tests feature
+    if !RUN_INTERNAL_TESTS {
+        return;
+    }
+    cfg.mode = TestMode::Ui;
+    cfg.src_base = Path::new("tests").join("ui-internal");
+    compiletest::run_tests(&cfg);
+}
+
 fn run_ui_toml(config: &mut compiletest::Config) {
     fn run_tests(config: &compiletest::Config, mut tests: Vec<tester::TestDescAndFn>) -> Result<bool, io::Error> {
         let mut result = true;
@@ -199,7 +212,6 @@ fn run_tests(
                         Some("main.rs") => {},
                         _ => continue,
                     }
-
                     let paths = compiletest::common::TestPaths {
                         file: file_path,
                         base: config.src_base.clone(),
@@ -253,4 +265,5 @@ fn compile_test() {
     run_mode(&mut config);
     run_ui_toml(&mut config);
     run_ui_cargo(&mut config);
+    run_internal_tests(&mut config);
 }
index 48e0478f16992275309baa6505e88395c32b143c..a6163a83d768709a562ca5a59a98b4eb92857bf4 100644 (file)
@@ -18,7 +18,8 @@ fn dogfood_clippy() {
     }
     let root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
 
-    let output = Command::new(&*CLIPPY_PATH)
+    let mut command = Command::new(&*CLIPPY_PATH);
+    command
         .current_dir(root_dir)
         .env("CLIPPY_DOGFOOD", "1")
         .env("CARGO_INCREMENTAL", "0")
@@ -27,11 +28,16 @@ fn dogfood_clippy() {
         .arg("--all-features")
         .arg("--")
         .args(&["-D", "clippy::all"])
-        .args(&["-D", "clippy::internal"])
         .args(&["-D", "clippy::pedantic"])
-        .arg("-Cdebuginfo=0") // disable debuginfo to generate less data in the target dir
-        .output()
-        .unwrap();
+        .arg("-Cdebuginfo=0"); // disable debuginfo to generate less data in the target dir
+
+    // internal lints only exist if we build with the internal-lints feature
+    if cfg!(feature = "internal-lints") {
+        command.args(&["-D", "clippy::internal"]);
+    }
+
+    let output = command.output().unwrap();
+
     println!("status: {}", output.status);
     println!("stdout: {}", String::from_utf8_lossy(&output.stdout));
     println!("stderr: {}", String::from_utf8_lossy(&output.stderr));
diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.fixed
new file mode 100644 (file)
index 0000000..e588c23
--- /dev/null
@@ -0,0 +1,91 @@
+// run-rustfix
+#![deny(clippy::internal)]
+#![feature(rustc_private)]
+
+extern crate rustc_ast;
+extern crate rustc_errors;
+extern crate rustc_lint;
+extern crate rustc_session;
+extern crate rustc_span;
+
+use rustc_ast::ast::Expr;
+use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::source_map::Span;
+
+#[allow(unused_variables)]
+pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F)
+where
+    F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>),
+{
+}
+
+#[allow(unused_variables)]
+fn span_lint_and_help<'a, T: LintContext>(
+    cx: &'a T,
+    lint: &'static Lint,
+    span: Span,
+    msg: &str,
+    option_span: Option<Span>,
+    help: &str,
+) {
+}
+
+#[allow(unused_variables)]
+fn span_lint_and_note<'a, T: LintContext>(
+    cx: &'a T,
+    lint: &'static Lint,
+    span: Span,
+    msg: &str,
+    note_span: Option<Span>,
+    note: &str,
+) {
+}
+
+#[allow(unused_variables)]
+fn span_lint_and_sugg<'a, T: LintContext>(
+    cx: &'a T,
+    lint: &'static Lint,
+    sp: Span,
+    msg: &str,
+    help: &str,
+    sugg: String,
+    applicability: Applicability,
+) {
+}
+
+declare_tool_lint! {
+    pub clippy::TEST_LINT,
+    Warn,
+    "",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(Pass => [TEST_LINT]);
+
+impl EarlyLintPass for Pass {
+    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
+        let lint_msg = "lint message";
+        let help_msg = "help message";
+        let note_msg = "note message";
+        let sugg = "new_call()";
+        let predicate = true;
+
+        span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable);
+        span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg);
+        span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg);
+        span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg);
+        span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg);
+
+        // This expr shouldn't trigger this lint.
+        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+            db.note(note_msg);
+            if predicate {
+                db.note(note_msg);
+            }
+        })
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.rs
new file mode 100644 (file)
index 0000000..d5dd3bb
--- /dev/null
@@ -0,0 +1,101 @@
+// run-rustfix
+#![deny(clippy::internal)]
+#![feature(rustc_private)]
+
+extern crate rustc_ast;
+extern crate rustc_errors;
+extern crate rustc_lint;
+extern crate rustc_session;
+extern crate rustc_span;
+
+use rustc_ast::ast::Expr;
+use rustc_errors::{Applicability, DiagnosticBuilder};
+use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+use rustc_span::source_map::Span;
+
+#[allow(unused_variables)]
+pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F)
+where
+    F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>),
+{
+}
+
+#[allow(unused_variables)]
+fn span_lint_and_help<'a, T: LintContext>(
+    cx: &'a T,
+    lint: &'static Lint,
+    span: Span,
+    msg: &str,
+    option_span: Option<Span>,
+    help: &str,
+) {
+}
+
+#[allow(unused_variables)]
+fn span_lint_and_note<'a, T: LintContext>(
+    cx: &'a T,
+    lint: &'static Lint,
+    span: Span,
+    msg: &str,
+    note_span: Option<Span>,
+    note: &str,
+) {
+}
+
+#[allow(unused_variables)]
+fn span_lint_and_sugg<'a, T: LintContext>(
+    cx: &'a T,
+    lint: &'static Lint,
+    sp: Span,
+    msg: &str,
+    help: &str,
+    sugg: String,
+    applicability: Applicability,
+) {
+}
+
+declare_tool_lint! {
+    pub clippy::TEST_LINT,
+    Warn,
+    "",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(Pass => [TEST_LINT]);
+
+impl EarlyLintPass for Pass {
+    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
+        let lint_msg = "lint message";
+        let help_msg = "help message";
+        let note_msg = "note message";
+        let sugg = "new_call()";
+        let predicate = true;
+
+        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+            db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable);
+        });
+        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+            db.span_help(expr.span, help_msg);
+        });
+        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+            db.help(help_msg);
+        });
+        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+            db.span_note(expr.span, note_msg);
+        });
+        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+            db.note(note_msg);
+        });
+
+        // This expr shouldn't trigger this lint.
+        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+            db.note(note_msg);
+            if predicate {
+                db.note(note_msg);
+            }
+        })
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr b/src/tools/clippy/tests/ui-internal/collapsible_span_lint_calls.stderr
new file mode 100644 (file)
index 0000000..874d4a9
--- /dev/null
@@ -0,0 +1,49 @@
+error: this call is collapsible
+  --> $DIR/collapsible_span_lint_calls.rs:75:9
+   |
+LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+LL | |             db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable);
+LL | |         });
+   | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable)`
+   |
+note: the lint level is defined here
+  --> $DIR/collapsible_span_lint_calls.rs:2:9
+   |
+LL | #![deny(clippy::internal)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]`
+
+error: this call is collapsible
+  --> $DIR/collapsible_span_lint_calls.rs:78:9
+   |
+LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+LL | |             db.span_help(expr.span, help_msg);
+LL | |         });
+   | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg)`
+
+error: this call is collapsible
+  --> $DIR/collapsible_span_lint_calls.rs:81:9
+   |
+LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+LL | |             db.help(help_msg);
+LL | |         });
+   | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg)`
+
+error: this call is collspible
+  --> $DIR/collapsible_span_lint_calls.rs:84:9
+   |
+LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+LL | |             db.span_note(expr.span, note_msg);
+LL | |         });
+   | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)`
+
+error: this call is collspible
+  --> $DIR/collapsible_span_lint_calls.rs:87:9
+   |
+LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
+LL | |             db.note(note_msg);
+LL | |         });
+   | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)`
+
+error: aborting due to 5 previous errors
+
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.rs b/src/tools/clippy/tests/ui-internal/custom_ice_message.rs
new file mode 100644 (file)
index 0000000..5b30c9d
--- /dev/null
@@ -0,0 +1,10 @@
+// rustc-env:RUST_BACKTRACE=0
+// normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo"
+// normalize-stderr-test: "internal_lints.rs:\d*:\d*" -> "internal_lints.rs"
+// normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
+
+#![deny(clippy::internal)]
+
+fn it_looks_like_you_are_trying_to_kill_clippy() {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr b/src/tools/clippy/tests/ui-internal/custom_ice_message.stderr
new file mode 100644 (file)
index 0000000..a1b8e2e
--- /dev/null
@@ -0,0 +1,13 @@
+thread 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints.rs
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+
+error: internal compiler error: unexpected panic
+
+note: the compiler unexpectedly panicked. this is a bug.
+
+note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new
+
+note: Clippy version: foo
+
+query stack during panic:
+end of query stack
diff --git a/src/tools/clippy/tests/ui-internal/default_lint.rs b/src/tools/clippy/tests/ui-internal/default_lint.rs
new file mode 100644 (file)
index 0000000..053faae
--- /dev/null
@@ -0,0 +1,27 @@
+#![deny(clippy::internal)]
+#![feature(rustc_private)]
+
+#[macro_use]
+extern crate rustc_middle;
+#[macro_use]
+extern crate rustc_session;
+extern crate rustc_lint;
+
+declare_tool_lint! {
+    pub clippy::TEST_LINT,
+    Warn,
+    "",
+    report_in_external_macro: true
+}
+
+declare_tool_lint! {
+    pub clippy::TEST_LINT_DEFAULT,
+    Warn,
+    "default lint description",
+    report_in_external_macro: true
+}
+
+declare_lint_pass!(Pass => [TEST_LINT]);
+declare_lint_pass!(Pass2 => [TEST_LINT_DEFAULT]);
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/default_lint.stderr b/src/tools/clippy/tests/ui-internal/default_lint.stderr
new file mode 100644 (file)
index 0000000..5c5836a
--- /dev/null
@@ -0,0 +1,21 @@
+error: the lint `TEST_LINT_DEFAULT` has the default lint description
+  --> $DIR/default_lint.rs:17:1
+   |
+LL | / declare_tool_lint! {
+LL | |     pub clippy::TEST_LINT_DEFAULT,
+LL | |     Warn,
+LL | |     "default lint description",
+LL | |     report_in_external_macro: true
+LL | | }
+   | |_^
+   |
+note: the lint level is defined here
+  --> $DIR/default_lint.rs:1:9
+   |
+LL | #![deny(clippy::internal)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: `#[deny(clippy::default_lint)]` implied by `#[deny(clippy::internal)]`
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-internal/invalid_paths.rs b/src/tools/clippy/tests/ui-internal/invalid_paths.rs
new file mode 100644 (file)
index 0000000..01e28ae
--- /dev/null
@@ -0,0 +1,23 @@
+#![warn(clippy::internal)]
+
+mod paths {
+    // Good path
+    pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"];
+
+    // Path to method on inherent impl of a primitive type
+    pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
+
+    // Path to method on inherent impl
+    pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"];
+
+    // Path with empty segment
+    pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
+
+    // Path with bad crate
+    pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"];
+
+    // Path with bad module
+    pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"];
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/invalid_paths.stderr b/src/tools/clippy/tests/ui-internal/invalid_paths.stderr
new file mode 100644 (file)
index 0000000..bd69d66
--- /dev/null
@@ -0,0 +1,16 @@
+error: invalid path
+  --> $DIR/invalid_paths.rs:17:5
+   |
+LL |     pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::clippy-lints-internal` implied by `-D warnings`
+
+error: invalid path
+  --> $DIR/invalid_paths.rs:20:5
+   |
+LL |     pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"];
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.rs
new file mode 100644 (file)
index 0000000..beaef79
--- /dev/null
@@ -0,0 +1,44 @@
+#![deny(clippy::internal)]
+#![feature(rustc_private)]
+
+#[macro_use]
+extern crate rustc_middle;
+#[macro_use]
+extern crate rustc_session;
+extern crate rustc_lint;
+use rustc_lint::LintPass;
+
+declare_tool_lint! {
+    pub clippy::TEST_LINT,
+    Warn,
+    "",
+    report_in_external_macro: true
+}
+
+declare_tool_lint! {
+    pub clippy::TEST_LINT_REGISTERED,
+    Warn,
+    "",
+    report_in_external_macro: true
+}
+
+declare_tool_lint! {
+    pub clippy::TEST_LINT_REGISTERED_ONLY_IMPL,
+    Warn,
+    "",
+    report_in_external_macro: true
+}
+
+pub struct Pass;
+impl LintPass for Pass {
+    fn name(&self) -> &'static str {
+        "TEST_LINT"
+    }
+}
+
+declare_lint_pass!(Pass2 => [TEST_LINT_REGISTERED]);
+
+pub struct Pass3;
+impl_lint_pass!(Pass3 => [TEST_LINT_REGISTERED_ONLY_IMPL]);
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr b/src/tools/clippy/tests/ui-internal/lint_without_lint_pass.stderr
new file mode 100644 (file)
index 0000000..1257dae
--- /dev/null
@@ -0,0 +1,21 @@
+error: the lint `TEST_LINT` is not added to any `LintPass`
+  --> $DIR/lint_without_lint_pass.rs:11:1
+   |
+LL | / declare_tool_lint! {
+LL | |     pub clippy::TEST_LINT,
+LL | |     Warn,
+LL | |     "",
+LL | |     report_in_external_macro: true
+LL | | }
+   | |_^
+   |
+note: the lint level is defined here
+  --> $DIR/lint_without_lint_pass.rs:1:9
+   |
+LL | #![deny(clippy::internal)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: `#[deny(clippy::lint_without_lint_pass)]` implied by `#[deny(clippy::internal)]`
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.rs
new file mode 100644 (file)
index 0000000..fe950b0
--- /dev/null
@@ -0,0 +1,50 @@
+#![deny(clippy::internal)]
+#![feature(rustc_private)]
+
+extern crate rustc_hir;
+extern crate rustc_lint;
+extern crate rustc_middle;
+#[macro_use]
+extern crate rustc_session;
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::Ty;
+
+mod paths {
+    pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
+}
+
+mod utils {
+    use super::*;
+
+    pub fn match_type(_cx: &LateContext<'_>, _ty: Ty<'_>, _path: &[&str]) -> bool {
+        false
+    }
+}
+
+use utils::match_type;
+
+declare_lint! {
+    pub TEST_LINT,
+    Warn,
+    ""
+}
+
+declare_lint_pass!(Pass => [TEST_LINT]);
+
+static OPTION: [&str; 3] = ["core", "option", "Option"];
+
+impl<'tcx> LateLintPass<'tcx> for Pass {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr) {
+        let ty = cx.typeck_results().expr_ty(expr);
+
+        let _ = match_type(cx, ty, &paths::VEC);
+        let _ = match_type(cx, ty, &OPTION);
+        let _ = match_type(cx, ty, &["core", "result", "Result"]);
+
+        let rc_path = &["alloc", "rc", "Rc"];
+        let _ = utils::match_type(cx, ty, rc_path);
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr b/src/tools/clippy/tests/ui-internal/match_type_on_diag_item.stderr
new file mode 100644 (file)
index 0000000..82465db
--- /dev/null
@@ -0,0 +1,33 @@
+error: usage of `utils::match_type()` on a type diagnostic item
+  --> $DIR/match_type_on_diag_item.rs:41:17
+   |
+LL |         let _ = match_type(cx, ty, &paths::VEC);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::vec_type)`
+   |
+note: the lint level is defined here
+  --> $DIR/match_type_on_diag_item.rs:1:9
+   |
+LL | #![deny(clippy::internal)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: `#[deny(clippy::match_type_on_diagnostic_item)]` implied by `#[deny(clippy::internal)]`
+
+error: usage of `utils::match_type()` on a type diagnostic item
+  --> $DIR/match_type_on_diag_item.rs:42:17
+   |
+LL |         let _ = match_type(cx, ty, &OPTION);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::option_type)`
+
+error: usage of `utils::match_type()` on a type diagnostic item
+  --> $DIR/match_type_on_diag_item.rs:43:17
+   |
+LL |         let _ = match_type(cx, ty, &["core", "result", "Result"]);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::result_type)`
+
+error: usage of `utils::match_type()` on a type diagnostic item
+  --> $DIR/match_type_on_diag_item.rs:46:17
+   |
+LL |         let _ = utils::match_type(cx, ty, rc_path);
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::Rc)`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed b/src/tools/clippy/tests/ui-internal/outer_expn_data.fixed
new file mode 100644 (file)
index 0000000..b0b3498
--- /dev/null
@@ -0,0 +1,28 @@
+// run-rustfix
+
+#![deny(clippy::internal)]
+#![feature(rustc_private)]
+
+extern crate rustc_hir;
+extern crate rustc_lint;
+extern crate rustc_middle;
+#[macro_use]
+extern crate rustc_session;
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, LateLintPass};
+
+declare_lint! {
+    pub TEST_LINT,
+    Warn,
+    ""
+}
+
+declare_lint_pass!(Pass => [TEST_LINT]);
+
+impl<'tcx> LateLintPass<'tcx> for Pass {
+    fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) {
+        let _ = expr.span.ctxt().outer_expn_data();
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.rs b/src/tools/clippy/tests/ui-internal/outer_expn_data.rs
new file mode 100644 (file)
index 0000000..55a3fed
--- /dev/null
@@ -0,0 +1,28 @@
+// run-rustfix
+
+#![deny(clippy::internal)]
+#![feature(rustc_private)]
+
+extern crate rustc_hir;
+extern crate rustc_lint;
+extern crate rustc_middle;
+#[macro_use]
+extern crate rustc_session;
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, LateLintPass};
+
+declare_lint! {
+    pub TEST_LINT,
+    Warn,
+    ""
+}
+
+declare_lint_pass!(Pass => [TEST_LINT]);
+
+impl<'tcx> LateLintPass<'tcx> for Pass {
+    fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) {
+        let _ = expr.span.ctxt().outer_expn().expn_data();
+    }
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr b/src/tools/clippy/tests/ui-internal/outer_expn_data.stderr
new file mode 100644 (file)
index 0000000..56b6ce1
--- /dev/null
@@ -0,0 +1,15 @@
+error: usage of `outer_expn().expn_data()`
+  --> $DIR/outer_expn_data.rs:24:34
+   |
+LL |         let _ = expr.span.ctxt().outer_expn().expn_data();
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `outer_expn_data()`
+   |
+note: the lint level is defined here
+  --> $DIR/outer_expn_data.rs:3:9
+   |
+LL | #![deny(clippy::internal)]
+   |         ^^^^^^^^^^^^^^^^
+   = note: `#[deny(clippy::outer_expn_expn_data)]` implied by `#[deny(clippy::internal)]`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/clippy.toml b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/clippy.toml
new file mode 100644 (file)
index 0000000..088b12b
--- /dev/null
@@ -0,0 +1 @@
+msrv = "invalid.version"
diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.rs
new file mode 100644 (file)
index 0000000..2ebf286
--- /dev/null
@@ -0,0 +1,3 @@
+#![allow(clippy::redundant_clone)]
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr b/src/tools/clippy/tests/ui-toml/invalid_min_rust_version/invalid_min_rust_version.stderr
new file mode 100644 (file)
index 0000000..e9d8fd2
--- /dev/null
@@ -0,0 +1,4 @@
+error: error reading Clippy's configuration file. `invalid.version` is not a valid Rust version
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/clippy.toml b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/clippy.toml
new file mode 100644 (file)
index 0000000..6feaf7d
--- /dev/null
@@ -0,0 +1 @@
+unreadable-literal-lint-fractions = false
\ No newline at end of file
diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.rs
new file mode 100644 (file)
index 0000000..9377eb6
--- /dev/null
@@ -0,0 +1,22 @@
+#[deny(clippy::unreadable_literal)]
+
+fn allow_inconsistent_digit_grouping() {
+    #![allow(clippy::inconsistent_digit_grouping)]
+    let _pass1 = 100_200_300.123456789;
+}
+
+fn main() {
+    allow_inconsistent_digit_grouping();
+
+    let _pass1 = 100_200_300.100_200_300;
+    let _pass2 = 1.123456789;
+    let _pass3 = 1.0;
+    let _pass4 = 10000.00001;
+    let _pass5 = 1.123456789e1;
+
+    // due to clippy::inconsistent-digit-grouping
+    let _fail1 = 100_200_300.123456789;
+
+    // fail due to the integer part
+    let _fail2 = 100200300.300200100;
+}
diff --git a/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr b/src/tools/clippy/tests/ui-toml/lint_decimal_readability/test.stderr
new file mode 100644 (file)
index 0000000..9119ef1
--- /dev/null
@@ -0,0 +1,10 @@
+error: digits grouped inconsistently by underscores
+  --> $DIR/test.rs:18:18
+   |
+LL |     let _fail1 = 100_200_300.123456789;
+   |                  ^^^^^^^^^^^^^^^^^^^^^ help: consider: `100_200_300.123_456_789`
+   |
+   = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui-toml/min_rust_version/clippy.toml b/src/tools/clippy/tests/ui-toml/min_rust_version/clippy.toml
new file mode 100644 (file)
index 0000000..8e17d80
--- /dev/null
@@ -0,0 +1 @@
+msrv = "1.0.0"
diff --git a/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs b/src/tools/clippy/tests/ui-toml/min_rust_version/min_rust_version.rs
new file mode 100644 (file)
index 0000000..bc41efa
--- /dev/null
@@ -0,0 +1,68 @@
+#![allow(clippy::redundant_clone)]
+#![warn(clippy::manual_non_exhaustive)]
+
+use std::ops::Deref;
+
+mod enums {
+    enum E {
+        A,
+        B,
+        #[doc(hidden)]
+        _C,
+    }
+
+    // user forgot to remove the marker
+    #[non_exhaustive]
+    enum Ep {
+        A,
+        B,
+        #[doc(hidden)]
+        _C,
+    }
+}
+
+fn option_as_ref_deref() {
+    let mut opt = Some(String::from("123"));
+
+    let _ = opt.as_ref().map(String::as_str);
+    let _ = opt.as_ref().map(|x| x.as_str());
+    let _ = opt.as_mut().map(String::as_mut_str);
+    let _ = opt.as_mut().map(|x| x.as_mut_str());
+}
+
+fn match_like_matches() {
+    let _y = match Some(5) {
+        Some(0) => true,
+        _ => false,
+    };
+}
+
+fn match_same_arms() {
+    match (1, 2, 3) {
+        (1, .., 3) => 42,
+        (.., 3) => 42, //~ ERROR match arms have same body
+        _ => 0,
+    };
+}
+
+fn match_same_arms2() {
+    let _ = match Some(42) {
+        Some(_) => 24,
+        None => 24, //~ ERROR match arms have same body
+    };
+}
+
+fn manual_strip_msrv() {
+    let s = "hello, world!";
+    if s.starts_with("hello, ") {
+        assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
+    }
+}
+
+fn main() {
+    option_as_ref_deref();
+    match_like_matches();
+    match_same_arms();
+    match_same_arms2();
+    manual_strip_msrv();
+}
index a58e7e918e2f85a6301c5f2d062f1fbce0bc892b..7b3c476461d506af54bad5ba90cfbcd6d290a245 100644 (file)
@@ -1,4 +1,4 @@
-error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `third-party` at line 5 column 1
+error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `msrv`, `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `pass-by-value-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-trait-bounds`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `disallowed-methods`, `unreadable-literal-lint-fractions`, `third-party` at line 5 column 1
 
 error: aborting due to previous error
 
index e01ba0c64df325535f88bb0909640657002f4047..cd745feec6d8acc81063dae1d74b6f0a0a4e85e2 100644 (file)
@@ -1,7 +1,19 @@
-#[warn(clippy::as_conversions)]
+// aux-build:macro_rules.rs
+
+#![warn(clippy::as_conversions)]
+
+#[macro_use]
+extern crate macro_rules;
+
+fn with_external_macro() {
+    as_conv_with_arg!(0u32 as u64);
+    as_conv!();
+}
 
 fn main() {
     let i = 0u32 as u64;
 
     let j = &i as *const u64 as *mut u64;
+
+    with_external_macro();
 }
index 312d3a7460ebe4a34a3753bcf01e9e17dee2693c..f5f75d3aee04a40f2032684353aa310418343389 100644 (file)
@@ -1,5 +1,5 @@
 error: using a potentially dangerous silent `as` conversion
-  --> $DIR/as_conversions.rs:4:13
+  --> $DIR/as_conversions.rs:14:13
    |
 LL |     let i = 0u32 as u64;
    |             ^^^^^^^^^^^
@@ -8,7 +8,7 @@ LL |     let i = 0u32 as u64;
    = help: consider using a safe wrapper for this conversion
 
 error: using a potentially dangerous silent `as` conversion
-  --> $DIR/as_conversions.rs:6:13
+  --> $DIR/as_conversions.rs:16:13
    |
 LL |     let j = &i as *const u64 as *mut u64;
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL |     let j = &i as *const u64 as *mut u64;
    = help: consider using a safe wrapper for this conversion
 
 error: using a potentially dangerous silent `as` conversion
-  --> $DIR/as_conversions.rs:6:13
+  --> $DIR/as_conversions.rs:16:13
    |
 LL |     let j = &i as *const u64 as *mut u64;
    |             ^^^^^^^^^^^^^^^^
index 93303865e178ec0dfb8d24638adfe76ee99c50b3..f985a15eda2bb5cbc48fecbbdd1e8c1b0205346e 100644 (file)
@@ -70,3 +70,17 @@ macro_rules! ref_arg_function {
         fn fun_example(ref _x: usize) {}
     };
 }
+
+#[macro_export]
+macro_rules! as_conv_with_arg {
+    (0u32 as u64) => {
+        ()
+    };
+}
+
+#[macro_export]
+macro_rules! as_conv {
+    () => {
+        0u32 as u64
+    };
+}
diff --git a/src/tools/clippy/tests/ui/collapsible_match.rs b/src/tools/clippy/tests/ui/collapsible_match.rs
new file mode 100644 (file)
index 0000000..a83e6c7
--- /dev/null
@@ -0,0 +1,239 @@
+#![warn(clippy::collapsible_match)]
+#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)]
+
+fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) {
+    // match without block
+    match res_opt {
+        Ok(val) => match val {
+            Some(n) => foo(n),
+            _ => return,
+        },
+        _ => return,
+    }
+
+    // match with block
+    match res_opt {
+        Ok(val) => match val {
+            Some(n) => foo(n),
+            _ => return,
+        },
+        _ => return,
+    }
+
+    // if let, if let
+    if let Ok(val) = res_opt {
+        if let Some(n) = val {
+            take(n);
+        }
+    }
+
+    // if let else, if let else
+    if let Ok(val) = res_opt {
+        if let Some(n) = val {
+            take(n);
+        } else {
+            return;
+        }
+    } else {
+        return;
+    }
+
+    // if let, match
+    if let Ok(val) = res_opt {
+        match val {
+            Some(n) => foo(n),
+            _ => (),
+        }
+    }
+
+    // match, if let
+    match res_opt {
+        Ok(val) => {
+            if let Some(n) = val {
+                take(n);
+            }
+        },
+        _ => {},
+    }
+
+    // if let else, match
+    if let Ok(val) = res_opt {
+        match val {
+            Some(n) => foo(n),
+            _ => return,
+        }
+    } else {
+        return;
+    }
+
+    // match, if let else
+    match res_opt {
+        Ok(val) => {
+            if let Some(n) = val {
+                take(n);
+            } else {
+                return;
+            }
+        },
+        _ => return,
+    }
+
+    // None in inner match same as outer wild branch
+    match res_opt {
+        Ok(val) => match val {
+            Some(n) => foo(n),
+            None => return,
+        },
+        _ => return,
+    }
+
+    // None in outer match same as inner wild branch
+    match opt_opt {
+        Some(val) => match val {
+            Some(n) => foo(n),
+            _ => return,
+        },
+        None => return,
+    }
+}
+
+fn negative_cases(res_opt: Result<Option<u32>, String>, res_res: Result<Result<u32, String>, String>) {
+    // no wild pattern in outer match
+    match res_opt {
+        Ok(val) => match val {
+            Some(n) => foo(n),
+            _ => return,
+        },
+        Err(_) => return,
+    }
+
+    // inner branch is not wild or None
+    match res_res {
+        Ok(val) => match val {
+            Ok(n) => foo(n),
+            Err(_) => return,
+        },
+        _ => return,
+    }
+
+    // statement before inner match
+    match res_opt {
+        Ok(val) => {
+            "hi buddy";
+            match val {
+                Some(n) => foo(n),
+                _ => return,
+            }
+        },
+        _ => return,
+    }
+
+    // statement after inner match
+    match res_opt {
+        Ok(val) => {
+            match val {
+                Some(n) => foo(n),
+                _ => return,
+            }
+            "hi buddy";
+        },
+        _ => return,
+    }
+
+    // wild branches do not match
+    match res_opt {
+        Ok(val) => match val {
+            Some(n) => foo(n),
+            _ => {
+                "sup";
+                return;
+            },
+        },
+        _ => return,
+    }
+
+    // binding used in if guard
+    match res_opt {
+        Ok(val) if val.is_some() => match val {
+            Some(n) => foo(n),
+            _ => return,
+        },
+        _ => return,
+    }
+
+    // binding used in inner match body
+    match res_opt {
+        Ok(val) => match val {
+            Some(_) => take(val),
+            _ => return,
+        },
+        _ => return,
+    }
+
+    // if guard on inner match
+    {
+        match res_opt {
+            Ok(val) => match val {
+                Some(n) if make() => foo(n),
+                _ => return,
+            },
+            _ => return,
+        }
+        match res_opt {
+            Ok(val) => match val {
+                _ => make(),
+                _ if make() => return,
+            },
+            _ => return,
+        }
+    }
+
+    // differing macro contexts
+    {
+        macro_rules! mac {
+            ($val:ident) => {
+                match $val {
+                    Some(n) => foo(n),
+                    _ => return,
+                }
+            };
+        }
+        match res_opt {
+            Ok(val) => mac!(val),
+            _ => return,
+        }
+    }
+
+    // OR pattern
+    enum E<T> {
+        A(T),
+        B(T),
+        C(T),
+    };
+    match make::<E<Option<u32>>>() {
+        E::A(val) | E::B(val) => match val {
+            Some(n) => foo(n),
+            _ => return,
+        },
+        _ => return,
+    }
+    match make::<Option<E<u32>>>() {
+        Some(val) => match val {
+            E::A(val) | E::B(val) => foo(val),
+            _ => return,
+        },
+        _ => return,
+    }
+}
+
+fn make<T>() -> T {
+    unimplemented!()
+}
+
+fn foo<T, U>(t: T) -> U {
+    unimplemented!()
+}
+
+fn take<T>(t: T) {}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/collapsible_match.stderr b/src/tools/clippy/tests/ui/collapsible_match.stderr
new file mode 100644 (file)
index 0000000..63ac6a1
--- /dev/null
@@ -0,0 +1,179 @@
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:7:20
+   |
+LL |           Ok(val) => match val {
+   |  ____________________^
+LL | |             Some(n) => foo(n),
+LL | |             _ => return,
+LL | |         },
+   | |_________^
+   |
+   = note: `-D clippy::collapsible-match` implied by `-D warnings`
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:7:12
+   |
+LL |         Ok(val) => match val {
+   |            ^^^ Replace this binding
+LL |             Some(n) => foo(n),
+   |             ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:16:20
+   |
+LL |           Ok(val) => match val {
+   |  ____________________^
+LL | |             Some(n) => foo(n),
+LL | |             _ => return,
+LL | |         },
+   | |_________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:16:12
+   |
+LL |         Ok(val) => match val {
+   |            ^^^ Replace this binding
+LL |             Some(n) => foo(n),
+   |             ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:25:9
+   |
+LL | /         if let Some(n) = val {
+LL | |             take(n);
+LL | |         }
+   | |_________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:24:15
+   |
+LL |     if let Ok(val) = res_opt {
+   |               ^^^ Replace this binding
+LL |         if let Some(n) = val {
+   |                ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:32:9
+   |
+LL | /         if let Some(n) = val {
+LL | |             take(n);
+LL | |         } else {
+LL | |             return;
+LL | |         }
+   | |_________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:31:15
+   |
+LL |     if let Ok(val) = res_opt {
+   |               ^^^ Replace this binding
+LL |         if let Some(n) = val {
+   |                ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:43:9
+   |
+LL | /         match val {
+LL | |             Some(n) => foo(n),
+LL | |             _ => (),
+LL | |         }
+   | |_________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:42:15
+   |
+LL |     if let Ok(val) = res_opt {
+   |               ^^^ Replace this binding
+LL |         match val {
+LL |             Some(n) => foo(n),
+   |             ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:52:13
+   |
+LL | /             if let Some(n) = val {
+LL | |                 take(n);
+LL | |             }
+   | |_____________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:51:12
+   |
+LL |         Ok(val) => {
+   |            ^^^ Replace this binding
+LL |             if let Some(n) = val {
+   |                    ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:61:9
+   |
+LL | /         match val {
+LL | |             Some(n) => foo(n),
+LL | |             _ => return,
+LL | |         }
+   | |_________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:60:15
+   |
+LL |     if let Ok(val) = res_opt {
+   |               ^^^ Replace this binding
+LL |         match val {
+LL |             Some(n) => foo(n),
+   |             ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:72:13
+   |
+LL | /             if let Some(n) = val {
+LL | |                 take(n);
+LL | |             } else {
+LL | |                 return;
+LL | |             }
+   | |_____________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:71:12
+   |
+LL |         Ok(val) => {
+   |            ^^^ Replace this binding
+LL |             if let Some(n) = val {
+   |                    ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:83:20
+   |
+LL |           Ok(val) => match val {
+   |  ____________________^
+LL | |             Some(n) => foo(n),
+LL | |             None => return,
+LL | |         },
+   | |_________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:83:12
+   |
+LL |         Ok(val) => match val {
+   |            ^^^ Replace this binding
+LL |             Some(n) => foo(n),
+   |             ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match.rs:92:22
+   |
+LL |           Some(val) => match val {
+   |  ______________________^
+LL | |             Some(n) => foo(n),
+LL | |             _ => return,
+LL | |         },
+   | |_________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match.rs:92:14
+   |
+LL |         Some(val) => match val {
+   |              ^^^ Replace this binding
+LL |             Some(n) => foo(n),
+   |             ^^^^^^^ with this pattern
+
+error: aborting due to 10 previous errors
+
diff --git a/src/tools/clippy/tests/ui/collapsible_match2.rs b/src/tools/clippy/tests/ui/collapsible_match2.rs
new file mode 100644 (file)
index 0000000..d571ac4
--- /dev/null
@@ -0,0 +1,53 @@
+#![warn(clippy::collapsible_match)]
+#![allow(clippy::needless_return, clippy::no_effect, clippy::single_match)]
+
+fn lint_cases(opt_opt: Option<Option<u32>>, res_opt: Result<Option<u32>, String>) {
+    // if guards on outer match
+    {
+        match res_opt {
+            Ok(val) if make() => match val {
+                Some(n) => foo(n),
+                _ => return,
+            },
+            _ => return,
+        }
+        match res_opt {
+            Ok(val) => match val {
+                Some(n) => foo(n),
+                _ => return,
+            },
+            _ if make() => return,
+            _ => return,
+        }
+    }
+
+    // macro
+    {
+        macro_rules! mac {
+            ($outer:expr => $pat:pat, $e:expr => $inner_pat:pat, $then:expr) => {
+                match $outer {
+                    $pat => match $e {
+                        $inner_pat => $then,
+                        _ => return,
+                    },
+                    _ => return,
+                }
+            };
+        }
+        // Lint this since the patterns are not defined by the macro.
+        // Allows the lint to work on if_chain! for example.
+        // Fixing the lint requires knowledge of the specific macro, but we optimistically assume that
+        // there is still a better way to write this.
+        mac!(res_opt => Ok(val), val => Some(n), foo(n));
+    }
+}
+
+fn make<T>() -> T {
+    unimplemented!()
+}
+
+fn foo<T, U>(t: T) -> U {
+    unimplemented!()
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/collapsible_match2.stderr b/src/tools/clippy/tests/ui/collapsible_match2.stderr
new file mode 100644 (file)
index 0000000..490d82d
--- /dev/null
@@ -0,0 +1,61 @@
+error: Unnecessary nested match
+  --> $DIR/collapsible_match2.rs:8:34
+   |
+LL |               Ok(val) if make() => match val {
+   |  __________________________________^
+LL | |                 Some(n) => foo(n),
+LL | |                 _ => return,
+LL | |             },
+   | |_____________^
+   |
+   = note: `-D clippy::collapsible-match` implied by `-D warnings`
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match2.rs:8:16
+   |
+LL |             Ok(val) if make() => match val {
+   |                ^^^ Replace this binding
+LL |                 Some(n) => foo(n),
+   |                 ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match2.rs:15:24
+   |
+LL |               Ok(val) => match val {
+   |  ________________________^
+LL | |                 Some(n) => foo(n),
+LL | |                 _ => return,
+LL | |             },
+   | |_____________^
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match2.rs:15:16
+   |
+LL |             Ok(val) => match val {
+   |                ^^^ Replace this binding
+LL |                 Some(n) => foo(n),
+   |                 ^^^^^^^ with this pattern
+
+error: Unnecessary nested match
+  --> $DIR/collapsible_match2.rs:29:29
+   |
+LL |                       $pat => match $e {
+   |  _____________________________^
+LL | |                         $inner_pat => $then,
+LL | |                         _ => return,
+LL | |                     },
+   | |_____________________^
+...
+LL |           mac!(res_opt => Ok(val), val => Some(n), foo(n));
+   |           ------------------------------------------------- in this macro invocation
+   |
+help: The outer pattern can be modified to include the inner pattern.
+  --> $DIR/collapsible_match2.rs:41:28
+   |
+LL |         mac!(res_opt => Ok(val), val => Some(n), foo(n));
+   |                            ^^^          ^^^^^^^ with this pattern
+   |                            |
+   |                            Replace this binding
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/collapsible_span_lint_calls.fixed b/src/tools/clippy/tests/ui/collapsible_span_lint_calls.fixed
deleted file mode 100644 (file)
index e588c23..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-// run-rustfix
-#![deny(clippy::internal)]
-#![feature(rustc_private)]
-
-extern crate rustc_ast;
-extern crate rustc_errors;
-extern crate rustc_lint;
-extern crate rustc_session;
-extern crate rustc_span;
-
-use rustc_ast::ast::Expr;
-use rustc_errors::{Applicability, DiagnosticBuilder};
-use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::source_map::Span;
-
-#[allow(unused_variables)]
-pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F)
-where
-    F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>),
-{
-}
-
-#[allow(unused_variables)]
-fn span_lint_and_help<'a, T: LintContext>(
-    cx: &'a T,
-    lint: &'static Lint,
-    span: Span,
-    msg: &str,
-    option_span: Option<Span>,
-    help: &str,
-) {
-}
-
-#[allow(unused_variables)]
-fn span_lint_and_note<'a, T: LintContext>(
-    cx: &'a T,
-    lint: &'static Lint,
-    span: Span,
-    msg: &str,
-    note_span: Option<Span>,
-    note: &str,
-) {
-}
-
-#[allow(unused_variables)]
-fn span_lint_and_sugg<'a, T: LintContext>(
-    cx: &'a T,
-    lint: &'static Lint,
-    sp: Span,
-    msg: &str,
-    help: &str,
-    sugg: String,
-    applicability: Applicability,
-) {
-}
-
-declare_tool_lint! {
-    pub clippy::TEST_LINT,
-    Warn,
-    "",
-    report_in_external_macro: true
-}
-
-declare_lint_pass!(Pass => [TEST_LINT]);
-
-impl EarlyLintPass for Pass {
-    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
-        let lint_msg = "lint message";
-        let help_msg = "help message";
-        let note_msg = "note message";
-        let sugg = "new_call()";
-        let predicate = true;
-
-        span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable);
-        span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg);
-        span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg);
-        span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg);
-        span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg);
-
-        // This expr shouldn't trigger this lint.
-        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-            db.note(note_msg);
-            if predicate {
-                db.note(note_msg);
-            }
-        })
-    }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/collapsible_span_lint_calls.rs b/src/tools/clippy/tests/ui/collapsible_span_lint_calls.rs
deleted file mode 100644 (file)
index d5dd3bb..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-// run-rustfix
-#![deny(clippy::internal)]
-#![feature(rustc_private)]
-
-extern crate rustc_ast;
-extern crate rustc_errors;
-extern crate rustc_lint;
-extern crate rustc_session;
-extern crate rustc_span;
-
-use rustc_ast::ast::Expr;
-use rustc_errors::{Applicability, DiagnosticBuilder};
-use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::source_map::Span;
-
-#[allow(unused_variables)]
-pub fn span_lint_and_then<'a, T: LintContext, F>(cx: &'a T, lint: &'static Lint, sp: Span, msg: &str, f: F)
-where
-    F: for<'b> FnOnce(&mut DiagnosticBuilder<'b>),
-{
-}
-
-#[allow(unused_variables)]
-fn span_lint_and_help<'a, T: LintContext>(
-    cx: &'a T,
-    lint: &'static Lint,
-    span: Span,
-    msg: &str,
-    option_span: Option<Span>,
-    help: &str,
-) {
-}
-
-#[allow(unused_variables)]
-fn span_lint_and_note<'a, T: LintContext>(
-    cx: &'a T,
-    lint: &'static Lint,
-    span: Span,
-    msg: &str,
-    note_span: Option<Span>,
-    note: &str,
-) {
-}
-
-#[allow(unused_variables)]
-fn span_lint_and_sugg<'a, T: LintContext>(
-    cx: &'a T,
-    lint: &'static Lint,
-    sp: Span,
-    msg: &str,
-    help: &str,
-    sugg: String,
-    applicability: Applicability,
-) {
-}
-
-declare_tool_lint! {
-    pub clippy::TEST_LINT,
-    Warn,
-    "",
-    report_in_external_macro: true
-}
-
-declare_lint_pass!(Pass => [TEST_LINT]);
-
-impl EarlyLintPass for Pass {
-    fn check_expr(&mut self, cx: &EarlyContext, expr: &Expr) {
-        let lint_msg = "lint message";
-        let help_msg = "help message";
-        let note_msg = "note message";
-        let sugg = "new_call()";
-        let predicate = true;
-
-        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-            db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable);
-        });
-        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-            db.span_help(expr.span, help_msg);
-        });
-        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-            db.help(help_msg);
-        });
-        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-            db.span_note(expr.span, note_msg);
-        });
-        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-            db.note(note_msg);
-        });
-
-        // This expr shouldn't trigger this lint.
-        span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-            db.note(note_msg);
-            if predicate {
-                db.note(note_msg);
-            }
-        })
-    }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/collapsible_span_lint_calls.stderr b/src/tools/clippy/tests/ui/collapsible_span_lint_calls.stderr
deleted file mode 100644 (file)
index 874d4a9..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-error: this call is collapsible
-  --> $DIR/collapsible_span_lint_calls.rs:75:9
-   |
-LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-LL | |             db.span_suggestion(expr.span, help_msg, sugg.to_string(), Applicability::MachineApplicable);
-LL | |         });
-   | |__________^ help: collapse into: `span_lint_and_sugg(cx, TEST_LINT, expr.span, lint_msg, help_msg, sugg.to_string(), Applicability::MachineApplicable)`
-   |
-note: the lint level is defined here
-  --> $DIR/collapsible_span_lint_calls.rs:2:9
-   |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::collapsible_span_lint_calls)]` implied by `#[deny(clippy::internal)]`
-
-error: this call is collapsible
-  --> $DIR/collapsible_span_lint_calls.rs:78:9
-   |
-LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-LL | |             db.span_help(expr.span, help_msg);
-LL | |         });
-   | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), help_msg)`
-
-error: this call is collapsible
-  --> $DIR/collapsible_span_lint_calls.rs:81:9
-   |
-LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-LL | |             db.help(help_msg);
-LL | |         });
-   | |__________^ help: collapse into: `span_lint_and_help(cx, TEST_LINT, expr.span, lint_msg, None, help_msg)`
-
-error: this call is collspible
-  --> $DIR/collapsible_span_lint_calls.rs:84:9
-   |
-LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-LL | |             db.span_note(expr.span, note_msg);
-LL | |         });
-   | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, Some(expr.span), note_msg)`
-
-error: this call is collspible
-  --> $DIR/collapsible_span_lint_calls.rs:87:9
-   |
-LL | /         span_lint_and_then(cx, TEST_LINT, expr.span, lint_msg, |db| {
-LL | |             db.note(note_msg);
-LL | |         });
-   | |__________^ help: collapse into: `span_lint_and_note(cx, TEST_LINT, expr.span, lint_msg, None, note_msg)`
-
-error: aborting due to 5 previous errors
-
diff --git a/src/tools/clippy/tests/ui/custom_ice_message.rs b/src/tools/clippy/tests/ui/custom_ice_message.rs
deleted file mode 100644 (file)
index 5b30c9d..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-// rustc-env:RUST_BACKTRACE=0
-// normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo"
-// normalize-stderr-test: "internal_lints.rs:\d*:\d*" -> "internal_lints.rs"
-// normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints"
-
-#![deny(clippy::internal)]
-
-fn it_looks_like_you_are_trying_to_kill_clippy() {}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/custom_ice_message.stderr b/src/tools/clippy/tests/ui/custom_ice_message.stderr
deleted file mode 100644 (file)
index a1b8e2e..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-thread 'rustc' panicked at 'Would you like some help with that?', clippy_lints/src/utils/internal_lints.rs
-note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-
-error: internal compiler error: unexpected panic
-
-note: the compiler unexpectedly panicked. this is a bug.
-
-note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new
-
-note: Clippy version: foo
-
-query stack during panic:
-end of query stack
diff --git a/src/tools/clippy/tests/ui/default_lint.rs b/src/tools/clippy/tests/ui/default_lint.rs
deleted file mode 100644 (file)
index 053faae..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#![deny(clippy::internal)]
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate rustc_middle;
-#[macro_use]
-extern crate rustc_session;
-extern crate rustc_lint;
-
-declare_tool_lint! {
-    pub clippy::TEST_LINT,
-    Warn,
-    "",
-    report_in_external_macro: true
-}
-
-declare_tool_lint! {
-    pub clippy::TEST_LINT_DEFAULT,
-    Warn,
-    "default lint description",
-    report_in_external_macro: true
-}
-
-declare_lint_pass!(Pass => [TEST_LINT]);
-declare_lint_pass!(Pass2 => [TEST_LINT_DEFAULT]);
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/default_lint.stderr b/src/tools/clippy/tests/ui/default_lint.stderr
deleted file mode 100644 (file)
index 5c5836a..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error: the lint `TEST_LINT_DEFAULT` has the default lint description
-  --> $DIR/default_lint.rs:17:1
-   |
-LL | / declare_tool_lint! {
-LL | |     pub clippy::TEST_LINT_DEFAULT,
-LL | |     Warn,
-LL | |     "default lint description",
-LL | |     report_in_external_macro: true
-LL | | }
-   | |_^
-   |
-note: the lint level is defined here
-  --> $DIR/default_lint.rs:1:9
-   |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::default_lint)]` implied by `#[deny(clippy::internal)]`
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
index 4cbc5630d759d76d6c5e631e31871a3cbfebb2ac..e1ee8dbca2c04286a9924606d4865aae056c1e10 100644 (file)
@@ -1,5 +1,3 @@
-#[warn(clippy::str_to_string)]
-#[warn(clippy::string_to_string)]
 #[warn(clippy::unstable_as_slice)]
 #[warn(clippy::unstable_as_mut_slice)]
 #[warn(clippy::misaligned_transmute)]
index a348d01d734fed006f29ecd2e7dba3b96e8f5f1d..edbb891afe07bdb9cfd6e9d2c84d158c400c5b86 100644 (file)
@@ -1,88 +1,76 @@
-error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
-  --> $DIR/deprecated.rs:1:8
-   |
-LL | #[warn(clippy::str_to_string)]
-   |        ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
-
-error: lint `clippy::string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon`
-  --> $DIR/deprecated.rs:2:8
-   |
-LL | #[warn(clippy::string_to_string)]
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: lint `clippy::unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
-  --> $DIR/deprecated.rs:3:8
+  --> $DIR/deprecated.rs:1:8
    |
 LL | #[warn(clippy::unstable_as_slice)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7`
-  --> $DIR/deprecated.rs:4:8
+  --> $DIR/deprecated.rs:2:8
    |
 LL | #[warn(clippy::unstable_as_mut_slice)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr`
-  --> $DIR/deprecated.rs:5:8
+  --> $DIR/deprecated.rs:3:8
    |
 LL | #[warn(clippy::misaligned_transmute)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::unused_collect` has been removed: ``collect` has been marked as #[must_use] in rustc and that covers all cases of this lint`
-  --> $DIR/deprecated.rs:6:8
+  --> $DIR/deprecated.rs:4:8
    |
 LL | #[warn(clippy::unused_collect)]
    |        ^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::invalid_ref` has been removed: `superseded by rustc lint `invalid_value``
-  --> $DIR/deprecated.rs:7:8
+  --> $DIR/deprecated.rs:5:8
    |
 LL | #[warn(clippy::invalid_ref)]
    |        ^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::into_iter_on_array` has been removed: `this lint has been uplifted to rustc and is now called `array_into_iter``
-  --> $DIR/deprecated.rs:8:8
+  --> $DIR/deprecated.rs:6:8
    |
 LL | #[warn(clippy::into_iter_on_array)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::unused_label` has been removed: `this lint has been uplifted to rustc and is now called `unused_labels``
-  --> $DIR/deprecated.rs:9:8
+  --> $DIR/deprecated.rs:7:8
    |
 LL | #[warn(clippy::unused_label)]
    |        ^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::regex_macro` has been removed: `the regex! macro has been removed from the regex crate in 2018`
-  --> $DIR/deprecated.rs:10:8
+  --> $DIR/deprecated.rs:8:8
    |
 LL | #[warn(clippy::regex_macro)]
    |        ^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::drop_bounds` has been removed: `this lint has been uplifted to rustc and is now called `drop_bounds``
-  --> $DIR/deprecated.rs:11:8
+  --> $DIR/deprecated.rs:9:8
    |
 LL | #[warn(clippy::drop_bounds)]
    |        ^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::temporary_cstring_as_ptr` has been removed: `this lint has been uplifted to rustc and is now called `temporary_cstring_as_ptr``
-  --> $DIR/deprecated.rs:12:8
+  --> $DIR/deprecated.rs:10:8
    |
 LL | #[warn(clippy::temporary_cstring_as_ptr)]
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `clippy::panic_params` has been removed: `this lint has been uplifted to rustc and is now called `panic_fmt``
-  --> $DIR/deprecated.rs:13:8
+  --> $DIR/deprecated.rs:11:8
    |
 LL | #[warn(clippy::panic_params)]
    |        ^^^^^^^^^^^^^^^^^^^^
 
-error: lint `clippy::str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
+error: lint `clippy::unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
   --> $DIR/deprecated.rs:1:8
    |
-LL | #[warn(clippy::str_to_string)]
-   |        ^^^^^^^^^^^^^^^^^^^^^
+LL | #[warn(clippy::unstable_as_slice)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 14 previous errors
+error: aborting due to 12 previous errors
 
index 2e5c5b7ead12c1e2fd81b2816473939feb5b508f..e89dca4fcfd4cf3ea6625b8d2e159f1e98956924 100644 (file)
@@ -1,5 +1,3 @@
-#[warn(str_to_string)]
-#[warn(string_to_string)]
 #[warn(unstable_as_slice)]
 #[warn(unstable_as_mut_slice)]
 #[warn(misaligned_transmute)]
index ff3e9e8fcf36763e57e282ad0f8149ce67eadb3c..2fe1facf0c72de582fef93a36a28527e32dc12c2 100644 (file)
@@ -1,40 +1,28 @@
-error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
-  --> $DIR/deprecated_old.rs:1:8
-   |
-LL | #[warn(str_to_string)]
-   |        ^^^^^^^^^^^^^
-   |
-   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
-
-error: lint `string_to_string` has been removed: `using `string::to_string` is common even today and specialization will likely happen soon`
-  --> $DIR/deprecated_old.rs:2:8
-   |
-LL | #[warn(string_to_string)]
-   |        ^^^^^^^^^^^^^^^^
-
 error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
-  --> $DIR/deprecated_old.rs:3:8
+  --> $DIR/deprecated_old.rs:1:8
    |
 LL | #[warn(unstable_as_slice)]
    |        ^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `unstable_as_mut_slice` has been removed: ``Vec::as_mut_slice` has been stabilized in 1.7`
-  --> $DIR/deprecated_old.rs:4:8
+  --> $DIR/deprecated_old.rs:2:8
    |
 LL | #[warn(unstable_as_mut_slice)]
    |        ^^^^^^^^^^^^^^^^^^^^^
 
 error: lint `misaligned_transmute` has been removed: `this lint has been split into cast_ptr_alignment and transmute_ptr_to_ptr`
-  --> $DIR/deprecated_old.rs:5:8
+  --> $DIR/deprecated_old.rs:3:8
    |
 LL | #[warn(misaligned_transmute)]
    |        ^^^^^^^^^^^^^^^^^^^^
 
-error: lint `str_to_string` has been removed: `using `str::to_string` is common even today and specialization will likely happen soon`
+error: lint `unstable_as_slice` has been removed: ``Vec::as_slice` has been stabilized in 1.7`
   --> $DIR/deprecated_old.rs:1:8
    |
-LL | #[warn(str_to_string)]
-   |        ^^^^^^^^^^^^^
+LL | #[warn(unstable_as_slice)]
+   |        ^^^^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
index 4e09d19ea214572f70adbeba6142268609c7a2f7..7ab23320db6d1b7aba040e382ea317cb517b2d2c 100644 (file)
@@ -86,3 +86,12 @@ fn check_ignore_macro() {
     // checks if the lint ignores macros with `!` operator
     !bool_macro!(1) && !bool_macro!("");
 }
+
+struct Nested {
+    inner: ((i32,), (i32,), (i32,)),
+}
+
+fn check_nested(n1: &Nested, n2: &Nested) -> bool {
+    // `n2.inner.0.0` mistyped as `n1.inner.0.0`
+    (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0
+}
index ad81b35a766493c9e81e61bca13a8540ef1e6f91..8ef658af8df429829ec50d85dfcdbe4f8ab3bd74 100644 (file)
@@ -162,5 +162,13 @@ error: equal expressions as operands to `/`
 LL |     const D: u32 = A / A;
    |                    ^^^^^
 
-error: aborting due to 27 previous errors
+error: equal expressions as operands to `==`
+  --> $DIR/eq_op.rs:96:5
+   |
+LL |     (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `#[deny(clippy::eq_op)]` on by default
+
+error: aborting due to 28 previous errors
 
diff --git a/src/tools/clippy/tests/ui/invalid_paths.rs b/src/tools/clippy/tests/ui/invalid_paths.rs
deleted file mode 100644 (file)
index 01e28ae..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-#![warn(clippy::internal)]
-
-mod paths {
-    // Good path
-    pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"];
-
-    // Path to method on inherent impl of a primitive type
-    pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
-
-    // Path to method on inherent impl
-    pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"];
-
-    // Path with empty segment
-    pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
-
-    // Path with bad crate
-    pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"];
-
-    // Path with bad module
-    pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"];
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/invalid_paths.stderr b/src/tools/clippy/tests/ui/invalid_paths.stderr
deleted file mode 100644 (file)
index bd69d66..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-error: invalid path
-  --> $DIR/invalid_paths.rs:17:5
-   |
-LL |     pub const BAD_CRATE_PATH: [&str; 2] = ["bad", "path"];
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `-D clippy::clippy-lints-internal` implied by `-D warnings`
-
-error: invalid path
-  --> $DIR/invalid_paths.rs:20:5
-   |
-LL |     pub const BAD_MOD_PATH: [&str; 2] = ["std", "xxx"];
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
index 377e58e44174977a5e4bdbea2257ada3d4946633..d439ca1e4e1a171ca3ef20dc99f2311b968b5573 100644 (file)
@@ -37,3 +37,16 @@ fn say_something() {
     b!();
     println!("{}", a);
 }
+
+fn semicolon() {
+    struct S {
+        a: u32,
+    };
+    impl S {
+        fn new(a: u32) -> Self {
+            Self { a }
+        }
+    }
+
+    let _ = S::new(3);
+}
diff --git a/src/tools/clippy/tests/ui/lint_without_lint_pass.rs b/src/tools/clippy/tests/ui/lint_without_lint_pass.rs
deleted file mode 100644 (file)
index beaef79..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#![deny(clippy::internal)]
-#![feature(rustc_private)]
-
-#[macro_use]
-extern crate rustc_middle;
-#[macro_use]
-extern crate rustc_session;
-extern crate rustc_lint;
-use rustc_lint::LintPass;
-
-declare_tool_lint! {
-    pub clippy::TEST_LINT,
-    Warn,
-    "",
-    report_in_external_macro: true
-}
-
-declare_tool_lint! {
-    pub clippy::TEST_LINT_REGISTERED,
-    Warn,
-    "",
-    report_in_external_macro: true
-}
-
-declare_tool_lint! {
-    pub clippy::TEST_LINT_REGISTERED_ONLY_IMPL,
-    Warn,
-    "",
-    report_in_external_macro: true
-}
-
-pub struct Pass;
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "TEST_LINT"
-    }
-}
-
-declare_lint_pass!(Pass2 => [TEST_LINT_REGISTERED]);
-
-pub struct Pass3;
-impl_lint_pass!(Pass3 => [TEST_LINT_REGISTERED_ONLY_IMPL]);
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/lint_without_lint_pass.stderr b/src/tools/clippy/tests/ui/lint_without_lint_pass.stderr
deleted file mode 100644 (file)
index 1257dae..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-error: the lint `TEST_LINT` is not added to any `LintPass`
-  --> $DIR/lint_without_lint_pass.rs:11:1
-   |
-LL | / declare_tool_lint! {
-LL | |     pub clippy::TEST_LINT,
-LL | |     Warn,
-LL | |     "",
-LL | |     report_in_external_macro: true
-LL | | }
-   | |_^
-   |
-note: the lint level is defined here
-  --> $DIR/lint_without_lint_pass.rs:1:9
-   |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::lint_without_lint_pass)]` implied by `#[deny(clippy::internal)]`
-   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to previous error
-
index 05b9949f10217e2cd9ef17c3fd8a2a51dfff61d5..00e037843f8c29e47afffe937d9ddc6052ee190c 100644 (file)
@@ -22,5 +22,9 @@ fn main() -> Result<(), Errors> {
 
     println!("{:?}", x.map_err(|_| Errors::Ignored));
 
+    // Should not warn you because you explicitly ignore the parameter
+    // using a named wildcard value
+    println!("{:?}", x.map_err(|_foo| Errors::Ignored));
+
     Ok(())
 }
index 390d7ce2e4e7b0fa5a6c956929a72d6983838173..8ee2941790d3542d243502c8dd81135480830d06 100644 (file)
@@ -1,11 +1,11 @@
-error: `map_err(|_|...` ignores the original error
+error: `map_err(|_|...` wildcard pattern discards the original error
   --> $DIR/map_err.rs:23:32
    |
 LL |     println!("{:?}", x.map_err(|_| Errors::Ignored));
    |                                ^^^
    |
    = note: `-D clippy::map-err-ignore` implied by `-D warnings`
-   = help: Consider wrapping the error in an enum variant
+   = help: Consider storing the original error as a source in the new error, or silence this warning using an ignored identifier (`.map_err(|_foo| ...`)
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/tests/ui/match_type_on_diag_item.rs b/src/tools/clippy/tests/ui/match_type_on_diag_item.rs
deleted file mode 100644 (file)
index fe950b0..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#![deny(clippy::internal)]
-#![feature(rustc_private)]
-
-extern crate rustc_hir;
-extern crate rustc_lint;
-extern crate rustc_middle;
-#[macro_use]
-extern crate rustc_session;
-use rustc_hir::Expr;
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::Ty;
-
-mod paths {
-    pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
-}
-
-mod utils {
-    use super::*;
-
-    pub fn match_type(_cx: &LateContext<'_>, _ty: Ty<'_>, _path: &[&str]) -> bool {
-        false
-    }
-}
-
-use utils::match_type;
-
-declare_lint! {
-    pub TEST_LINT,
-    Warn,
-    ""
-}
-
-declare_lint_pass!(Pass => [TEST_LINT]);
-
-static OPTION: [&str; 3] = ["core", "option", "Option"];
-
-impl<'tcx> LateLintPass<'tcx> for Pass {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr) {
-        let ty = cx.typeck_results().expr_ty(expr);
-
-        let _ = match_type(cx, ty, &paths::VEC);
-        let _ = match_type(cx, ty, &OPTION);
-        let _ = match_type(cx, ty, &["core", "result", "Result"]);
-
-        let rc_path = &["alloc", "rc", "Rc"];
-        let _ = utils::match_type(cx, ty, rc_path);
-    }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/match_type_on_diag_item.stderr b/src/tools/clippy/tests/ui/match_type_on_diag_item.stderr
deleted file mode 100644 (file)
index 82465db..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-error: usage of `utils::match_type()` on a type diagnostic item
-  --> $DIR/match_type_on_diag_item.rs:41:17
-   |
-LL |         let _ = match_type(cx, ty, &paths::VEC);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::vec_type)`
-   |
-note: the lint level is defined here
-  --> $DIR/match_type_on_diag_item.rs:1:9
-   |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::match_type_on_diagnostic_item)]` implied by `#[deny(clippy::internal)]`
-
-error: usage of `utils::match_type()` on a type diagnostic item
-  --> $DIR/match_type_on_diag_item.rs:42:17
-   |
-LL |         let _ = match_type(cx, ty, &OPTION);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::option_type)`
-
-error: usage of `utils::match_type()` on a type diagnostic item
-  --> $DIR/match_type_on_diag_item.rs:43:17
-   |
-LL |         let _ = match_type(cx, ty, &["core", "result", "Result"]);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::result_type)`
-
-error: usage of `utils::match_type()` on a type diagnostic item
-  --> $DIR/match_type_on_diag_item.rs:46:17
-   |
-LL |         let _ = utils::match_type(cx, ty, rc_path);
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `utils::is_type_diagnostic_item(cx, ty, sym::Rc)`
-
-error: aborting due to 4 previous errors
-
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_attr.rs
new file mode 100644 (file)
index 0000000..1026cc4
--- /dev/null
@@ -0,0 +1,87 @@
+#![allow(clippy::redundant_clone)]
+#![feature(custom_inner_attributes)]
+#![clippy::msrv = "1.0.0"]
+
+use std::ops::Deref;
+
+fn option_as_ref_deref() {
+    let mut opt = Some(String::from("123"));
+
+    let _ = opt.as_ref().map(String::as_str);
+    let _ = opt.as_ref().map(|x| x.as_str());
+    let _ = opt.as_mut().map(String::as_mut_str);
+    let _ = opt.as_mut().map(|x| x.as_mut_str());
+}
+
+fn match_like_matches() {
+    let _y = match Some(5) {
+        Some(0) => true,
+        _ => false,
+    };
+}
+
+fn match_same_arms() {
+    match (1, 2, 3) {
+        (1, .., 3) => 42,
+        (.., 3) => 42, //~ ERROR match arms have same body
+        _ => 0,
+    };
+}
+
+fn match_same_arms2() {
+    let _ = match Some(42) {
+        Some(_) => 24,
+        None => 24, //~ ERROR match arms have same body
+    };
+}
+
+pub fn manual_strip_msrv() {
+    let s = "hello, world!";
+    if s.starts_with("hello, ") {
+        assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
+    }
+}
+
+fn main() {
+    option_as_ref_deref();
+    match_like_matches();
+    match_same_arms();
+    match_same_arms2();
+    manual_strip_msrv();
+}
+
+mod meets_msrv {
+    #![feature(custom_inner_attributes)]
+    #![clippy::msrv = "1.45.0"]
+
+    fn main() {
+        let s = "hello, world!";
+        if s.starts_with("hello, ") {
+            assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
+        }
+    }
+}
+
+mod just_under_msrv {
+    #![feature(custom_inner_attributes)]
+    #![clippy::msrv = "1.46.0"]
+
+    fn main() {
+        let s = "hello, world!";
+        if s.starts_with("hello, ") {
+            assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
+        }
+    }
+}
+
+mod just_above_msrv {
+    #![feature(custom_inner_attributes)]
+    #![clippy::msrv = "1.44.0"]
+
+    fn main() {
+        let s = "hello, world!";
+        if s.starts_with("hello, ") {
+            assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
+        }
+    }
+}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_attr.stderr
new file mode 100644 (file)
index 0000000..3e1af04
--- /dev/null
@@ -0,0 +1,37 @@
+error: stripping a prefix manually
+  --> $DIR/min_rust_version_attr.rs:60:24
+   |
+LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
+   |                        ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::manual-strip` implied by `-D warnings`
+note: the prefix was tested here
+  --> $DIR/min_rust_version_attr.rs:59:9
+   |
+LL |         if s.starts_with("hello, ") {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using the `strip_prefix` method
+   |
+LL |         if let Some(<stripped>) = s.strip_prefix("hello, ") {
+LL |             assert_eq!(<stripped>.to_uppercase(), "WORLD!");
+   |
+
+error: stripping a prefix manually
+  --> $DIR/min_rust_version_attr.rs:72:24
+   |
+LL |             assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
+   |                        ^^^^^^^^^^^^^^^^^^^^
+   |
+note: the prefix was tested here
+  --> $DIR/min_rust_version_attr.rs:71:9
+   |
+LL |         if s.starts_with("hello, ") {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: try using the `strip_prefix` method
+   |
+LL |         if let Some(<stripped>) = s.strip_prefix("hello, ") {
+LL |             assert_eq!(<stripped>.to_uppercase(), "WORLD!");
+   |
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.rs
new file mode 100644 (file)
index 0000000..f208418
--- /dev/null
@@ -0,0 +1,4 @@
+#![feature(custom_inner_attributes)]
+#![clippy::msrv = "invalid.version"]
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_invalid_attr.stderr
new file mode 100644 (file)
index 0000000..6ff88ca
--- /dev/null
@@ -0,0 +1,8 @@
+error: `invalid.version` is not a valid Rust version
+  --> $DIR/min_rust_version_invalid_attr.rs:2:1
+   |
+LL | #![clippy::msrv = "invalid.version"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.rs
new file mode 100644 (file)
index 0000000..e882d5c
--- /dev/null
@@ -0,0 +1,11 @@
+#![feature(custom_inner_attributes)]
+#![clippy::msrv = "1.40"]
+#![clippy::msrv = "=1.35.0"]
+#![clippy::msrv = "1.10.1"]
+
+mod foo {
+    #![clippy::msrv = "1"]
+    #![clippy::msrv = "1.0.0"]
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_multiple_inner_attr.stderr
new file mode 100644 (file)
index 0000000..e3ff660
--- /dev/null
@@ -0,0 +1,38 @@
+error: `msrv` is defined multiple times
+  --> $DIR/min_rust_version_multiple_inner_attr.rs:3:1
+   |
+LL | #![clippy::msrv = "=1.35.0"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first definition found here
+  --> $DIR/min_rust_version_multiple_inner_attr.rs:2:1
+   |
+LL | #![clippy::msrv = "1.40"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `msrv` is defined multiple times
+  --> $DIR/min_rust_version_multiple_inner_attr.rs:4:1
+   |
+LL | #![clippy::msrv = "1.10.1"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first definition found here
+  --> $DIR/min_rust_version_multiple_inner_attr.rs:2:1
+   |
+LL | #![clippy::msrv = "1.40"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: `msrv` is defined multiple times
+  --> $DIR/min_rust_version_multiple_inner_attr.rs:8:5
+   |
+LL |     #![clippy::msrv = "1.0.0"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: first definition found here
+  --> $DIR/min_rust_version_multiple_inner_attr.rs:7:5
+   |
+LL |     #![clippy::msrv = "1"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/src/tools/clippy/tests/ui/min_rust_version_no_patch.rs b/src/tools/clippy/tests/ui/min_rust_version_no_patch.rs
new file mode 100644 (file)
index 0000000..98fffe1
--- /dev/null
@@ -0,0 +1,14 @@
+#![allow(clippy::redundant_clone)]
+#![feature(custom_inner_attributes)]
+#![clippy::msrv = "1.0"]
+
+fn manual_strip_msrv() {
+    let s = "hello, world!";
+    if s.starts_with("hello, ") {
+        assert_eq!(s["hello, ".len()..].to_uppercase(), "WORLD!");
+    }
+}
+
+fn main() {
+    manual_strip_msrv()
+}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs b/src/tools/clippy/tests/ui/min_rust_version_outer_attr.rs
new file mode 100644 (file)
index 0000000..551948b
--- /dev/null
@@ -0,0 +1,4 @@
+#![feature(custom_inner_attributes)]
+
+#[clippy::msrv = "invalid.version"]
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr b/src/tools/clippy/tests/ui/min_rust_version_outer_attr.stderr
new file mode 100644 (file)
index 0000000..579ee7a
--- /dev/null
@@ -0,0 +1,8 @@
+error: `msrv` cannot be an outer attribute
+  --> $DIR/min_rust_version_outer_attr.rs:3:1
+   |
+LL | #[clippy::msrv = "invalid.version"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
index cc8c8e7cdaefd5a203b3e9839fe1db98dfdc9fc8..678a312f66e53af9ed72aeb8765c9db6cbbb53e1 100644 (file)
@@ -2,13 +2,22 @@
 #![allow(clippy::no_effect, clippy::unnecessary_operation)]
 
 static STATIC_ONE: usize = 2 - 1;
+static STATIC_NEG_ONE: i64 = 1 - 2;
 
 fn main() {
     10 % 1;
+    10 % -1;
     10 % 2;
+    i32::MIN % (-1); // also caught by rustc
 
     const ONE: u32 = 1 * 1;
+    const NEG_ONE: i64 = 1 - 2;
+    const INT_MIN: i64 = i64::MIN;
 
     2 % ONE;
-    5 % STATIC_ONE;
+    5 % STATIC_ONE; // NOT caught by lint
+    2 % NEG_ONE;
+    5 % STATIC_NEG_ONE; // NOT caught by lint
+    INT_MIN % NEG_ONE; // also caught by rustc
+    INT_MIN % STATIC_NEG_ONE; // ONLY caught by rustc
 }
index 6bee68360b6fbde118d04883faa81f756cbd78a5..2b2c699733852dd464507708dc41ad79a15b92eb 100644 (file)
@@ -1,13 +1,45 @@
+error: this arithmetic operation will overflow
+  --> $DIR/modulo_one.rs:11:5
+   |
+LL |     i32::MIN % (-1); // also caught by rustc
+   |     ^^^^^^^^^^^^^^^ attempt to compute the remainder of `i32::MIN % -1_i32`, which would overflow
+   |
+   = note: `#[deny(arithmetic_overflow)]` on by default
+
+error: this arithmetic operation will overflow
+  --> $DIR/modulo_one.rs:21:5
+   |
+LL |     INT_MIN % NEG_ONE; // also caught by rustc
+   |     ^^^^^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+
+error: this arithmetic operation will overflow
+  --> $DIR/modulo_one.rs:22:5
+   |
+LL |     INT_MIN % STATIC_NEG_ONE; // ONLY caught by rustc
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute the remainder of `i64::MIN % -1_i64`, which would overflow
+
 error: any number modulo 1 will be 0
-  --> $DIR/modulo_one.rs:7:5
+  --> $DIR/modulo_one.rs:8:5
    |
 LL |     10 % 1;
    |     ^^^^^^
    |
    = note: `-D clippy::modulo-one` implied by `-D warnings`
 
+error: any number modulo -1 will panic/overflow or result in 0
+  --> $DIR/modulo_one.rs:9:5
+   |
+LL |     10 % -1;
+   |     ^^^^^^^
+
+error: any number modulo -1 will panic/overflow or result in 0
+  --> $DIR/modulo_one.rs:11:5
+   |
+LL |     i32::MIN % (-1); // also caught by rustc
+   |     ^^^^^^^^^^^^^^^
+
 error: the operation is ineffective. Consider reducing it to `1`
-  --> $DIR/modulo_one.rs:10:22
+  --> $DIR/modulo_one.rs:13:22
    |
 LL |     const ONE: u32 = 1 * 1;
    |                      ^^^^^
@@ -15,16 +47,28 @@ LL |     const ONE: u32 = 1 * 1;
    = note: `-D clippy::identity-op` implied by `-D warnings`
 
 error: the operation is ineffective. Consider reducing it to `1`
-  --> $DIR/modulo_one.rs:10:22
+  --> $DIR/modulo_one.rs:13:22
    |
 LL |     const ONE: u32 = 1 * 1;
    |                      ^^^^^
 
 error: any number modulo 1 will be 0
-  --> $DIR/modulo_one.rs:12:5
+  --> $DIR/modulo_one.rs:17:5
    |
 LL |     2 % ONE;
    |     ^^^^^^^
 
-error: aborting due to 4 previous errors
+error: any number modulo -1 will panic/overflow or result in 0
+  --> $DIR/modulo_one.rs:19:5
+   |
+LL |     2 % NEG_ONE;
+   |     ^^^^^^^^^^^
+
+error: any number modulo -1 will panic/overflow or result in 0
+  --> $DIR/modulo_one.rs:21:5
+   |
+LL |     INT_MIN % NEG_ONE; // also caught by rustc
+   |     ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 11 previous errors
 
index 4f6e53577273cf1b05cc33ca9aaed6a3260abf62..0918a6868ab4b08c4958f4975209012c24faa09f 100644 (file)
@@ -22,4 +22,24 @@ fn main() {
     let sample = vec![a.clone(), "b".to_string(), "c".to_string()];
     let non_copy_contains = sample.into_iter().collect::<Vec<_>>();
     non_copy_contains.contains(&a);
+
+    // Fix #5991
+    let vec_a = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
+    let vec_b = vec_a.iter().collect::<Vec<_>>();
+    if vec_b.len() > 3 {}
+    let other_vec = vec![1, 3, 12, 4, 16, 2];
+    let we_got_the_same_numbers = other_vec.iter().filter(|item| vec_b.contains(item)).collect::<Vec<_>>();
+
+    // Fix #6297
+    let sample = [1; 5];
+    let multiple_indirect = sample.iter().collect::<Vec<_>>();
+    let sample2 = vec![2, 3];
+    if multiple_indirect.is_empty() {
+        // do something
+    } else {
+        let found = sample2
+            .iter()
+            .filter(|i| multiple_indirect.iter().any(|s| **s % **i == 0))
+            .collect::<Vec<_>>();
+    }
 }
diff --git a/src/tools/clippy/tests/ui/outer_expn_data.fixed b/src/tools/clippy/tests/ui/outer_expn_data.fixed
deleted file mode 100644 (file)
index b0b3498..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// run-rustfix
-
-#![deny(clippy::internal)]
-#![feature(rustc_private)]
-
-extern crate rustc_hir;
-extern crate rustc_lint;
-extern crate rustc_middle;
-#[macro_use]
-extern crate rustc_session;
-use rustc_hir::Expr;
-use rustc_lint::{LateContext, LateLintPass};
-
-declare_lint! {
-    pub TEST_LINT,
-    Warn,
-    ""
-}
-
-declare_lint_pass!(Pass => [TEST_LINT]);
-
-impl<'tcx> LateLintPass<'tcx> for Pass {
-    fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) {
-        let _ = expr.span.ctxt().outer_expn_data();
-    }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/outer_expn_data.rs b/src/tools/clippy/tests/ui/outer_expn_data.rs
deleted file mode 100644 (file)
index 55a3fed..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-// run-rustfix
-
-#![deny(clippy::internal)]
-#![feature(rustc_private)]
-
-extern crate rustc_hir;
-extern crate rustc_lint;
-extern crate rustc_middle;
-#[macro_use]
-extern crate rustc_session;
-use rustc_hir::Expr;
-use rustc_lint::{LateContext, LateLintPass};
-
-declare_lint! {
-    pub TEST_LINT,
-    Warn,
-    ""
-}
-
-declare_lint_pass!(Pass => [TEST_LINT]);
-
-impl<'tcx> LateLintPass<'tcx> for Pass {
-    fn check_expr(&mut self, _cx: &LateContext<'tcx>, expr: &'tcx Expr) {
-        let _ = expr.span.ctxt().outer_expn().expn_data();
-    }
-}
-
-fn main() {}
diff --git a/src/tools/clippy/tests/ui/outer_expn_data.stderr b/src/tools/clippy/tests/ui/outer_expn_data.stderr
deleted file mode 100644 (file)
index 56b6ce1..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-error: usage of `outer_expn().expn_data()`
-  --> $DIR/outer_expn_data.rs:24:34
-   |
-LL |         let _ = expr.span.ctxt().outer_expn().expn_data();
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `outer_expn_data()`
-   |
-note: the lint level is defined here
-  --> $DIR/outer_expn_data.rs:3:9
-   |
-LL | #![deny(clippy::internal)]
-   |         ^^^^^^^^^^^^^^^^
-   = note: `#[deny(clippy::outer_expn_expn_data)]` implied by `#[deny(clippy::internal)]`
-
-error: aborting due to previous error
-
index 83234c0ed92cc4fc93a53e30d2e22aa1f36d9bdb..6028323a3c84d2dee0ed4b4cbcad5424a42e5bac 100644 (file)
@@ -62,7 +62,7 @@ error: `unimplemented` should not be present in production code
 LL |     unimplemented!("{} {}", "panic with", "multiple arguments");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: `unreachable` should not be present in production code
+error: usage of the `unreachable!` macro
   --> $DIR/panicking_macros.rs:32:5
    |
 LL |     unreachable!();
@@ -70,7 +70,7 @@ LL |     unreachable!();
    |
    = note: `-D clippy::unreachable` implied by `-D warnings`
 
-error: `unreachable` should not be present in production code
+error: usage of the `unreachable!` macro
   --> $DIR/panicking_macros.rs:33:5
    |
 LL |     unreachable!("message");
@@ -78,7 +78,7 @@ LL |     unreachable!("message");
    |
    = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `unreachable` should not be present in production code
+error: usage of the `unreachable!` macro
   --> $DIR/panicking_macros.rs:34:5
    |
 LL |     unreachable!("{} {}", "panic with", "multiple arguments");
@@ -102,7 +102,7 @@ error: `unimplemented` should not be present in production code
 LL |     unimplemented!();
    |     ^^^^^^^^^^^^^^^^^
 
-error: `unreachable` should not be present in production code
+error: usage of the `unreachable!` macro
   --> $DIR/panicking_macros.rs:43:5
    |
 LL |     unreachable!();
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching.fixed
deleted file mode 100644 (file)
index aa20512..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-// run-rustfix
-
-#![warn(clippy::all)]
-#![warn(clippy::redundant_pattern_matching)]
-#![allow(
-    clippy::unit_arg,
-    unused_must_use,
-    clippy::needless_bool,
-    clippy::match_like_matches_macro,
-    clippy::unnecessary_wraps,
-    deprecated
-)]
-
-fn main() {
-    let result: Result<usize, usize> = Err(5);
-    if result.is_ok() {}
-
-    if Ok::<i32, i32>(42).is_ok() {}
-
-    if Err::<i32, i32>(42).is_err() {}
-
-    while Ok::<i32, i32>(10).is_ok() {}
-
-    while Ok::<i32, i32>(10).is_err() {}
-
-    if Ok::<i32, i32>(42).is_ok() {}
-
-    if Err::<i32, i32>(42).is_err() {}
-
-    if let Ok(x) = Ok::<i32, i32>(42) {
-        println!("{}", x);
-    }
-
-    Ok::<i32, i32>(42).is_ok();
-
-    Ok::<i32, i32>(42).is_err();
-
-    Err::<i32, i32>(42).is_err();
-
-    Err::<i32, i32>(42).is_ok();
-
-    let _ = if Ok::<usize, ()>(4).is_ok() { true } else { false };
-
-    issue5504();
-    issue6067();
-    issue6065();
-
-    let _ = if gen_res().is_ok() {
-        1
-    } else if gen_res().is_err() {
-        2
-    } else {
-        3
-    };
-}
-
-fn gen_res() -> Result<(), ()> {
-    Ok(())
-}
-
-macro_rules! m {
-    () => {
-        Some(42u32)
-    };
-}
-
-fn issue5504() {
-    fn result_opt() -> Result<Option<i32>, i32> {
-        Err(42)
-    }
-
-    fn try_result_opt() -> Result<i32, i32> {
-        while r#try!(result_opt()).is_some() {}
-        if r#try!(result_opt()).is_some() {}
-        Ok(42)
-    }
-
-    try_result_opt();
-
-    if m!().is_some() {}
-    while m!().is_some() {}
-}
-
-fn issue6065() {
-    macro_rules! if_let_in_macro {
-        ($pat:pat, $x:expr) => {
-            if let Some($pat) = $x {}
-        };
-    }
-
-    // shouldn't be linted
-    if_let_in_macro!(_, Some(42));
-}
-
-// Methods that are unstable const should not be suggested within a const context, see issue #5697.
-// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const,
-// so the following should be linted.
-const fn issue6067() {
-    if Ok::<i32, i32>(42).is_ok() {}
-
-    if Err::<i32, i32>(42).is_err() {}
-
-    while Ok::<i32, i32>(10).is_ok() {}
-
-    while Ok::<i32, i32>(10).is_err() {}
-
-    Ok::<i32, i32>(42).is_ok();
-
-    Err::<i32, i32>(42).is_err();
-}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching.rs
deleted file mode 100644 (file)
index d76f9c2..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-// run-rustfix
-
-#![warn(clippy::all)]
-#![warn(clippy::redundant_pattern_matching)]
-#![allow(
-    clippy::unit_arg,
-    unused_must_use,
-    clippy::needless_bool,
-    clippy::match_like_matches_macro,
-    clippy::unnecessary_wraps,
-    deprecated
-)]
-
-fn main() {
-    let result: Result<usize, usize> = Err(5);
-    if let Ok(_) = &result {}
-
-    if let Ok(_) = Ok::<i32, i32>(42) {}
-
-    if let Err(_) = Err::<i32, i32>(42) {}
-
-    while let Ok(_) = Ok::<i32, i32>(10) {}
-
-    while let Err(_) = Ok::<i32, i32>(10) {}
-
-    if Ok::<i32, i32>(42).is_ok() {}
-
-    if Err::<i32, i32>(42).is_err() {}
-
-    if let Ok(x) = Ok::<i32, i32>(42) {
-        println!("{}", x);
-    }
-
-    match Ok::<i32, i32>(42) {
-        Ok(_) => true,
-        Err(_) => false,
-    };
-
-    match Ok::<i32, i32>(42) {
-        Ok(_) => false,
-        Err(_) => true,
-    };
-
-    match Err::<i32, i32>(42) {
-        Ok(_) => false,
-        Err(_) => true,
-    };
-
-    match Err::<i32, i32>(42) {
-        Ok(_) => true,
-        Err(_) => false,
-    };
-
-    let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
-
-    issue5504();
-    issue6067();
-    issue6065();
-
-    let _ = if let Ok(_) = gen_res() {
-        1
-    } else if let Err(_) = gen_res() {
-        2
-    } else {
-        3
-    };
-}
-
-fn gen_res() -> Result<(), ()> {
-    Ok(())
-}
-
-macro_rules! m {
-    () => {
-        Some(42u32)
-    };
-}
-
-fn issue5504() {
-    fn result_opt() -> Result<Option<i32>, i32> {
-        Err(42)
-    }
-
-    fn try_result_opt() -> Result<i32, i32> {
-        while let Some(_) = r#try!(result_opt()) {}
-        if let Some(_) = r#try!(result_opt()) {}
-        Ok(42)
-    }
-
-    try_result_opt();
-
-    if let Some(_) = m!() {}
-    while let Some(_) = m!() {}
-}
-
-fn issue6065() {
-    macro_rules! if_let_in_macro {
-        ($pat:pat, $x:expr) => {
-            if let Some($pat) = $x {}
-        };
-    }
-
-    // shouldn't be linted
-    if_let_in_macro!(_, Some(42));
-}
-
-// Methods that are unstable const should not be suggested within a const context, see issue #5697.
-// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const,
-// so the following should be linted.
-const fn issue6067() {
-    if let Ok(_) = Ok::<i32, i32>(42) {}
-
-    if let Err(_) = Err::<i32, i32>(42) {}
-
-    while let Ok(_) = Ok::<i32, i32>(10) {}
-
-    while let Err(_) = Ok::<i32, i32>(10) {}
-
-    match Ok::<i32, i32>(42) {
-        Ok(_) => true,
-        Err(_) => false,
-    };
-
-    match Err::<i32, i32>(42) {
-        Ok(_) => false,
-        Err(_) => true,
-    };
-}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching.stderr
deleted file mode 100644 (file)
index aeb309f..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:16:12
-   |
-LL |     if let Ok(_) = &result {}
-   |     -------^^^^^---------- help: try this: `if result.is_ok()`
-   |
-   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
-
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:18:12
-   |
-LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
-   |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:20:12
-   |
-LL |     if let Err(_) = Err::<i32, i32>(42) {}
-   |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:22:15
-   |
-LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
-   |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:24:15
-   |
-LL |     while let Err(_) = Ok::<i32, i32>(10) {}
-   |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:34:5
-   |
-LL | /     match Ok::<i32, i32>(42) {
-LL | |         Ok(_) => true,
-LL | |         Err(_) => false,
-LL | |     };
-   | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:39:5
-   |
-LL | /     match Ok::<i32, i32>(42) {
-LL | |         Ok(_) => false,
-LL | |         Err(_) => true,
-LL | |     };
-   | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
-
-error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:44:5
-   |
-LL | /     match Err::<i32, i32>(42) {
-LL | |         Ok(_) => false,
-LL | |         Err(_) => true,
-LL | |     };
-   | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:49:5
-   |
-LL | /     match Err::<i32, i32>(42) {
-LL | |         Ok(_) => true,
-LL | |         Err(_) => false,
-LL | |     };
-   | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:54:20
-   |
-LL |     let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
-   |             -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
-
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:60:20
-   |
-LL |     let _ = if let Ok(_) = gen_res() {
-   |             -------^^^^^------------ help: try this: `if gen_res().is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:62:19
-   |
-LL |     } else if let Err(_) = gen_res() {
-   |            -------^^^^^^------------ help: try this: `if gen_res().is_err()`
-
-error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:85:19
-   |
-LL |         while let Some(_) = r#try!(result_opt()) {}
-   |         ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
-
-error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:86:16
-   |
-LL |         if let Some(_) = r#try!(result_opt()) {}
-   |         -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
-
-error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:92:12
-   |
-LL |     if let Some(_) = m!() {}
-   |     -------^^^^^^^------- help: try this: `if m!().is_some()`
-
-error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching.rs:93:15
-   |
-LL |     while let Some(_) = m!() {}
-   |     ----------^^^^^^^------- help: try this: `while m!().is_some()`
-
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:111:12
-   |
-LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
-   |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:113:12
-   |
-LL |     if let Err(_) = Err::<i32, i32>(42) {}
-   |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:115:15
-   |
-LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
-   |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:117:15
-   |
-LL |     while let Err(_) = Ok::<i32, i32>(10) {}
-   |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
-
-error: redundant pattern matching, consider using `is_ok()`
-  --> $DIR/redundant_pattern_matching.rs:119:5
-   |
-LL | /     match Ok::<i32, i32>(42) {
-LL | |         Ok(_) => true,
-LL | |         Err(_) => false,
-LL | |     };
-   | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
-
-error: redundant pattern matching, consider using `is_err()`
-  --> $DIR/redundant_pattern_matching.rs:124:5
-   |
-LL | /     match Err::<i32, i32>(42) {
-LL | |         Ok(_) => false,
-LL | |         Err(_) => true,
-LL | |     };
-   | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
-
-error: aborting due to 22 previous errors
-
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.fixed
new file mode 100644 (file)
index 0000000..acc8de5
--- /dev/null
@@ -0,0 +1,73 @@
+// run-rustfix
+
+#![warn(clippy::all)]
+#![warn(clippy::redundant_pattern_matching)]
+#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+
+use std::net::{
+    IpAddr::{self, V4, V6},
+    Ipv4Addr, Ipv6Addr,
+};
+
+fn main() {
+    let ipaddr: IpAddr = V4(Ipv4Addr::LOCALHOST);
+    if ipaddr.is_ipv4() {}
+
+    if V4(Ipv4Addr::LOCALHOST).is_ipv4() {}
+
+    if V6(Ipv6Addr::LOCALHOST).is_ipv6() {}
+
+    while V4(Ipv4Addr::LOCALHOST).is_ipv4() {}
+
+    while V6(Ipv6Addr::LOCALHOST).is_ipv6() {}
+
+    if V4(Ipv4Addr::LOCALHOST).is_ipv4() {}
+
+    if V6(Ipv6Addr::LOCALHOST).is_ipv6() {}
+
+    if let V4(ipaddr) = V4(Ipv4Addr::LOCALHOST) {
+        println!("{}", ipaddr);
+    }
+
+    V4(Ipv4Addr::LOCALHOST).is_ipv4();
+
+    V4(Ipv4Addr::LOCALHOST).is_ipv6();
+
+    V6(Ipv6Addr::LOCALHOST).is_ipv6();
+
+    V6(Ipv6Addr::LOCALHOST).is_ipv4();
+
+    let _ = if V4(Ipv4Addr::LOCALHOST).is_ipv4() {
+        true
+    } else {
+        false
+    };
+
+    ipaddr_const();
+
+    let _ = if gen_ipaddr().is_ipv4() {
+        1
+    } else if gen_ipaddr().is_ipv6() {
+        2
+    } else {
+        3
+    };
+}
+
+fn gen_ipaddr() -> IpAddr {
+    V4(Ipv4Addr::LOCALHOST)
+}
+
+const fn ipaddr_const() {
+    if V4(Ipv4Addr::LOCALHOST).is_ipv4() {}
+
+    if V6(Ipv6Addr::LOCALHOST).is_ipv6() {}
+
+    while V4(Ipv4Addr::LOCALHOST).is_ipv4() {}
+
+    while V6(Ipv6Addr::LOCALHOST).is_ipv6() {}
+
+    V4(Ipv4Addr::LOCALHOST).is_ipv4();
+
+    V6(Ipv6Addr::LOCALHOST).is_ipv6();
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.rs
new file mode 100644 (file)
index 0000000..678d91c
--- /dev/null
@@ -0,0 +1,91 @@
+// run-rustfix
+
+#![warn(clippy::all)]
+#![warn(clippy::redundant_pattern_matching)]
+#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+
+use std::net::{
+    IpAddr::{self, V4, V6},
+    Ipv4Addr, Ipv6Addr,
+};
+
+fn main() {
+    let ipaddr: IpAddr = V4(Ipv4Addr::LOCALHOST);
+    if let V4(_) = &ipaddr {}
+
+    if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
+
+    if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
+
+    while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
+
+    while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
+
+    if V4(Ipv4Addr::LOCALHOST).is_ipv4() {}
+
+    if V6(Ipv6Addr::LOCALHOST).is_ipv6() {}
+
+    if let V4(ipaddr) = V4(Ipv4Addr::LOCALHOST) {
+        println!("{}", ipaddr);
+    }
+
+    match V4(Ipv4Addr::LOCALHOST) {
+        V4(_) => true,
+        V6(_) => false,
+    };
+
+    match V4(Ipv4Addr::LOCALHOST) {
+        V4(_) => false,
+        V6(_) => true,
+    };
+
+    match V6(Ipv6Addr::LOCALHOST) {
+        V4(_) => false,
+        V6(_) => true,
+    };
+
+    match V6(Ipv6Addr::LOCALHOST) {
+        V4(_) => true,
+        V6(_) => false,
+    };
+
+    let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) {
+        true
+    } else {
+        false
+    };
+
+    ipaddr_const();
+
+    let _ = if let V4(_) = gen_ipaddr() {
+        1
+    } else if let V6(_) = gen_ipaddr() {
+        2
+    } else {
+        3
+    };
+}
+
+fn gen_ipaddr() -> IpAddr {
+    V4(Ipv4Addr::LOCALHOST)
+}
+
+const fn ipaddr_const() {
+    if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
+
+    if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
+
+    while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
+
+    while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
+
+    match V4(Ipv4Addr::LOCALHOST) {
+        V4(_) => true,
+        V6(_) => false,
+    };
+
+    match V6(Ipv6Addr::LOCALHOST) {
+        V4(_) => false,
+        V6(_) => true,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_ipaddr.stderr
new file mode 100644 (file)
index 0000000..caf458c
--- /dev/null
@@ -0,0 +1,130 @@
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:14:12
+   |
+LL |     if let V4(_) = &ipaddr {}
+   |     -------^^^^^---------- help: try this: `if ipaddr.is_ipv4()`
+   |
+   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
+
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:16:12
+   |
+LL |     if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
+   |     -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
+
+error: redundant pattern matching, consider using `is_ipv6()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:18:12
+   |
+LL |     if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
+   |     -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()`
+
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:20:15
+   |
+LL |     while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
+   |     ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()`
+
+error: redundant pattern matching, consider using `is_ipv6()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:22:15
+   |
+LL |     while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
+   |     ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()`
+
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:32:5
+   |
+LL | /     match V4(Ipv4Addr::LOCALHOST) {
+LL | |         V4(_) => true,
+LL | |         V6(_) => false,
+LL | |     };
+   | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()`
+
+error: redundant pattern matching, consider using `is_ipv6()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:37:5
+   |
+LL | /     match V4(Ipv4Addr::LOCALHOST) {
+LL | |         V4(_) => false,
+LL | |         V6(_) => true,
+LL | |     };
+   | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv6()`
+
+error: redundant pattern matching, consider using `is_ipv6()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:42:5
+   |
+LL | /     match V6(Ipv6Addr::LOCALHOST) {
+LL | |         V4(_) => false,
+LL | |         V6(_) => true,
+LL | |     };
+   | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()`
+
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:47:5
+   |
+LL | /     match V6(Ipv6Addr::LOCALHOST) {
+LL | |         V4(_) => true,
+LL | |         V6(_) => false,
+LL | |     };
+   | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv4()`
+
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:52:20
+   |
+LL |     let _ = if let V4(_) = V4(Ipv4Addr::LOCALHOST) {
+   |             -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
+
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:60:20
+   |
+LL |     let _ = if let V4(_) = gen_ipaddr() {
+   |             -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv4()`
+
+error: redundant pattern matching, consider using `is_ipv6()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:62:19
+   |
+LL |     } else if let V6(_) = gen_ipaddr() {
+   |            -------^^^^^--------------- help: try this: `if gen_ipaddr().is_ipv6()`
+
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:74:12
+   |
+LL |     if let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
+   |     -------^^^^^-------------------------- help: try this: `if V4(Ipv4Addr::LOCALHOST).is_ipv4()`
+
+error: redundant pattern matching, consider using `is_ipv6()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:76:12
+   |
+LL |     if let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
+   |     -------^^^^^-------------------------- help: try this: `if V6(Ipv6Addr::LOCALHOST).is_ipv6()`
+
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:78:15
+   |
+LL |     while let V4(_) = V4(Ipv4Addr::LOCALHOST) {}
+   |     ----------^^^^^-------------------------- help: try this: `while V4(Ipv4Addr::LOCALHOST).is_ipv4()`
+
+error: redundant pattern matching, consider using `is_ipv6()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:80:15
+   |
+LL |     while let V6(_) = V6(Ipv6Addr::LOCALHOST) {}
+   |     ----------^^^^^-------------------------- help: try this: `while V6(Ipv6Addr::LOCALHOST).is_ipv6()`
+
+error: redundant pattern matching, consider using `is_ipv4()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:82:5
+   |
+LL | /     match V4(Ipv4Addr::LOCALHOST) {
+LL | |         V4(_) => true,
+LL | |         V6(_) => false,
+LL | |     };
+   | |_____^ help: try this: `V4(Ipv4Addr::LOCALHOST).is_ipv4()`
+
+error: redundant pattern matching, consider using `is_ipv6()`
+  --> $DIR/redundant_pattern_matching_ipaddr.rs:87:5
+   |
+LL | /     match V6(Ipv6Addr::LOCALHOST) {
+LL | |         V4(_) => false,
+LL | |         V6(_) => true,
+LL | |     };
+   | |_____^ help: try this: `V6(Ipv6Addr::LOCALHOST).is_ipv6()`
+
+error: aborting due to 18 previous errors
+
index 499b975b2bb475d9343b556d03db861c02e0086f..66f580a0a683426e250479c01e5a8a6c1ff86dd6 100644 (file)
@@ -2,13 +2,7 @@
 
 #![warn(clippy::all)]
 #![warn(clippy::redundant_pattern_matching)]
-#![allow(
-    clippy::unit_arg,
-    unused_must_use,
-    clippy::needless_bool,
-    clippy::match_like_matches_macro,
-    deprecated
-)]
+#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
 
 fn main() {
     if None::<()>.is_none() {}
@@ -43,8 +37,7 @@ fn main() {
     let _ = None::<()>.is_none();
 
     let opt = Some(false);
-    let x = if opt.is_some() { true } else { false };
-    takes_bool(x);
+    let _ = if opt.is_some() { true } else { false };
 
     issue6067();
 
@@ -61,8 +54,6 @@ fn gen_opt() -> Option<()> {
     None
 }
 
-fn takes_bool(_: bool) {}
-
 fn foo() {}
 
 fn bar() {}
index 2a98435e7902e8aa7b246c71322fc30ed26e2929..f18b27b8b95c30b4cc33e5756e2d51d4bf5bcd75 100644 (file)
@@ -2,13 +2,7 @@
 
 #![warn(clippy::all)]
 #![warn(clippy::redundant_pattern_matching)]
-#![allow(
-    clippy::unit_arg,
-    unused_must_use,
-    clippy::needless_bool,
-    clippy::match_like_matches_macro,
-    deprecated
-)]
+#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
 
 fn main() {
     if let None = None::<()> {}
@@ -52,8 +46,7 @@ fn main() {
     };
 
     let opt = Some(false);
-    let x = if let Some(_) = opt { true } else { false };
-    takes_bool(x);
+    let _ = if let Some(_) = opt { true } else { false };
 
     issue6067();
 
@@ -70,8 +63,6 @@ fn gen_opt() -> Option<()> {
     None
 }
 
-fn takes_bool(_: bool) {}
-
 fn foo() {}
 
 fn bar() {}
index eebb34484913e9794b774a805bc38ff9ad609616..58482a0ab70dcbe0c4c1a2bef214861dcbd06d3a 100644 (file)
@@ -1,5 +1,5 @@
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:14:12
+  --> $DIR/redundant_pattern_matching_option.rs:8:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
@@ -7,43 +7,43 @@ LL |     if let None = None::<()> {}
    = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:16:12
+  --> $DIR/redundant_pattern_matching_option.rs:10:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:18:12
+  --> $DIR/redundant_pattern_matching_option.rs:12:12
    |
 LL |     if let Some(_) = Some(42) {
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:24:15
+  --> $DIR/redundant_pattern_matching_option.rs:18:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:26:15
+  --> $DIR/redundant_pattern_matching_option.rs:20:15
    |
 LL |     while let None = Some(42) {}
    |     ----------^^^^----------- help: try this: `while Some(42).is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:28:15
+  --> $DIR/redundant_pattern_matching_option.rs:22:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:31:15
+  --> $DIR/redundant_pattern_matching_option.rs:25:15
    |
 LL |     while let Some(_) = v.pop() {
    |     ----------^^^^^^^---------- help: try this: `while v.pop().is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:39:5
+  --> $DIR/redundant_pattern_matching_option.rs:33:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -52,7 +52,7 @@ LL | |     };
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:44:5
+  --> $DIR/redundant_pattern_matching_option.rs:38:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
@@ -61,7 +61,7 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:49:13
+  --> $DIR/redundant_pattern_matching_option.rs:43:13
    |
 LL |       let _ = match None::<()> {
    |  _____________^
@@ -71,49 +71,49 @@ LL | |     };
    | |_____^ help: try this: `None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:55:20
+  --> $DIR/redundant_pattern_matching_option.rs:49:20
    |
-LL |     let x = if let Some(_) = opt { true } else { false };
+LL |     let _ = if let Some(_) = opt { true } else { false };
    |             -------^^^^^^^------ help: try this: `if opt.is_some()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:60:20
+  --> $DIR/redundant_pattern_matching_option.rs:53:20
    |
 LL |     let _ = if let Some(_) = gen_opt() {
    |             -------^^^^^^^------------ help: try this: `if gen_opt().is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:62:19
+  --> $DIR/redundant_pattern_matching_option.rs:55:19
    |
 LL |     } else if let None = gen_opt() {
    |            -------^^^^------------ help: try this: `if gen_opt().is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:83:12
+  --> $DIR/redundant_pattern_matching_option.rs:74:12
    |
 LL |     if let Some(_) = Some(42) {}
    |     -------^^^^^^^----------- help: try this: `if Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:85:12
+  --> $DIR/redundant_pattern_matching_option.rs:76:12
    |
 LL |     if let None = None::<()> {}
    |     -------^^^^------------- help: try this: `if None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:87:15
+  --> $DIR/redundant_pattern_matching_option.rs:78:15
    |
 LL |     while let Some(_) = Some(42) {}
    |     ----------^^^^^^^----------- help: try this: `while Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:89:15
+  --> $DIR/redundant_pattern_matching_option.rs:80:15
    |
 LL |     while let None = None::<()> {}
    |     ----------^^^^------------- help: try this: `while None::<()>.is_none()`
 
 error: redundant pattern matching, consider using `is_some()`
-  --> $DIR/redundant_pattern_matching_option.rs:91:5
+  --> $DIR/redundant_pattern_matching_option.rs:82:5
    |
 LL | /     match Some(42) {
 LL | |         Some(_) => true,
@@ -122,7 +122,7 @@ LL | |     };
    | |_____^ help: try this: `Some(42).is_some()`
 
 error: redundant pattern matching, consider using `is_none()`
-  --> $DIR/redundant_pattern_matching_option.rs:96:5
+  --> $DIR/redundant_pattern_matching_option.rs:87:5
    |
 LL | /     match None::<()> {
 LL | |         Some(_) => false,
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.fixed
new file mode 100644 (file)
index 0000000..465aa80
--- /dev/null
@@ -0,0 +1,70 @@
+// run-rustfix
+
+#![warn(clippy::all)]
+#![warn(clippy::redundant_pattern_matching)]
+#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+
+use std::task::Poll::{self, Pending, Ready};
+
+fn main() {
+    if Pending::<()>.is_pending() {}
+
+    if Ready(42).is_ready() {}
+
+    if Ready(42).is_ready() {
+        foo();
+    } else {
+        bar();
+    }
+
+    while Ready(42).is_ready() {}
+
+    while Ready(42).is_pending() {}
+
+    while Pending::<()>.is_pending() {}
+
+    if Pending::<i32>.is_pending() {}
+
+    if Ready(42).is_ready() {}
+
+    Ready(42).is_ready();
+
+    Pending::<()>.is_pending();
+
+    let _ = Pending::<()>.is_pending();
+
+    let poll = Ready(false);
+    let _ = if poll.is_ready() { true } else { false };
+
+    poll_const();
+
+    let _ = if gen_poll().is_ready() {
+        1
+    } else if gen_poll().is_pending() {
+        2
+    } else {
+        3
+    };
+}
+
+fn gen_poll() -> Poll<()> {
+    Pending
+}
+
+fn foo() {}
+
+fn bar() {}
+
+const fn poll_const() {
+    if Ready(42).is_ready() {}
+
+    if Pending::<()>.is_pending() {}
+
+    while Ready(42).is_ready() {}
+
+    while Pending::<()>.is_pending() {}
+
+    Ready(42).is_ready();
+
+    Pending::<()>.is_pending();
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.rs
new file mode 100644 (file)
index 0000000..7891ff3
--- /dev/null
@@ -0,0 +1,85 @@
+// run-rustfix
+
+#![warn(clippy::all)]
+#![warn(clippy::redundant_pattern_matching)]
+#![allow(unused_must_use, clippy::needless_bool, clippy::match_like_matches_macro)]
+
+use std::task::Poll::{self, Pending, Ready};
+
+fn main() {
+    if let Pending = Pending::<()> {}
+
+    if let Ready(_) = Ready(42) {}
+
+    if let Ready(_) = Ready(42) {
+        foo();
+    } else {
+        bar();
+    }
+
+    while let Ready(_) = Ready(42) {}
+
+    while let Pending = Ready(42) {}
+
+    while let Pending = Pending::<()> {}
+
+    if Pending::<i32>.is_pending() {}
+
+    if Ready(42).is_ready() {}
+
+    match Ready(42) {
+        Ready(_) => true,
+        Pending => false,
+    };
+
+    match Pending::<()> {
+        Ready(_) => false,
+        Pending => true,
+    };
+
+    let _ = match Pending::<()> {
+        Ready(_) => false,
+        Pending => true,
+    };
+
+    let poll = Ready(false);
+    let _ = if let Ready(_) = poll { true } else { false };
+
+    poll_const();
+
+    let _ = if let Ready(_) = gen_poll() {
+        1
+    } else if let Pending = gen_poll() {
+        2
+    } else {
+        3
+    };
+}
+
+fn gen_poll() -> Poll<()> {
+    Pending
+}
+
+fn foo() {}
+
+fn bar() {}
+
+const fn poll_const() {
+    if let Ready(_) = Ready(42) {}
+
+    if let Pending = Pending::<()> {}
+
+    while let Ready(_) = Ready(42) {}
+
+    while let Pending = Pending::<()> {}
+
+    match Ready(42) {
+        Ready(_) => true,
+        Pending => false,
+    };
+
+    match Pending::<()> {
+        Ready(_) => false,
+        Pending => true,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_poll.stderr
new file mode 100644 (file)
index 0000000..5ffc6c4
--- /dev/null
@@ -0,0 +1,128 @@
+error: redundant pattern matching, consider using `is_pending()`
+  --> $DIR/redundant_pattern_matching_poll.rs:10:12
+   |
+LL |     if let Pending = Pending::<()> {}
+   |     -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
+   |
+   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
+
+error: redundant pattern matching, consider using `is_ready()`
+  --> $DIR/redundant_pattern_matching_poll.rs:12:12
+   |
+LL |     if let Ready(_) = Ready(42) {}
+   |     -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
+
+error: redundant pattern matching, consider using `is_ready()`
+  --> $DIR/redundant_pattern_matching_poll.rs:14:12
+   |
+LL |     if let Ready(_) = Ready(42) {
+   |     -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
+
+error: redundant pattern matching, consider using `is_ready()`
+  --> $DIR/redundant_pattern_matching_poll.rs:20:15
+   |
+LL |     while let Ready(_) = Ready(42) {}
+   |     ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
+
+error: redundant pattern matching, consider using `is_pending()`
+  --> $DIR/redundant_pattern_matching_poll.rs:22:15
+   |
+LL |     while let Pending = Ready(42) {}
+   |     ----------^^^^^^^------------ help: try this: `while Ready(42).is_pending()`
+
+error: redundant pattern matching, consider using `is_pending()`
+  --> $DIR/redundant_pattern_matching_poll.rs:24:15
+   |
+LL |     while let Pending = Pending::<()> {}
+   |     ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
+
+error: redundant pattern matching, consider using `is_ready()`
+  --> $DIR/redundant_pattern_matching_poll.rs:30:5
+   |
+LL | /     match Ready(42) {
+LL | |         Ready(_) => true,
+LL | |         Pending => false,
+LL | |     };
+   | |_____^ help: try this: `Ready(42).is_ready()`
+
+error: redundant pattern matching, consider using `is_pending()`
+  --> $DIR/redundant_pattern_matching_poll.rs:35:5
+   |
+LL | /     match Pending::<()> {
+LL | |         Ready(_) => false,
+LL | |         Pending => true,
+LL | |     };
+   | |_____^ help: try this: `Pending::<()>.is_pending()`
+
+error: redundant pattern matching, consider using `is_pending()`
+  --> $DIR/redundant_pattern_matching_poll.rs:40:13
+   |
+LL |       let _ = match Pending::<()> {
+   |  _____________^
+LL | |         Ready(_) => false,
+LL | |         Pending => true,
+LL | |     };
+   | |_____^ help: try this: `Pending::<()>.is_pending()`
+
+error: redundant pattern matching, consider using `is_ready()`
+  --> $DIR/redundant_pattern_matching_poll.rs:46:20
+   |
+LL |     let _ = if let Ready(_) = poll { true } else { false };
+   |             -------^^^^^^^^------- help: try this: `if poll.is_ready()`
+
+error: redundant pattern matching, consider using `is_ready()`
+  --> $DIR/redundant_pattern_matching_poll.rs:50:20
+   |
+LL |     let _ = if let Ready(_) = gen_poll() {
+   |             -------^^^^^^^^------------- help: try this: `if gen_poll().is_ready()`
+
+error: redundant pattern matching, consider using `is_pending()`
+  --> $DIR/redundant_pattern_matching_poll.rs:52:19
+   |
+LL |     } else if let Pending = gen_poll() {
+   |            -------^^^^^^^------------- help: try this: `if gen_poll().is_pending()`
+
+error: redundant pattern matching, consider using `is_ready()`
+  --> $DIR/redundant_pattern_matching_poll.rs:68:12
+   |
+LL |     if let Ready(_) = Ready(42) {}
+   |     -------^^^^^^^^------------ help: try this: `if Ready(42).is_ready()`
+
+error: redundant pattern matching, consider using `is_pending()`
+  --> $DIR/redundant_pattern_matching_poll.rs:70:12
+   |
+LL |     if let Pending = Pending::<()> {}
+   |     -------^^^^^^^---------------- help: try this: `if Pending::<()>.is_pending()`
+
+error: redundant pattern matching, consider using `is_ready()`
+  --> $DIR/redundant_pattern_matching_poll.rs:72:15
+   |
+LL |     while let Ready(_) = Ready(42) {}
+   |     ----------^^^^^^^^------------ help: try this: `while Ready(42).is_ready()`
+
+error: redundant pattern matching, consider using `is_pending()`
+  --> $DIR/redundant_pattern_matching_poll.rs:74:15
+   |
+LL |     while let Pending = Pending::<()> {}
+   |     ----------^^^^^^^---------------- help: try this: `while Pending::<()>.is_pending()`
+
+error: redundant pattern matching, consider using `is_ready()`
+  --> $DIR/redundant_pattern_matching_poll.rs:76:5
+   |
+LL | /     match Ready(42) {
+LL | |         Ready(_) => true,
+LL | |         Pending => false,
+LL | |     };
+   | |_____^ help: try this: `Ready(42).is_ready()`
+
+error: redundant pattern matching, consider using `is_pending()`
+  --> $DIR/redundant_pattern_matching_poll.rs:81:5
+   |
+LL | /     match Pending::<()> {
+LL | |         Ready(_) => false,
+LL | |         Pending => true,
+LL | |     };
+   | |_____^ help: try this: `Pending::<()>.is_pending()`
+
+error: aborting due to 18 previous errors
+
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.fixed
new file mode 100644 (file)
index 0000000..e94c570
--- /dev/null
@@ -0,0 +1,109 @@
+// run-rustfix
+
+#![warn(clippy::all)]
+#![warn(clippy::redundant_pattern_matching)]
+#![allow(
+    unused_must_use,
+    clippy::needless_bool,
+    clippy::match_like_matches_macro,
+    clippy::unnecessary_wraps,
+    deprecated
+)]
+
+fn main() {
+    let result: Result<usize, usize> = Err(5);
+    if result.is_ok() {}
+
+    if Ok::<i32, i32>(42).is_ok() {}
+
+    if Err::<i32, i32>(42).is_err() {}
+
+    while Ok::<i32, i32>(10).is_ok() {}
+
+    while Ok::<i32, i32>(10).is_err() {}
+
+    if Ok::<i32, i32>(42).is_ok() {}
+
+    if Err::<i32, i32>(42).is_err() {}
+
+    if let Ok(x) = Ok::<i32, i32>(42) {
+        println!("{}", x);
+    }
+
+    Ok::<i32, i32>(42).is_ok();
+
+    Ok::<i32, i32>(42).is_err();
+
+    Err::<i32, i32>(42).is_err();
+
+    Err::<i32, i32>(42).is_ok();
+
+    let _ = if Ok::<usize, ()>(4).is_ok() { true } else { false };
+
+    issue5504();
+    issue6067();
+    issue6065();
+
+    let _ = if gen_res().is_ok() {
+        1
+    } else if gen_res().is_err() {
+        2
+    } else {
+        3
+    };
+}
+
+fn gen_res() -> Result<(), ()> {
+    Ok(())
+}
+
+macro_rules! m {
+    () => {
+        Some(42u32)
+    };
+}
+
+fn issue5504() {
+    fn result_opt() -> Result<Option<i32>, i32> {
+        Err(42)
+    }
+
+    fn try_result_opt() -> Result<i32, i32> {
+        while r#try!(result_opt()).is_some() {}
+        if r#try!(result_opt()).is_some() {}
+        Ok(42)
+    }
+
+    try_result_opt();
+
+    if m!().is_some() {}
+    while m!().is_some() {}
+}
+
+fn issue6065() {
+    macro_rules! if_let_in_macro {
+        ($pat:pat, $x:expr) => {
+            if let Some($pat) = $x {}
+        };
+    }
+
+    // shouldn't be linted
+    if_let_in_macro!(_, Some(42));
+}
+
+// Methods that are unstable const should not be suggested within a const context, see issue #5697.
+// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const,
+// so the following should be linted.
+const fn issue6067() {
+    if Ok::<i32, i32>(42).is_ok() {}
+
+    if Err::<i32, i32>(42).is_err() {}
+
+    while Ok::<i32, i32>(10).is_ok() {}
+
+    while Ok::<i32, i32>(10).is_err() {}
+
+    Ok::<i32, i32>(42).is_ok();
+
+    Err::<i32, i32>(42).is_err();
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.rs
new file mode 100644 (file)
index 0000000..5d17529
--- /dev/null
@@ -0,0 +1,127 @@
+// run-rustfix
+
+#![warn(clippy::all)]
+#![warn(clippy::redundant_pattern_matching)]
+#![allow(
+    unused_must_use,
+    clippy::needless_bool,
+    clippy::match_like_matches_macro,
+    clippy::unnecessary_wraps,
+    deprecated
+)]
+
+fn main() {
+    let result: Result<usize, usize> = Err(5);
+    if let Ok(_) = &result {}
+
+    if let Ok(_) = Ok::<i32, i32>(42) {}
+
+    if let Err(_) = Err::<i32, i32>(42) {}
+
+    while let Ok(_) = Ok::<i32, i32>(10) {}
+
+    while let Err(_) = Ok::<i32, i32>(10) {}
+
+    if Ok::<i32, i32>(42).is_ok() {}
+
+    if Err::<i32, i32>(42).is_err() {}
+
+    if let Ok(x) = Ok::<i32, i32>(42) {
+        println!("{}", x);
+    }
+
+    match Ok::<i32, i32>(42) {
+        Ok(_) => true,
+        Err(_) => false,
+    };
+
+    match Ok::<i32, i32>(42) {
+        Ok(_) => false,
+        Err(_) => true,
+    };
+
+    match Err::<i32, i32>(42) {
+        Ok(_) => false,
+        Err(_) => true,
+    };
+
+    match Err::<i32, i32>(42) {
+        Ok(_) => true,
+        Err(_) => false,
+    };
+
+    let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
+
+    issue5504();
+    issue6067();
+    issue6065();
+
+    let _ = if let Ok(_) = gen_res() {
+        1
+    } else if let Err(_) = gen_res() {
+        2
+    } else {
+        3
+    };
+}
+
+fn gen_res() -> Result<(), ()> {
+    Ok(())
+}
+
+macro_rules! m {
+    () => {
+        Some(42u32)
+    };
+}
+
+fn issue5504() {
+    fn result_opt() -> Result<Option<i32>, i32> {
+        Err(42)
+    }
+
+    fn try_result_opt() -> Result<i32, i32> {
+        while let Some(_) = r#try!(result_opt()) {}
+        if let Some(_) = r#try!(result_opt()) {}
+        Ok(42)
+    }
+
+    try_result_opt();
+
+    if let Some(_) = m!() {}
+    while let Some(_) = m!() {}
+}
+
+fn issue6065() {
+    macro_rules! if_let_in_macro {
+        ($pat:pat, $x:expr) => {
+            if let Some($pat) = $x {}
+        };
+    }
+
+    // shouldn't be linted
+    if_let_in_macro!(_, Some(42));
+}
+
+// Methods that are unstable const should not be suggested within a const context, see issue #5697.
+// However, in Rust 1.48.0 the methods `is_ok` and `is_err` of `Result` were stabilized as const,
+// so the following should be linted.
+const fn issue6067() {
+    if let Ok(_) = Ok::<i32, i32>(42) {}
+
+    if let Err(_) = Err::<i32, i32>(42) {}
+
+    while let Ok(_) = Ok::<i32, i32>(10) {}
+
+    while let Err(_) = Ok::<i32, i32>(10) {}
+
+    match Ok::<i32, i32>(42) {
+        Ok(_) => true,
+        Err(_) => false,
+    };
+
+    match Err::<i32, i32>(42) {
+        Ok(_) => false,
+        Err(_) => true,
+    };
+}
diff --git a/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr b/src/tools/clippy/tests/ui/redundant_pattern_matching_result.stderr
new file mode 100644 (file)
index 0000000..d6a46ba
--- /dev/null
@@ -0,0 +1,154 @@
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:15:12
+   |
+LL |     if let Ok(_) = &result {}
+   |     -------^^^^^---------- help: try this: `if result.is_ok()`
+   |
+   = note: `-D clippy::redundant-pattern-matching` implied by `-D warnings`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:17:12
+   |
+LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
+   |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:19:12
+   |
+LL |     if let Err(_) = Err::<i32, i32>(42) {}
+   |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:21:15
+   |
+LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
+   |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:23:15
+   |
+LL |     while let Err(_) = Ok::<i32, i32>(10) {}
+   |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:33:5
+   |
+LL | /     match Ok::<i32, i32>(42) {
+LL | |         Ok(_) => true,
+LL | |         Err(_) => false,
+LL | |     };
+   | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:38:5
+   |
+LL | /     match Ok::<i32, i32>(42) {
+LL | |         Ok(_) => false,
+LL | |         Err(_) => true,
+LL | |     };
+   | |_____^ help: try this: `Ok::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:43:5
+   |
+LL | /     match Err::<i32, i32>(42) {
+LL | |         Ok(_) => false,
+LL | |         Err(_) => true,
+LL | |     };
+   | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:48:5
+   |
+LL | /     match Err::<i32, i32>(42) {
+LL | |         Ok(_) => true,
+LL | |         Err(_) => false,
+LL | |     };
+   | |_____^ help: try this: `Err::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:53:20
+   |
+LL |     let _ = if let Ok(_) = Ok::<usize, ()>(4) { true } else { false };
+   |             -------^^^^^--------------------- help: try this: `if Ok::<usize, ()>(4).is_ok()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:59:20
+   |
+LL |     let _ = if let Ok(_) = gen_res() {
+   |             -------^^^^^------------ help: try this: `if gen_res().is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:61:19
+   |
+LL |     } else if let Err(_) = gen_res() {
+   |            -------^^^^^^------------ help: try this: `if gen_res().is_err()`
+
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_result.rs:84:19
+   |
+LL |         while let Some(_) = r#try!(result_opt()) {}
+   |         ----------^^^^^^^----------------------- help: try this: `while r#try!(result_opt()).is_some()`
+
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_result.rs:85:16
+   |
+LL |         if let Some(_) = r#try!(result_opt()) {}
+   |         -------^^^^^^^----------------------- help: try this: `if r#try!(result_opt()).is_some()`
+
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_result.rs:91:12
+   |
+LL |     if let Some(_) = m!() {}
+   |     -------^^^^^^^------- help: try this: `if m!().is_some()`
+
+error: redundant pattern matching, consider using `is_some()`
+  --> $DIR/redundant_pattern_matching_result.rs:92:15
+   |
+LL |     while let Some(_) = m!() {}
+   |     ----------^^^^^^^------- help: try this: `while m!().is_some()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:110:12
+   |
+LL |     if let Ok(_) = Ok::<i32, i32>(42) {}
+   |     -------^^^^^--------------------- help: try this: `if Ok::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:112:12
+   |
+LL |     if let Err(_) = Err::<i32, i32>(42) {}
+   |     -------^^^^^^---------------------- help: try this: `if Err::<i32, i32>(42).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:114:15
+   |
+LL |     while let Ok(_) = Ok::<i32, i32>(10) {}
+   |     ----------^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:116:15
+   |
+LL |     while let Err(_) = Ok::<i32, i32>(10) {}
+   |     ----------^^^^^^--------------------- help: try this: `while Ok::<i32, i32>(10).is_err()`
+
+error: redundant pattern matching, consider using `is_ok()`
+  --> $DIR/redundant_pattern_matching_result.rs:118:5
+   |
+LL | /     match Ok::<i32, i32>(42) {
+LL | |         Ok(_) => true,
+LL | |         Err(_) => false,
+LL | |     };
+   | |_____^ help: try this: `Ok::<i32, i32>(42).is_ok()`
+
+error: redundant pattern matching, consider using `is_err()`
+  --> $DIR/redundant_pattern_matching_result.rs:123:5
+   |
+LL | /     match Err::<i32, i32>(42) {
+LL | |         Ok(_) => false,
+LL | |         Err(_) => true,
+LL | |     };
+   | |_____^ help: try this: `Err::<i32, i32>(42).is_err()`
+
+error: aborting due to 22 previous errors
+
diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count.rs b/src/tools/clippy/tests/ui/size_of_in_element_count.rs
new file mode 100644 (file)
index 0000000..b13e390
--- /dev/null
@@ -0,0 +1,61 @@
+#![warn(clippy::size_of_in_element_count)]
+#![allow(clippy::ptr_offset_with_cast)]
+
+use std::mem::{size_of, size_of_val};
+use std::ptr::{
+    copy, copy_nonoverlapping, slice_from_raw_parts, slice_from_raw_parts_mut, swap_nonoverlapping, write_bytes,
+};
+use std::slice::{from_raw_parts, from_raw_parts_mut};
+
+fn main() {
+    const SIZE: usize = 128;
+    const HALF_SIZE: usize = SIZE / 2;
+    const DOUBLE_SIZE: usize = SIZE * 2;
+    let mut x = [2u8; SIZE];
+    let mut y = [2u8; SIZE];
+
+    // Count is size_of (Should trigger the lint)
+    unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
+
+    unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
+    unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
+
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
+
+    unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
+    unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
+
+    unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
+
+    slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
+    slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
+
+    unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+    unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
+
+    unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
+    y.as_ptr().wrapping_sub(size_of::<u8>());
+    unsafe { y.as_ptr().add(size_of::<u8>()) };
+    y.as_mut_ptr().wrapping_add(size_of::<u8>());
+    unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
+    y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
+
+    // Count expression involving multiplication of size_of (Should trigger the lint)
+    unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+
+    // Count expression involving nested multiplications of size_of (Should trigger the lint)
+    unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
+
+    // Count expression involving divisions of size_of (Should trigger the lint)
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
+
+    // No size_of calls (Should not trigger the lint)
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), SIZE) };
+
+    // Different types for pointee and size_of (Should not trigger the lint)
+    unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u16>() / 2 * SIZE) };
+}
diff --git a/src/tools/clippy/tests/ui/size_of_in_element_count.stderr b/src/tools/clippy/tests/ui/size_of_in_element_count.stderr
new file mode 100644 (file)
index 0000000..8cf3612
--- /dev/null
@@ -0,0 +1,195 @@
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:18:68
+   |
+LL |     unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+   |                                                                    ^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:19:62
+   |
+LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
+   |                                                              ^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:21:49
+   |
+LL |     unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
+   |                                                 ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:22:64
+   |
+LL |     unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
+   |                                                                ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:23:51
+   |
+LL |     unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
+   |                                                   ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:24:66
+   |
+LL |     unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
+   |                                                                  ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:26:47
+   |
+LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+   |                                               ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:27:47
+   |
+LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
+   |                                               ^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:29:46
+   |
+LL |     unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:30:47
+   |
+LL |     unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:32:66
+   |
+LL |     unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
+   |                                                                  ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:34:46
+   |
+LL |     slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:35:38
+   |
+LL |     slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:37:49
+   |
+LL |     unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:38:41
+   |
+LL |     unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:40:33
+   |
+LL |     unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
+   |                                 ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:41:29
+   |
+LL |     y.as_ptr().wrapping_sub(size_of::<u8>());
+   |                             ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:42:29
+   |
+LL |     unsafe { y.as_ptr().add(size_of::<u8>()) };
+   |                             ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:43:33
+   |
+LL |     y.as_mut_ptr().wrapping_add(size_of::<u8>());
+   |                                 ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:44:32
+   |
+LL |     unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:45:36
+   |
+LL |     y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:48:62
+   |
+LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:51:62
+   |
+LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of `T`
+  --> $DIR/size_of_in_element_count.rs:54:47
+   |
+LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: aborting due to 24 previous errors
+
diff --git a/src/tools/clippy/tests/ui/str_to_string.rs b/src/tools/clippy/tests/ui/str_to_string.rs
new file mode 100644 (file)
index 0000000..08f7340
--- /dev/null
@@ -0,0 +1,7 @@
+#![warn(clippy::str_to_string)]
+
+fn main() {
+    let hello = "hello world".to_string();
+    let msg = &hello[..];
+    msg.to_string();
+}
diff --git a/src/tools/clippy/tests/ui/str_to_string.stderr b/src/tools/clippy/tests/ui/str_to_string.stderr
new file mode 100644 (file)
index 0000000..b1f73ed
--- /dev/null
@@ -0,0 +1,19 @@
+error: `to_string()` called on a `&str`
+  --> $DIR/str_to_string.rs:4:17
+   |
+LL |     let hello = "hello world".to_string();
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::str-to-string` implied by `-D warnings`
+   = help: consider using `.to_owned()`
+
+error: `to_string()` called on a `&str`
+  --> $DIR/str_to_string.rs:6:5
+   |
+LL |     msg.to_string();
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: consider using `.to_owned()`
+
+error: aborting due to 2 previous errors
+
diff --git a/src/tools/clippy/tests/ui/string_to_string.rs b/src/tools/clippy/tests/ui/string_to_string.rs
new file mode 100644 (file)
index 0000000..4c66855
--- /dev/null
@@ -0,0 +1,7 @@
+#![warn(clippy::string_to_string)]
+#![allow(clippy::redundant_clone)]
+
+fn main() {
+    let mut message = String::from("Hello");
+    let mut v = message.to_string();
+}
diff --git a/src/tools/clippy/tests/ui/string_to_string.stderr b/src/tools/clippy/tests/ui/string_to_string.stderr
new file mode 100644 (file)
index 0000000..1ebd179
--- /dev/null
@@ -0,0 +1,11 @@
+error: `to_string()` called on a `String`
+  --> $DIR/string_to_string.rs:6:17
+   |
+LL |     let mut v = message.to_string();
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::string-to-string` implied by `-D warnings`
+   = help: consider using `.clone()`
+
+error: aborting due to previous error
+
diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs b/src/tools/clippy/tests/ui/suspicious_operation_groupings.rs
new file mode 100644 (file)
index 0000000..dd6f4ec
--- /dev/null
@@ -0,0 +1,207 @@
+#![warn(clippy::suspicious_operation_groupings)]
+
+struct Vec3 {
+    x: f64,
+    y: f64,
+    z: f64,
+}
+
+impl Eq for Vec3 {}
+
+impl PartialEq for Vec3 {
+    fn eq(&self, other: &Self) -> bool {
+        // This should trigger the lint because `self.x` is compared to `other.y`
+        self.x == other.y && self.y == other.y && self.z == other.z
+    }
+}
+
+struct S {
+    a: i32,
+    b: i32,
+    c: i32,
+    d: i32,
+}
+
+fn buggy_ab_cmp(s1: &S, s2: &S) -> bool {
+    // There's no `s1.b`
+    s1.a < s2.a && s1.a < s2.b
+}
+
+struct SAOnly {
+    a: i32,
+}
+
+impl S {
+    fn a(&self) -> i32 {
+        0
+    }
+}
+
+fn do_not_give_bad_suggestions_for_this_unusual_expr(s1: &S, s2: &SAOnly) -> bool {
+    // This is superficially similar to `buggy_ab_cmp`, but we should not suggest
+    // `s2.b` since that is invalid.
+    s1.a < s2.a && s1.a() < s1.b
+}
+
+fn do_not_give_bad_suggestions_for_this_macro_expr(s1: &S, s2: &SAOnly) -> bool {
+    macro_rules! s1 {
+        () => {
+            S {
+                a: 1,
+                b: 1,
+                c: 1,
+                d: 1,
+            }
+        };
+    }
+
+    // This is superficially similar to `buggy_ab_cmp`, but we should not suggest
+    // `s2.b` since that is invalid.
+    s1.a < s2.a && s1!().a < s1.b
+}
+
+fn do_not_give_bad_suggestions_for_this_incorrect_expr(s1: &S, s2: &SAOnly) -> bool {
+    // There's two `s1.b`, but we should not suggest `s2.b` since that is invalid
+    s1.a < s2.a && s1.b < s1.b
+}
+
+fn permissable(s1: &S, s2: &S) -> bool {
+    // Something like this seems like it might actually be what is desired.
+    s1.a == s2.b
+}
+
+fn non_boolean_operators(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.c`
+    s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d
+}
+
+fn odd_number_of_pairs(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.b`
+    s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
+}
+
+fn not_caught_by_eq_op_middle_change_left(s1: &S, s2: &S) -> i32 {
+    // There's no `s1.b`
+    s1.a * s2.a + s2.b * s2.b + s1.c * s2.c
+}
+
+fn not_caught_by_eq_op_middle_change_right(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.b`
+    s1.a * s2.a + s1.b * s1.b + s1.c * s2.c
+}
+
+fn not_caught_by_eq_op_start(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.a`
+    s1.a * s1.a + s1.b * s2.b + s1.c * s2.c
+}
+
+fn not_caught_by_eq_op_end(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.c`
+    s1.a * s2.a + s1.b * s2.b + s1.c * s1.c
+}
+
+fn the_cross_product_should_not_lint(s1: &S, s2: &S) -> (i32, i32, i32) {
+    (
+        s1.b * s2.c - s1.c * s2.b,
+        s1.c * s2.a - s1.a * s2.c,
+        s1.a * s2.b - s1.b * s2.a,
+    )
+}
+
+fn outer_parens_simple(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.b`
+    (s1.a * s2.a + s1.b * s1.b)
+}
+
+fn outer_parens(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.c`
+    (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d)
+}
+
+fn inner_parens(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.c`
+    (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)
+}
+
+fn outer_and_some_inner_parens(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.c`
+    ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))
+}
+
+fn all_parens_balanced_tree(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.c`
+    (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
+}
+
+fn all_parens_left_tree(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.c`
+    (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d))
+}
+
+fn all_parens_right_tree(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.c`
+    ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)))
+}
+
+fn inside_other_binop_expression(s1: &S, s2: &S) -> i32 {
+    // There's no `s1.b`
+    (s1.a * s2.a + s2.b * s2.b) / 2
+}
+
+fn inside_function_call(s1: &S, s2: &S) -> i32 {
+    // There's no `s1.b`
+    i32::swap_bytes(s1.a * s2.a + s2.b * s2.b)
+}
+
+fn inside_larger_boolean_expression(s1: &S, s2: &S) -> bool {
+    // There's no `s1.c`
+    s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d
+}
+
+fn inside_larger_boolean_expression_with_unsorted_ops(s1: &S, s2: &S) -> bool {
+    // There's no `s1.c`
+    s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d
+}
+
+struct Nested {
+    inner: ((i32,), (i32,), (i32,)),
+}
+
+fn changed_middle_ident(n1: &Nested, n2: &Nested) -> bool {
+    // There's no `n2.inner.2.0`
+    (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0
+}
+
+// `eq_op` should catch this one.
+fn changed_initial_ident(n1: &Nested, n2: &Nested) -> bool {
+    // There's no `n2.inner.0.0`
+    (n1.inner.0).0 == (n1.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.2).0
+}
+
+fn inside_fn_with_similar_expression(s1: &S, s2: &S, strict: bool) -> bool {
+    if strict {
+        s1.a < s2.a && s1.b < s2.b
+    } else {
+        // There's no `s1.b` in this subexpression
+        s1.a <= s2.a && s1.a <= s2.b
+    }
+}
+
+fn inside_an_if_statement(s1: &S, s2: &S) {
+    // There's no `s1.b`
+    if s1.a < s2.a && s1.a < s2.b {
+        s1.c = s2.c;
+    }
+}
+
+fn maximum_unary_minus_right_tree(s1: &S, s2: &S) -> i32 {
+    // There's no `s2.c`
+    -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d)))
+}
+
+fn unary_minus_and_an_if_expression(s1: &S, s2: &S) -> i32 {
+    // There's no `s1.b`
+    -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
+}
+
+fn main() {}
diff --git a/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr b/src/tools/clippy/tests/ui/suspicious_operation_groupings.stderr
new file mode 100644 (file)
index 0000000..ce71082
--- /dev/null
@@ -0,0 +1,166 @@
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:14:9
+   |
+LL |         self.x == other.y && self.y == other.y && self.z == other.z
+   |         ^^^^^^^^^^^^^^^^^ help: I think you meant: `self.x == other.x`
+   |
+   = note: `-D clippy::suspicious-operation-groupings` implied by `-D warnings`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:14:9
+   |
+LL |         self.x == other.y && self.y == other.y && self.z == other.z
+   |         ^^^^^^^^^^^^^^^^^ help: I think you meant: `self.x == other.x`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:27:20
+   |
+LL |     s1.a < s2.a && s1.a < s2.b
+   |                    ^^^^^^^^^^^ help: I think you meant: `s1.b < s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:75:33
+   |
+LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d
+   |                                 ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:80:19
+   |
+LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
+   |                   ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:80:19
+   |
+LL |     s1.a * s2.a + s1.b * s2.c + s1.c * s2.c
+   |                   ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:85:19
+   |
+LL |     s1.a * s2.a + s2.b * s2.b + s1.c * s2.c
+   |                   ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:90:19
+   |
+LL |     s1.a * s2.a + s1.b * s1.b + s1.c * s2.c
+   |                   ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:95:5
+   |
+LL |     s1.a * s1.a + s1.b * s2.b + s1.c * s2.c
+   |     ^^^^^^^^^^^ help: I think you meant: `s1.a * s2.a`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:100:33
+   |
+LL |     s1.a * s2.a + s1.b * s2.b + s1.c * s1.c
+   |                                 ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:113:20
+   |
+LL |     (s1.a * s2.a + s1.b * s1.b)
+   |                    ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:118:34
+   |
+LL |     (s1.a * s2.a + s1.b * s2.b + s1.c * s2.b + s1.d * s2.d)
+   |                                  ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:123:38
+   |
+LL |     (s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)
+   |                                      ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:128:39
+   |
+LL |     ((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d))
+   |                                       ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:133:42
+   |
+LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
+   |                                          ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:133:42
+   |
+LL |     (((s1.a * s2.a) + (s1.b * s2.b)) + ((s1.c * s2.b) + (s1.d * s2.d)))
+   |                                          ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:138:40
+   |
+LL |     (((s1.a * s2.a) + (s1.b * s2.b) + (s1.c * s2.b)) + (s1.d * s2.d))
+   |                                        ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:143:40
+   |
+LL |     ((s1.a * s2.a) + ((s1.b * s2.b) + (s1.c * s2.b) + (s1.d * s2.d)))
+   |                                        ^^^^^^^^^^^ help: I think you meant: `s1.c * s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:148:20
+   |
+LL |     (s1.a * s2.a + s2.b * s2.b) / 2
+   |                    ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:153:35
+   |
+LL |     i32::swap_bytes(s1.a * s2.a + s2.b * s2.b)
+   |                                   ^^^^^^^^^^^ help: I think you meant: `s1.b * s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:158:29
+   |
+LL |     s1.a > 0 && s1.b > 0 && s1.d == s2.c && s1.d == s2.d
+   |                             ^^^^^^^^^^^^ help: I think you meant: `s1.c == s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:163:17
+   |
+LL |     s1.a > 0 && s1.d == s2.c && s1.b > 0 && s1.d == s2.d
+   |                 ^^^^^^^^^^^^ help: I think you meant: `s1.c == s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:172:77
+   |
+LL |     (n1.inner.0).0 == (n2.inner.0).0 && (n1.inner.1).0 == (n2.inner.1).0 && (n1.inner.2).0 == (n2.inner.1).0
+   |                                                                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: I think you meant: `(n1.inner.2).0 == (n2.inner.2).0`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:186:25
+   |
+LL |         s1.a <= s2.a && s1.a <= s2.b
+   |                         ^^^^^^^^^^^^ help: I think you meant: `s1.b <= s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:192:23
+   |
+LL |     if s1.a < s2.a && s1.a < s2.b {
+   |                       ^^^^^^^^^^^ help: I think you meant: `s1.b < s2.b`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:199:48
+   |
+LL |     -(-(-s1.a * -s2.a) + (-(-s1.b * -s2.b) + -(-s1.c * -s2.b) + -(-s1.d * -s2.d)))
+   |                                                ^^^^^^^^^^^^^ help: I think you meant: `-s1.c * -s2.c`
+
+error: This sequence of operators looks suspiciously like a bug.
+  --> $DIR/suspicious_operation_groupings.rs:204:27
+   |
+LL |     -(if -s1.a < -s2.a && -s1.a < -s2.b { s1.c } else { s2.a })
+   |                           ^^^^^^^^^^^^^ help: I think you meant: `-s1.b < -s2.b`
+
+error: aborting due to 27 previous errors
+
index df9b227eeb3f55ad2cc6acb1f69c3ad040d9b11b..e8f2fb46665924848e113fa3a5ee4b2859714c0a 100644 (file)
@@ -20,4 +20,7 @@ pub fn $a() -> $b {
     foo!(a, i32);
     foo!(b, f32);
     foo!(c, f64);
+
+    // do not lint cast to cfg-dependant type
+    1 as std::os::raw::c_char;
 }
index 350da4965d11d9323433b7cf33631f1fd7e3e0a7..7fbce58a82f8e340e7d1ddc76eeb65732de23e7d 100644 (file)
@@ -11,6 +11,8 @@ fn main() {
     let _ = -100_f32;
     let _ = -100_f64;
     let _ = -100_f64;
+    100_f32;
+    100_f64;
     // Should not trigger
     #[rustfmt::skip]
     let v = vec!(1);
index ad2fb2e628921477fad7cf24c73e87a00b681898..a71363ea4d265ac86a4aaf3081fdc5aabdd62536 100644 (file)
@@ -11,6 +11,8 @@ fn main() {
     let _ = -100 as f32;
     let _ = -100 as f64;
     let _ = -100_i32 as f64;
+    100. as f32;
+    100. as f64;
     // Should not trigger
     #[rustfmt::skip]
     let v = vec!(1);
index 5a210fc89097bcdc7f5c93260b08ae89709849ed..3695a8f819c4a9da2ab2c364d29cf4f34a2a3c2b 100644 (file)
@@ -36,59 +36,71 @@ error: casting integer literal to `f64` is unnecessary
 LL |     let _ = -100_i32 as f64;
    |             ^^^^^^^^^^^^^^^ help: try: `-100_f64`
 
+error: casting float literal to `f32` is unnecessary
+  --> $DIR/unnecessary_cast_fixable.rs:14:5
+   |
+LL |     100. as f32;
+   |     ^^^^^^^^^^^ help: try: `100_f32`
+
+error: casting float literal to `f64` is unnecessary
+  --> $DIR/unnecessary_cast_fixable.rs:15:5
+   |
+LL |     100. as f64;
+   |     ^^^^^^^^^^^ help: try: `100_f64`
+
 error: casting integer literal to `u32` is unnecessary
-  --> $DIR/unnecessary_cast_fixable.rs:25:5
+  --> $DIR/unnecessary_cast_fixable.rs:27:5
    |
 LL |     1 as u32;
    |     ^^^^^^^^ help: try: `1_u32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast_fixable.rs:26:5
+  --> $DIR/unnecessary_cast_fixable.rs:28:5
    |
 LL |     0x10 as i32;
    |     ^^^^^^^^^^^ help: try: `0x10_i32`
 
 error: casting integer literal to `usize` is unnecessary
-  --> $DIR/unnecessary_cast_fixable.rs:27:5
+  --> $DIR/unnecessary_cast_fixable.rs:29:5
    |
 LL |     0b10 as usize;
    |     ^^^^^^^^^^^^^ help: try: `0b10_usize`
 
 error: casting integer literal to `u16` is unnecessary
-  --> $DIR/unnecessary_cast_fixable.rs:28:5
+  --> $DIR/unnecessary_cast_fixable.rs:30:5
    |
 LL |     0o73 as u16;
    |     ^^^^^^^^^^^ help: try: `0o73_u16`
 
 error: casting integer literal to `u32` is unnecessary
-  --> $DIR/unnecessary_cast_fixable.rs:29:5
+  --> $DIR/unnecessary_cast_fixable.rs:31:5
    |
 LL |     1_000_000_000 as u32;
    |     ^^^^^^^^^^^^^^^^^^^^ help: try: `1_000_000_000_u32`
 
 error: casting float literal to `f64` is unnecessary
-  --> $DIR/unnecessary_cast_fixable.rs:31:5
+  --> $DIR/unnecessary_cast_fixable.rs:33:5
    |
 LL |     1.0 as f64;
    |     ^^^^^^^^^^ help: try: `1.0_f64`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast_fixable.rs:32:5
+  --> $DIR/unnecessary_cast_fixable.rs:34:5
    |
 LL |     0.5 as f32;
    |     ^^^^^^^^^^ help: try: `0.5_f32`
 
 error: casting integer literal to `i32` is unnecessary
-  --> $DIR/unnecessary_cast_fixable.rs:36:13
+  --> $DIR/unnecessary_cast_fixable.rs:38:13
    |
 LL |     let _ = -1 as i32;
    |             ^^^^^^^^^ help: try: `-1_i32`
 
 error: casting float literal to `f32` is unnecessary
-  --> $DIR/unnecessary_cast_fixable.rs:37:13
+  --> $DIR/unnecessary_cast_fixable.rs:39:13
    |
 LL |     let _ = -1.0 as f32;
    |             ^^^^^^^^^^^ help: try: `-1.0_f32`
 
-error: aborting due to 15 previous errors
+error: aborting due to 17 previous errors
 
index a53dec8f91ac50acae35e3d5c02ec13a501e8456..a4570098d7167da8393f6c4933d20cf277be8962 100644 (file)
@@ -109,6 +109,13 @@ fn func13() -> Option<i32> {
     }
 }
 
+fn issue_6384(s: &str) -> Option<&str> {
+    Some(match s {
+        "a" => "A",
+        _ => return None,
+    })
+}
+
 fn main() {
     // method calls are not linted
     func1(true, true);
index 4043d53299f6b0ca219892ade384801523d5ed3a..c2e38037addd2465af022e7ce1b786ca33b24260 100644 (file)
@@ -10,6 +10,14 @@ macro_rules! foo {
     };
 }
 
+struct Bar(f32);
+
+macro_rules! bar {
+    () => {
+        Bar(100200300400.100200300400500)
+    };
+}
+
 fn main() {
     let _good = (
         0b1011_i64,
@@ -26,10 +34,12 @@ fn main() {
     let _good_sci = 1.1234e1;
     let _bad_sci = 1.123_456e1;
 
-    let _fail9 = 0x00ab_cdef;
-    let _fail10: u32 = 0xBAFE_BAFE;
-    let _fail11 = 0x0abc_deff;
-    let _fail12: i128 = 0x00ab_cabc_abca_bcab_cabc;
+    let _fail1 = 0x00ab_cdef;
+    let _fail2: u32 = 0xBAFE_BAFE;
+    let _fail3 = 0x0abc_deff;
+    let _fail4: i128 = 0x00ab_cabc_abca_bcab_cabc;
+    let _fail5 = 1.100_300_400;
 
     let _ = foo!();
+    let _ = bar!();
 }
index e658a5f28c90e6b2b036047e9289b0096041643e..8296945b25eb4713fc702fa08d298cdf2d9a6214 100644 (file)
@@ -10,6 +10,14 @@ macro_rules! foo {
     };
 }
 
+struct Bar(f32);
+
+macro_rules! bar {
+    () => {
+        Bar(100200300400.100200300400500)
+    };
+}
+
 fn main() {
     let _good = (
         0b1011_i64,
@@ -26,10 +34,12 @@ fn main() {
     let _good_sci = 1.1234e1;
     let _bad_sci = 1.123456e1;
 
-    let _fail9 = 0xabcdef;
-    let _fail10: u32 = 0xBAFEBAFE;
-    let _fail11 = 0xabcdeff;
-    let _fail12: i128 = 0xabcabcabcabcabcabc;
+    let _fail1 = 0xabcdef;
+    let _fail2: u32 = 0xBAFEBAFE;
+    let _fail3 = 0xabcdeff;
+    let _fail4: i128 = 0xabcabcabcabcabcabc;
+    let _fail5 = 1.100300400;
 
     let _ = foo!();
+    let _ = bar!();
 }
index 8645cabeabbbc92dfe8a7a0a16e57f4d82bb990c..8436aac17acfe76b42d9a20a21ddd9e81e1723d1 100644 (file)
@@ -1,5 +1,5 @@
 error: digits of hex or binary literal not grouped by four
-  --> $DIR/unreadable_literal.rs:17:9
+  --> $DIR/unreadable_literal.rs:25:9
    |
 LL |         0x1_234_567,
    |         ^^^^^^^^^^^ help: consider: `0x0123_4567`
@@ -7,7 +7,7 @@ LL |         0x1_234_567,
    = note: `-D clippy::unusual-byte-groupings` implied by `-D warnings`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:25:17
+  --> $DIR/unreadable_literal.rs:33:17
    |
 LL |     let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
    |                 ^^^^^^^^^^^^ help: consider: `0b11_0110_i64`
@@ -15,52 +15,58 @@ LL |     let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
    = note: `-D clippy::unreadable-literal` implied by `-D warnings`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:25:31
+  --> $DIR/unreadable_literal.rs:33:31
    |
 LL |     let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
    |                               ^^^^^^^^^^^^^^^^ help: consider: `0xcafe_babe_usize`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:25:49
+  --> $DIR/unreadable_literal.rs:33:49
    |
 LL |     let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
    |                                                 ^^^^^^^^^^ help: consider: `123_456_f32`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:25:61
+  --> $DIR/unreadable_literal.rs:33:61
    |
 LL |     let _bad = (0b110110_i64, 0xcafebabe_usize, 123456_f32, 1.234567_f32);
    |                                                             ^^^^^^^^^^^^ help: consider: `1.234_567_f32`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:27:20
+  --> $DIR/unreadable_literal.rs:35:20
    |
 LL |     let _bad_sci = 1.123456e1;
    |                    ^^^^^^^^^^ help: consider: `1.123_456e1`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:29:18
+  --> $DIR/unreadable_literal.rs:37:18
    |
-LL |     let _fail9 = 0xabcdef;
+LL |     let _fail1 = 0xabcdef;
    |                  ^^^^^^^^ help: consider: `0x00ab_cdef`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:30:24
+  --> $DIR/unreadable_literal.rs:38:23
    |
-LL |     let _fail10: u32 = 0xBAFEBAFE;
-   |                        ^^^^^^^^^^ help: consider: `0xBAFE_BAFE`
+LL |     let _fail2: u32 = 0xBAFEBAFE;
+   |                       ^^^^^^^^^^ help: consider: `0xBAFE_BAFE`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:31:19
+  --> $DIR/unreadable_literal.rs:39:18
    |
-LL |     let _fail11 = 0xabcdeff;
-   |                   ^^^^^^^^^ help: consider: `0x0abc_deff`
+LL |     let _fail3 = 0xabcdeff;
+   |                  ^^^^^^^^^ help: consider: `0x0abc_deff`
 
 error: long literal lacking separators
-  --> $DIR/unreadable_literal.rs:32:25
+  --> $DIR/unreadable_literal.rs:40:24
    |
-LL |     let _fail12: i128 = 0xabcabcabcabcabcabc;
-   |                         ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc`
+LL |     let _fail4: i128 = 0xabcabcabcabcabcabc;
+   |                        ^^^^^^^^^^^^^^^^^^^^ help: consider: `0x00ab_cabc_abca_bcab_cabc`
 
-error: aborting due to 10 previous errors
+error: long literal lacking separators
+  --> $DIR/unreadable_literal.rs:41:18
+   |
+LL |     let _fail5 = 1.100300400;
+   |                  ^^^^^^^^^^^ help: consider: `1.100_300_400`
+
+error: aborting due to 11 previous errors
 
index b1e5742b78531870fafac354b30323eafbcf72eb..c266f684a36f94f042c11e9491034efa40296446 100644 (file)
@@ -7,7 +7,8 @@
     dead_code,
     clippy::single_match,
     clippy::wildcard_in_or_patterns,
-    clippy::unnested_or_patterns, clippy::diverging_sub_expression
+    clippy::unnested_or_patterns,
+    clippy::diverging_sub_expression
 )]
 
 use std::io::ErrorKind;
index cd3ec3ea8d2629a3e22a532dc10279a234c080d4..2dbf726d5d07236801f9fee0441f3c2e6b15b12f 100644 (file)
@@ -7,7 +7,8 @@
     dead_code,
     clippy::single_match,
     clippy::wildcard_in_or_patterns,
-    clippy::unnested_or_patterns, clippy::diverging_sub_expression
+    clippy::unnested_or_patterns,
+    clippy::diverging_sub_expression
 )]
 
 use std::io::ErrorKind;
index e03b3be43ed236ddc1bbe5e82234054f3f16263a..0da2b68ba0b2f80fc6c3885bc6d4b6b5f14abd23 100644 (file)
@@ -1,5 +1,5 @@
 error: wildcard match will miss any future added variants
-  --> $DIR/wildcard_enum_match_arm.rs:38:9
+  --> $DIR/wildcard_enum_match_arm.rs:39:9
    |
 LL |         _ => eprintln!("Not red"),
    |         ^ help: try this: `Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
@@ -11,25 +11,25 @@ LL | #![deny(clippy::wildcard_enum_match_arm)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: wildcard match will miss any future added variants
-  --> $DIR/wildcard_enum_match_arm.rs:42:9
+  --> $DIR/wildcard_enum_match_arm.rs:43:9
    |
 LL |         _not_red => eprintln!("Not red"),
    |         ^^^^^^^^ help: try this: `_not_red @ Color::Green | _not_red @ Color::Blue | _not_red @ Color::Rgb(..) | _not_red @ Color::Cyan`
 
 error: wildcard match will miss any future added variants
-  --> $DIR/wildcard_enum_match_arm.rs:46:9
+  --> $DIR/wildcard_enum_match_arm.rs:47:9
    |
 LL |         not_red => format!("{:?}", not_red),
    |         ^^^^^^^ help: try this: `not_red @ Color::Green | not_red @ Color::Blue | not_red @ Color::Rgb(..) | not_red @ Color::Cyan`
 
 error: wildcard match will miss any future added variants
-  --> $DIR/wildcard_enum_match_arm.rs:62:9
+  --> $DIR/wildcard_enum_match_arm.rs:63:9
    |
 LL |         _ => "No red",
    |         ^ help: try this: `Color::Red | Color::Green | Color::Blue | Color::Rgb(..) | Color::Cyan`
 
 error: match on non-exhaustive enum doesn't explicitly match all known variants
-  --> $DIR/wildcard_enum_match_arm.rs:79:9
+  --> $DIR/wildcard_enum_match_arm.rs:80:9
    |
 LL |         _ => {},
    |         ^ help: try this: `std::io::ErrorKind::PermissionDenied | std::io::ErrorKind::ConnectionRefused | std::io::ErrorKind::ConnectionReset | std::io::ErrorKind::ConnectionAborted | std::io::ErrorKind::NotConnected | std::io::ErrorKind::AddrInUse | std::io::ErrorKind::AddrNotAvailable | std::io::ErrorKind::BrokenPipe | std::io::ErrorKind::AlreadyExists | std::io::ErrorKind::WouldBlock | std::io::ErrorKind::InvalidInput | std::io::ErrorKind::InvalidData | std::io::ErrorKind::TimedOut | std::io::ErrorKind::WriteZero | std::io::ErrorKind::Interrupted | std::io::ErrorKind::Other | std::io::ErrorKind::UnexpectedEof | _`
index 7586f5aa3b53b7a7c7d52e89257c989f831f1b54..0d4a755551a7e4c62218497c307b59f9984cc715 100755 (executable)
@@ -28,7 +28,7 @@ MAINTAINERS = {
     'rls': {'Xanewok'},
     'rustfmt': {'topecongiro', 'calebcartwright'},
     'book': {'carols10cents', 'steveklabnik'},
-    'nomicon': {'frewsxcv', 'Gankra'},
+    'nomicon': {'frewsxcv', 'Gankra', 'JohnTitor'},
     'reference': {'steveklabnik', 'Havvy', 'matthewjasper', 'ehuss'},
     'rust-by-example': {'steveklabnik', 'marioidival'},
     'embedded-book': {'adamgreig', 'andre-richter', 'jamesmunns', 'therealprof'},
index dab1468d6aeed0e49f7d0569c1d2128b5a7751e0..2cf84baa5e3c55ac02f42919e67440acb5417125 160000 (submodule)
@@ -1 +1 @@
-Subproject commit dab1468d6aeed0e49f7d0569c1d2128b5a7751e0
+Subproject commit 2cf84baa5e3c55ac02f42919e67440acb5417125
index 337d65e4da4947e9493da11968a0c1ea612edd4b..11b175f9e80ed3320d846be02d9eadbc29ee0b07 100644 (file)
@@ -64,6 +64,7 @@ features = [
 byteorder = { version = "1", features = ['default', 'std'] }
 curl-sys = { version = "0.4.13", features = ["http2", "libnghttp2-sys"], optional = true }
 crossbeam-utils = { version = "0.7.2", features = ["nightly"] }
+libc = { version = "0.2.79", features = ["align"] }
 proc-macro2 = { version = "1", features = ["default"] }
 quote = { version = "1", features = ["default"] }
 serde = { version = "1.0.82", features = ['derive'] }
index 580d826e9b0f407a2d4b36696cda2f0fa8d7ddaa..70ce18255f429caf0d75ecfed8c1464535ee779b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit 580d826e9b0f407a2d4b36696cda2f0fa8d7ddaa
+Subproject commit 70ce18255f429caf0d75ecfed8c1464535ee779b