about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduardo Broto <ebroto@tutanota.com>2020-09-28 23:05:40 +0200
committerEduardo Broto <ebroto@tutanota.com>2020-09-28 23:05:40 +0200
commit1b58144af56d8e42adadb1d02dab75da00f5b2ea (patch)
tree3d758b9a65dae3c591c70952214f3a7b8337facf
parent952ec7d06660277dedf3436a9f50952a9caa6523 (diff)
parentdb6fb90bc0d9cbf4ddf1bfa560b9e8db10851a84 (diff)
downloadrust-1b58144af56d8e42adadb1d02dab75da00f5b2ea.tar.gz
rust-1b58144af56d8e42adadb1d02dab75da00f5b2ea.zip
Merge remote-tracking branch 'upstream/master' into rustup
-rw-r--r--CHANGELOG.md1
-rw-r--r--README.md2
-rw-r--r--clippy_lints/src/disallowed_method.rs73
-rw-r--r--clippy_lints/src/lib.rs6
-rw-r--r--clippy_lints/src/loops.rs6
-rw-r--r--clippy_lints/src/missing_const_for_fn.rs2
-rw-r--r--clippy_lints/src/types.rs15
-rw-r--r--clippy_lints/src/utils/conf.rs2
-rw-r--r--clippy_lints/src/utils/mod.rs11
-rw-r--r--clippy_lints/src/utils/qualify_min_const_fn.rs193
-rw-r--r--clippy_lints/src/write.rs17
-rw-r--r--clippy_workspace_tests/build.rs7
-rw-r--r--src/lintlist/mod.rs7
-rw-r--r--tests/compile-test.rs2
-rw-r--r--tests/ui-toml/toml_disallowed_method/clippy.toml1
-rw-r--r--tests/ui-toml/toml_disallowed_method/conf_disallowed_method.rs13
-rw-r--r--tests/ui-toml/toml_disallowed_method/conf_disallowed_method.stderr16
-rw-r--r--tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr2
-rw-r--r--tests/ui/auxiliary/proc_macro_attr.rs1
-rw-r--r--tests/ui/auxiliary/proc_macro_derive.rs1
-rw-r--r--tests/ui/crashes/associated-constant-ice.rs2
-rw-r--r--tests/ui/crashes/auxiliary/proc_macro_crash.rs1
-rw-r--r--tests/ui/crashes/cc_seme.rs2
-rw-r--r--tests/ui/crashes/enum-glob-import-crate.rs2
-rw-r--r--tests/ui/crashes/ice-1588.rs2
-rw-r--r--tests/ui/crashes/ice-1782.rs2
-rw-r--r--tests/ui/crashes/ice-1969.rs2
-rw-r--r--tests/ui/crashes/ice-2499.rs2
-rw-r--r--tests/ui/crashes/ice-2594.rs2
-rw-r--r--tests/ui/crashes/ice-2727.rs2
-rw-r--r--tests/ui/crashes/ice-2760.rs2
-rw-r--r--tests/ui/crashes/ice-2774.rs2
-rw-r--r--tests/ui/crashes/ice-2862.rs2
-rw-r--r--tests/ui/crashes/ice-2865.rs2
-rw-r--r--tests/ui/crashes/ice-3151.rs2
-rw-r--r--tests/ui/crashes/ice-3462.rs2
-rw-r--r--tests/ui/crashes/ice-3741.rs1
-rw-r--r--tests/ui/crashes/ice-3747.rs2
-rw-r--r--tests/ui/crashes/ice-4727.rs2
-rw-r--r--tests/ui/crashes/ice-4760.rs1
-rw-r--r--tests/ui/crashes/ice-700.rs2
-rw-r--r--tests/ui/crashes/ice_exacte_size.rs2
-rw-r--r--tests/ui/crashes/if_same_then_else.rs2
-rw-r--r--tests/ui/crashes/issue-825.rs2
-rw-r--r--tests/ui/crashes/issues_loop_mut_cond.rs2
-rw-r--r--tests/ui/crashes/match_same_arms_const.rs2
-rw-r--r--tests/ui/crashes/mut_mut_macro.rs2
-rw-r--r--tests/ui/crashes/needless_borrow_fp.rs2
-rw-r--r--tests/ui/crashes/needless_lifetimes_impl_trait.rs2
-rw-r--r--tests/ui/crashes/procedural_macro.rs2
-rw-r--r--tests/ui/crashes/regressions.rs2
-rw-r--r--tests/ui/crashes/returns.rs2
-rw-r--r--tests/ui/crashes/single-match-else.rs2
-rw-r--r--tests/ui/crashes/trivial_bounds.rs2
-rw-r--r--tests/ui/crashes/used_underscore_binding_macro.rs2
-rw-r--r--tests/ui/explicit_counter_loop.rs29
-rw-r--r--tests/ui/or_fun_call.fixed25
-rw-r--r--tests/ui/or_fun_call.rs25
-rw-r--r--tests/ui/or_fun_call.stderr20
-rw-r--r--tests/ui/print_stdout_build_script.rs12
-rw-r--r--tests/ui/temporary_assignment.rs1
-rw-r--r--tests/ui/temporary_assignment.stderr8
-rwxr-xr-xutil/dev7
63 files changed, 302 insertions, 270 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index d1dfe36ffd8..575cbd60792 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1559,6 +1559,7 @@ Released 2018-09-13
 [`deref_addrof`]: https://rust-lang.github.io/rust-clippy/master/index.html#deref_addrof
 [`derive_hash_xor_eq`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_hash_xor_eq
 [`derive_ord_xor_partial_ord`]: https://rust-lang.github.io/rust-clippy/master/index.html#derive_ord_xor_partial_ord
+[`disallowed_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_method
 [`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
 [`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
 [`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons
diff --git a/README.md b/README.md
index a2984d73641..62a8be0abf2 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,7 @@
 
 A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
 
-[There are over 350 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are over 400 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
 
 We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
 
diff --git a/clippy_lints/src/disallowed_method.rs b/clippy_lints/src/disallowed_method.rs
new file mode 100644
index 00000000000..581c3242e37
--- /dev/null
+++ b/clippy_lints/src/disallowed_method.rs
@@ -0,0 +1,73 @@
+use crate::utils::span_lint;
+
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::{declare_tool_lint, impl_lint_pass};
+use rustc_span::Symbol;
+
+declare_clippy_lint! {
+    /// **What it does:** Lints for specific trait methods defined in clippy.toml
+    ///
+    /// **Why is this bad?** Some methods are undesirable in certain contexts,
+    /// and it would be beneficial to lint for them as needed.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    ///
+    /// ```rust,ignore
+    /// // example code where clippy issues a warning
+    /// foo.bad_method(); // Foo::bad_method is disallowed in the configuration
+    /// ```
+    /// Use instead:
+    /// ```rust,ignore
+    /// // example code which does not raise clippy warning
+    /// goodStruct.bad_method(); // GoodStruct::bad_method is not disallowed
+    /// ```
+    pub DISALLOWED_METHOD,
+    nursery,
+    "use of a disallowed method call"
+}
+
+#[derive(Clone, Debug)]
+pub struct DisallowedMethod {
+    disallowed: FxHashSet<Vec<Symbol>>,
+}
+
+impl DisallowedMethod {
+    pub fn new(disallowed: &FxHashSet<String>) -> Self {
+        Self {
+            disallowed: disallowed
+                .iter()
+                .map(|s| s.split("::").map(|seg| Symbol::intern(seg)).collect::<Vec<_>>())
+                .collect(),
+        }
+    }
+}
+
+impl_lint_pass!(DisallowedMethod => [DISALLOWED_METHOD]);
+
+impl<'tcx> LateLintPass<'tcx> for DisallowedMethod {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        if let ExprKind::MethodCall(_path, _, _args, _) = &expr.kind {
+            let def_id = cx.typeck_results().type_dependent_def_id(expr.hir_id).unwrap();
+
+            let method_call = cx.get_def_path(def_id);
+            if self.disallowed.contains(&method_call) {
+                let method = method_call
+                    .iter()
+                    .map(|s| s.to_ident_string())
+                    .collect::<Vec<_>>()
+                    .join("::");
+
+                span_lint(
+                    cx,
+                    DISALLOWED_METHOD,
+                    expr.span,
+                    &format!("use of a disallowed method `{}`", method),
+                );
+            }
+        }
+    }
+}
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index c3ff34e6e1e..529c2450541 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -176,6 +176,7 @@ mod dbg_macro;
 mod default_trait_access;
 mod dereference;
 mod derive;
+mod disallowed_method;
 mod doc;
 mod double_comparison;
 mod double_parens;
@@ -526,6 +527,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &derive::DERIVE_ORD_XOR_PARTIAL_ORD,
         &derive::EXPL_IMPL_CLONE_ON_COPY,
         &derive::UNSAFE_DERIVE_DESERIALIZE,
+        &disallowed_method::DISALLOWED_METHOD,
         &doc::DOC_MARKDOWN,
         &doc::MISSING_ERRORS_DOC,
         &doc::MISSING_SAFETY_DOC,
@@ -1119,6 +1121,9 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     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_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
         LintId::of(&arithmetic::FLOAT_ARITHMETIC),
@@ -1808,6 +1813,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
         LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
         LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY),
+        LintId::of(&disallowed_method::DISALLOWED_METHOD),
         LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
         LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS),
         LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),
diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs
index 3410341a1e3..7f998c63f49 100644
--- a/clippy_lints/src/loops.rs
+++ b/clippy_lints/src/loops.rs
@@ -2134,7 +2134,7 @@ enum VarState {
     DontWarn,
 }
 
-/// Scan a for loop for variables that are incremented exactly once.
+/// Scan a for loop for variables that are incremented exactly once and not used after that.
 struct IncrementVisitor<'a, 'tcx> {
     cx: &'a LateContext<'tcx>,          // context reference
     states: FxHashMap<HirId, VarState>, // incremented variables
@@ -2154,6 +2154,10 @@ impl<'a, 'tcx> Visitor<'tcx> for IncrementVisitor<'a, 'tcx> {
         if let Some(def_id) = var_def_id(self.cx, expr) {
             if let Some(parent) = get_parent_expr(self.cx, expr) {
                 let state = self.states.entry(def_id).or_insert(VarState::Initial);
+                if *state == VarState::IncrOnce {
+                    *state = VarState::DontWarn;
+                    return;
+                }
 
                 match parent.kind {
                     ExprKind::AssignOp(op, ref lhs, ref rhs) => {
diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs
index e5f7cc51111..3e786da28df 100644
--- a/clippy_lints/src/missing_const_for_fn.rs
+++ b/clippy_lints/src/missing_const_for_fn.rs
@@ -1,10 +1,10 @@
+use crate::utils::qualify_min_const_fn::is_min_const_fn;
 use crate::utils::{fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method};
 use rustc_hir as hir;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::lint::in_external_macro;
-use crate::utils::qualify_min_const_fn::is_min_const_fn;
 use rustc_session::{declare_lint_pass, declare_tool_lint};
 use rustc_span::Span;
 use rustc_typeck::hir_ty_to_ty;
diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs
index a29a199b8c3..17d950169fd 100644
--- a/clippy_lints/src/types.rs
+++ b/clippy_lints/src/types.rs
@@ -216,18 +216,19 @@ declare_clippy_lint! {
 }
 
 declare_clippy_lint! {
-    /// **What it does:** Checks for Rc<T> and Arc<T> when T is a mutable buffer type such as String or Vec
+    /// **What it does:** Checks for `Rc<T>` and `Arc<T>` when `T` is a mutable buffer type such as `String` or `Vec`.
     ///
-    /// **Why is this bad?** Expressions such as Rc<String> have no advantage over Rc<str>, since
-    /// it is larger and involves an extra level of indirection, and doesn't implement Borrow<str>.
+    /// **Why is this bad?** Expressions such as `Rc<String>` usually have no advantage over `Rc<str>`, since
+    /// it is larger and involves an extra level of indirection, and doesn't implement `Borrow<str>`.
     ///
-    /// While mutating a buffer type would still be possible with Rc::get_mut(), it only
-    /// works if there are no additional references yet, which defeats the purpose of
+    /// While mutating a buffer type would still be possible with `Rc::get_mut()`, it only
+    /// works if there are no additional references yet, which usually defeats the purpose of
     /// enclosing it in a shared ownership type. Instead, additionally wrapping the inner
-    /// type with an interior mutable container (such as RefCell or Mutex) would normally
+    /// type with an interior mutable container (such as `RefCell` or `Mutex`) would normally
     /// be used.
     ///
-    /// **Known problems:** None.
+    /// **Known problems:** This pattern can be desirable to avoid the overhead of a `RefCell` or `Mutex` for
+    /// cases where mutation only happens before there are any additional references.
     ///
     /// **Example:**
     /// ```rust,ignore
diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs
index 9c5a12ea9c8..03f8c5a2c07 100644
--- a/clippy_lints/src/utils/conf.rs
+++ b/clippy_lints/src/utils/conf.rs
@@ -164,6 +164,8 @@ define_Conf! {
     (max_fn_params_bools, "max_fn_params_bools": u64, 3),
     /// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests).
     (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()),
 }
 
 impl Default for Conf {
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 96d9905027b..dfe2aadffc0 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -18,9 +18,9 @@ pub mod internal_lints;
 pub mod numeric_literal;
 pub mod paths;
 pub mod ptr;
+pub mod qualify_min_const_fn;
 pub mod sugg;
 pub mod usage;
-pub mod qualify_min_const_fn;
 
 pub use self::attrs::*;
 pub use self::diagnostics::*;
@@ -47,7 +47,6 @@ use rustc_lint::{LateContext, Level, Lint, LintContext};
 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_mir::const_eval;
 use rustc_span::hygiene::{ExpnKind, MacroKind};
 use rustc_span::source_map::original_sp;
 use rustc_span::symbol::{self, kw, Symbol};
@@ -884,19 +883,11 @@ pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
 
 /// Checks if an expression is constructing a tuple-like enum variant or struct
 pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    fn has_no_arguments(cx: &LateContext<'_>, def_id: DefId) -> bool {
-        cx.tcx.fn_sig(def_id).skip_binder().inputs().is_empty()
-    }
-
     if let ExprKind::Call(ref fun, _) = expr.kind {
         if let ExprKind::Path(ref qp) = fun.kind {
             let res = cx.qpath_res(qp, fun.hir_id);
             return match res {
                 def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
-                // FIXME: check the constness of the arguments, see https://github.com/rust-lang/rust-clippy/pull/5682#issuecomment-638681210
-                def::Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) if has_no_arguments(cx, def_id) => {
-                    const_eval::is_const_fn(cx.tcx, def_id)
-                },
                 def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
                 _ => false,
             };
diff --git a/clippy_lints/src/utils/qualify_min_const_fn.rs b/clippy_lints/src/utils/qualify_min_const_fn.rs
index 6809b1fa88d..3773b9d9a2e 100644
--- a/clippy_lints/src/utils/qualify_min_const_fn.rs
+++ b/clippy_lints/src/utils/qualify_min_const_fn.rs
@@ -1,9 +1,12 @@
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_middle::mir::*;
+use rustc_middle::mir::{
+    Body, CastKind, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator,
+    TerminatorKind,
+};
 use rustc_middle::ty::subst::GenericArgKind;
 use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt};
-use rustc_span::symbol::{sym};
+use rustc_span::symbol::sym;
 use rustc_span::Span;
 use rustc_target::spec::abi::Abi::RustIntrinsic;
 use std::borrow::Cow;
@@ -23,15 +26,9 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
                 | ty::PredicateAtom::ConstEvaluatable(..)
                 | ty::PredicateAtom::ConstEquate(..)
                 | ty::PredicateAtom::TypeWellFormedFromEnv(..) => continue,
-                ty::PredicateAtom::ObjectSafe(_) => {
-                    panic!("object safe predicate on function: {:#?}", predicate)
-                }
-                ty::PredicateAtom::ClosureKind(..) => {
-                    panic!("closure kind predicate on function: {:#?}", predicate)
-                }
-                ty::PredicateAtom::Subtype(_) => {
-                    panic!("subtype predicate on function: {:#?}", predicate)
-                }
+                ty::PredicateAtom::ObjectSafe(_) => panic!("object safe predicate on function: {:#?}", predicate),
+                ty::PredicateAtom::ClosureKind(..) => panic!("closure kind predicate on function: {:#?}", predicate),
+                ty::PredicateAtom::Subtype(_) => panic!("subtype predicate on function: {:#?}", predicate),
                 ty::PredicateAtom::Trait(pred, _) => {
                     if Some(pred.def_id()) == tcx.lang_items().sized_trait() {
                         continue;
@@ -47,12 +44,12 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, def_id: DefId, body: &'a Body<'tcx>) -
                                  on const fn parameters are unstable"
                                     .into(),
                             ));
-                        }
+                        },
                         // other kinds of bounds are either tautologies
                         // or cause errors in other passes
                         _ => continue,
                     }
-                }
+                },
             }
         }
         match predicates.parent {
@@ -92,24 +89,23 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
 
         match ty.kind() {
             ty::Ref(_, _, hir::Mutability::Mut) => {
-                    return Err((span, "mutable references in const fn are unstable".into()));
-            }
+                return Err((span, "mutable references in const fn are unstable".into()));
+            },
             ty::Opaque(..) => return Err((span, "`impl Trait` in const fn is unstable".into())),
             ty::FnPtr(..) => {
-                    return Err((span, "function pointers in const fn are unstable".into()));
-            }
+                return Err((span, "function pointers in const fn are unstable".into()));
+            },
             ty::Dynamic(preds, _) => {
                 for pred in preds.iter() {
                     match pred.skip_binder() {
-                        ty::ExistentialPredicate::AutoTrait(_)
-                        | ty::ExistentialPredicate::Projection(_) => {
+                        ty::ExistentialPredicate::AutoTrait(_) | ty::ExistentialPredicate::Projection(_) => {
                             return Err((
                                 span,
                                 "trait bounds other than `Sized` \
                                  on const fn parameters are unstable"
                                     .into(),
                             ));
-                        }
+                        },
                         ty::ExistentialPredicate::Trait(trait_ref) => {
                             if Some(trait_ref.def_id) != tcx.lang_items().sized_trait() {
                                 return Err((
@@ -119,34 +115,23 @@ fn check_ty(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
                                         .into(),
                                 ));
                             }
-                        }
+                        },
                     }
                 }
-            }
-            _ => {}
+            },
+            _ => {},
         }
     }
     Ok(())
 }
 
-fn check_rvalue(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    def_id: DefId,
-    rvalue: &Rvalue<'tcx>,
-    span: Span,
-) -> McfResult {
+fn check_rvalue(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rvalue<'tcx>, span: Span) -> McfResult {
     match rvalue {
-        Rvalue::ThreadLocalRef(_) => {
-            Err((span, "cannot access thread local storage in const fn".into()))
-        }
-        Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => {
-            check_operand(tcx, operand, span, body)
-        }
-        Rvalue::Len(place)
-        | Rvalue::Discriminant(place)
-        | Rvalue::Ref(_, _, place)
-        | Rvalue::AddressOf(_, place) => check_place(tcx, *place, span,  body),
+        Rvalue::ThreadLocalRef(_) => Err((span, "cannot access thread local storage in const fn".into())),
+        Rvalue::Repeat(operand, _) | Rvalue::Use(operand) => check_operand(tcx, operand, span, body),
+        Rvalue::Len(place) | Rvalue::Discriminant(place) | Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
+            check_place(tcx, *place, span, body)
+        },
         Rvalue::Cast(CastKind::Misc, operand, cast_ty) => {
             use rustc_middle::ty::cast::CastTy;
             let cast_in = CastTy::from_ty(operand.ty(body, tcx)).expect("bad input type for cast");
@@ -154,20 +139,16 @@ fn check_rvalue(
             match (cast_in, cast_out) {
                 (CastTy::Ptr(_) | CastTy::FnPtr, CastTy::Int(_)) => {
                     Err((span, "casting pointers to ints is unstable in const fn".into()))
-                }
+                },
                 _ => check_operand(tcx, operand, span, body),
             }
-        }
-        Rvalue::Cast(
-            CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer),
-            operand,
-            _,
-        ) => check_operand(tcx, operand, span, body),
+        },
+        Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer | PointerCast::ArrayToPointer), operand, _) => {
+            check_operand(tcx, operand, span, body)
+        },
         Rvalue::Cast(
             CastKind::Pointer(
-                PointerCast::UnsafeFnPointer
-                | PointerCast::ClosureFnPointer(_)
-                | PointerCast::ReifyFnPointer,
+                PointerCast::UnsafeFnPointer | PointerCast::ClosureFnPointer(_) | PointerCast::ReifyFnPointer,
             ),
             _,
             _,
@@ -177,10 +158,7 @@ fn check_rvalue(
                 deref_ty.ty
             } else {
                 // We cannot allow this for now.
-                return Err((
-                    span,
-                    "unsizing casts are only allowed for references right now".into(),
-                ));
+                return Err((span, "unsizing casts are only allowed for references right now".into()));
             };
             let unsized_ty = tcx.struct_tail_erasing_lifetimes(pointee_ty, tcx.param_env(def_id));
             if let ty::Slice(_) | ty::Str = unsized_ty.kind() {
@@ -191,7 +169,7 @@ fn check_rvalue(
                 // We just can't allow trait objects until we have figured out trait method calls.
                 Err((span, "unsizing casts are not allowed in const fn".into()))
             }
-        }
+        },
         // binops are fine on integers
         Rvalue::BinaryOp(_, lhs, rhs) | Rvalue::CheckedBinaryOp(_, lhs, rhs) => {
             check_operand(tcx, lhs, span, body)?;
@@ -200,13 +178,14 @@ fn check_rvalue(
             if ty.is_integral() || ty.is_bool() || ty.is_char() {
                 Ok(())
             } else {
-                Err((span, "only int, `bool` and `char` operations are stable in const fn".into()))
+                Err((
+                    span,
+                    "only int, `bool` and `char` operations are stable in const fn".into(),
+                ))
             }
-        }
+        },
         Rvalue::NullaryOp(NullOp::SizeOf, _) => Ok(()),
-        Rvalue::NullaryOp(NullOp::Box, _) => {
-            Err((span, "heap allocations are not allowed in const fn".into()))
-        }
+        Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())),
         Rvalue::UnaryOp(_, operand) => {
             let ty = operand.ty(body, tcx);
             if ty.is_integral() || ty.is_bool() {
@@ -214,39 +193,29 @@ fn check_rvalue(
             } else {
                 Err((span, "only int and `bool` operations are stable in const fn".into()))
             }
-        }
+        },
         Rvalue::Aggregate(_, operands) => {
             for operand in operands {
                 check_operand(tcx, operand, span, body)?;
             }
             Ok(())
-        }
+        },
     }
 }
 
-fn check_statement(
-    tcx: TyCtxt<'tcx>,
-    body: &Body<'tcx>,
-    def_id: DefId,
-    statement: &Statement<'tcx>,
-) -> McfResult {
+fn check_statement(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, statement: &Statement<'tcx>) -> McfResult {
     let span = statement.source_info.span;
     match &statement.kind {
         StatementKind::Assign(box (place, rval)) => {
-            check_place(tcx, *place, span,  body)?;
+            check_place(tcx, *place, span, body)?;
             check_rvalue(tcx, body, def_id, rval, span)
-        }
-
-        StatementKind::FakeRead(_, place) => check_place(tcx, **place, span, body),
+        },
 
+        StatementKind::FakeRead(_, place) |
         // just an assignment
-        StatementKind::SetDiscriminant { place, .. } => {
-            check_place(tcx, **place, span,  body)
-        }
+        StatementKind::SetDiscriminant { place, .. } => check_place(tcx, **place, span, body),
 
-        StatementKind::LlvmInlineAsm { .. } => {
-            Err((span, "cannot use inline assembly in const fn".into()))
-        }
+        StatementKind::LlvmInlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
 
         // These are all NOPs
         StatementKind::StorageLive(_)
@@ -258,12 +227,7 @@ fn check_statement(
     }
 }
 
-fn check_operand(
-    tcx: TyCtxt<'tcx>,
-    operand: &Operand<'tcx>,
-    span: Span,
-    body: &Body<'tcx>,
-) -> McfResult {
+fn check_operand(tcx: TyCtxt<'tcx>, operand: &Operand<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
     match operand {
         Operand::Move(place) | Operand::Copy(place) => check_place(tcx, *place, span, body),
         Operand::Constant(c) => match c.check_static_ptr(tcx) {
@@ -273,14 +237,9 @@ fn check_operand(
     }
 }
 
-fn check_place(
-    tcx: TyCtxt<'tcx>,
-    place: Place<'tcx>,
-    span: Span,
-    body: &Body<'tcx>,
-) -> McfResult {
+fn check_place(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'tcx>) -> McfResult {
     let mut cursor = place.projection.as_ref();
-    while let &[ref proj_base @ .., elem] = cursor {
+    while let [ref proj_base @ .., elem] = *cursor {
         cursor = proj_base;
         match elem {
             ProjectionElem::Field(..) => {
@@ -288,26 +247,22 @@ fn check_place(
                 if let Some(def) = base_ty.ty_adt_def() {
                     // No union field accesses in `const fn`
                     if def.is_union() {
-                            return Err((span, "accessing union fields is unstable".into()));
+                        return Err((span, "accessing union fields is unstable".into()));
                     }
                 }
-            }
+            },
             ProjectionElem::ConstantIndex { .. }
             | ProjectionElem::Downcast(..)
             | ProjectionElem::Subslice { .. }
             | ProjectionElem::Deref
-            | ProjectionElem::Index(_) => {}
+            | ProjectionElem::Index(_) => {},
         }
     }
 
     Ok(())
 }
 
-fn check_terminator(
-    tcx: TyCtxt<'tcx>,
-    body: &'a Body<'tcx>,
-    terminator: &Terminator<'tcx>,
-) -> McfResult {
+fn check_terminator(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, terminator: &Terminator<'tcx>) -> McfResult {
     let span = terminator.source_info.span;
     match &terminator.kind {
         TerminatorKind::FalseEdge { .. }
@@ -317,20 +272,23 @@ fn check_terminator(
         | TerminatorKind::Resume
         | TerminatorKind::Unreachable => Ok(()),
 
-        TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span,  body),
+        TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body),
         TerminatorKind::DropAndReplace { place, value, .. } => {
-            check_place(tcx, *place, span,  body)?;
+            check_place(tcx, *place, span, body)?;
             check_operand(tcx, value, span, body)
-        }
+        },
 
-        TerminatorKind::SwitchInt { discr, switch_ty: _, values: _, targets: _ } => {
-            check_operand(tcx, discr, span, body)
-        }
+        TerminatorKind::SwitchInt {
+            discr,
+            switch_ty: _,
+            values: _,
+            targets: _,
+        } => check_operand(tcx, discr, span, body),
 
         TerminatorKind::Abort => Err((span, "abort is not stable in const fn".into())),
         TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => {
             Err((span, "const fn generators are unstable".into()))
-        }
+        },
 
         TerminatorKind::Call {
             func,
@@ -342,8 +300,7 @@ fn check_terminator(
         } => {
             let fn_ty = func.ty(body, tcx);
             if let ty::FnDef(fn_def_id, _) = *fn_ty.kind() {
-                if !rustc_mir::const_eval::is_min_const_fn(tcx, fn_def_id)
-                {
+                if !rustc_mir::const_eval::is_min_const_fn(tcx, fn_def_id) {
                     return Err((
                         span,
                         format!(
@@ -359,9 +316,7 @@ fn check_terminator(
                 // within const fns. `transmute` is allowed in all other const contexts.
                 // This won't really scale to more intrinsics or functions. Let's allow const
                 // transmutes in const fn before we add more hacks to this.
-                if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic
-                    && tcx.item_name(fn_def_id) == sym::transmute
-                {
+                if tcx.fn_sig(fn_def_id).abi() == RustIntrinsic && tcx.item_name(fn_def_id) == sym::transmute {
                     return Err((
                         span,
                         "can only call `transmute` from const items, not `const fn`".into(),
@@ -377,14 +332,16 @@ fn check_terminator(
             } else {
                 Err((span, "can only call other const fns within const fn".into()))
             }
-        }
+        },
 
-        TerminatorKind::Assert { cond, expected: _, msg: _, target: _, cleanup: _ } => {
-            check_operand(tcx, cond, span, body)
-        }
+        TerminatorKind::Assert {
+            cond,
+            expected: _,
+            msg: _,
+            target: _,
+            cleanup: _,
+        } => check_operand(tcx, cond, span, body),
 
-        TerminatorKind::InlineAsm { .. } => {
-            Err((span, "cannot use inline assembly in const fn".into()))
-        }
+        TerminatorKind::InlineAsm { .. } => Err((span, "cannot use inline assembly in const fn".into())),
     }
 }
diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs
index fac63bcb993..d9d60fffcd7 100644
--- a/clippy_lints/src/write.rs
+++ b/clippy_lints/src/write.rs
@@ -235,8 +235,19 @@ impl EarlyLintPass for Write {
     }
 
     fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &MacCall) {
+        fn is_build_script(cx: &EarlyContext<'_>) -> bool {
+            // Cargo sets the crate name for build scripts to `build_script_build`
+            cx.sess
+                .opts
+                .crate_name
+                .as_ref()
+                .map_or(false, |crate_name| crate_name == "build_script_build")
+        }
+
         if mac.path == sym!(println) {
-            span_lint(cx, PRINT_STDOUT, mac.span(), "use of `println!`");
+            if !is_build_script(cx) {
+                span_lint(cx, PRINT_STDOUT, mac.span(), "use of `println!`");
+            }
             if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) {
                 if fmt_str.symbol == Symbol::intern("") {
                     span_lint_and_sugg(
@@ -251,7 +262,9 @@ impl EarlyLintPass for Write {
                 }
             }
         } else if mac.path == sym!(print) {
-            span_lint(cx, PRINT_STDOUT, mac.span(), "use of `print!`");
+            if !is_build_script(cx) {
+                span_lint(cx, PRINT_STDOUT, mac.span(), "use of `print!`");
+            }
             if let (Some(fmt_str), _) = self.check_tts(cx, mac.args.inner_tokens(), false) {
                 if check_newlines(&fmt_str) {
                     span_lint_and_then(
diff --git a/clippy_workspace_tests/build.rs b/clippy_workspace_tests/build.rs
new file mode 100644
index 00000000000..3507168a3a9
--- /dev/null
+++ b/clippy_workspace_tests/build.rs
@@ -0,0 +1,7 @@
+#![deny(clippy::print_stdout)]
+
+fn main() {
+    // Test for #6041
+    println!("Hello");
+    print!("Hello");
+}
diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs
index 9603023ed06..76e655ad603 100644
--- a/src/lintlist/mod.rs
+++ b/src/lintlist/mod.rs
@@ -382,6 +382,13 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
         module: "derive",
     },
     Lint {
+        name: "disallowed_method",
+        group: "nursery",
+        desc: "use of a disallowed method call",
+        deprecation: None,
+        module: "disallowed_method",
+    },
+    Lint {
         name: "diverging_sub_expression",
         group: "complexity",
         desc: "whether an expression contains a diverging sub expression",
diff --git a/tests/compile-test.rs b/tests/compile-test.rs
index 697823712bf..f0d73e9b0e2 100644
--- a/tests/compile-test.rs
+++ b/tests/compile-test.rs
@@ -71,7 +71,7 @@ fn default_config() -> compiletest::Config {
     }
 
     config.target_rustcflags = Some(format!(
-        "-L {0} -L {1} -Dwarnings -Zui-testing {2}",
+        "--emit=metadata -L {0} -L {1} -Dwarnings -Zui-testing {2}",
         host_lib().join("deps").display(),
         cargo::TARGET_LIB.join("deps").display(),
         third_party_crates(),
diff --git a/tests/ui-toml/toml_disallowed_method/clippy.toml b/tests/ui-toml/toml_disallowed_method/clippy.toml
new file mode 100644
index 00000000000..a1f515e443d
--- /dev/null
+++ b/tests/ui-toml/toml_disallowed_method/clippy.toml
@@ -0,0 +1 @@
+disallowed-methods = ["core::iter::traits::iterator::Iterator::sum", "regex::re_unicode::Regex::is_match"]
diff --git a/tests/ui-toml/toml_disallowed_method/conf_disallowed_method.rs b/tests/ui-toml/toml_disallowed_method/conf_disallowed_method.rs
new file mode 100644
index 00000000000..3d3f0729abd
--- /dev/null
+++ b/tests/ui-toml/toml_disallowed_method/conf_disallowed_method.rs
@@ -0,0 +1,13 @@
+#![warn(clippy::disallowed_method)]
+
+extern crate regex;
+use regex::Regex;
+
+fn main() {
+    let a = vec![1, 2, 3, 4];
+    let re = Regex::new(r"ab.*c").unwrap();
+
+    re.is_match("abc");
+
+    a.iter().sum::<i32>();
+}
diff --git a/tests/ui-toml/toml_disallowed_method/conf_disallowed_method.stderr b/tests/ui-toml/toml_disallowed_method/conf_disallowed_method.stderr
new file mode 100644
index 00000000000..ed91b5a6796
--- /dev/null
+++ b/tests/ui-toml/toml_disallowed_method/conf_disallowed_method.stderr
@@ -0,0 +1,16 @@
+error: use of a disallowed method `regex::re_unicode::Regex::is_match`
+  --> $DIR/conf_disallowed_method.rs:10:5
+   |
+LL |     re.is_match("abc");
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::disallowed-method` implied by `-D warnings`
+
+error: use of a disallowed method `core::iter::traits::iterator::Iterator::sum`
+  --> $DIR/conf_disallowed_method.rs:12:5
+   |
+LL |     a.iter().sum::<i32>();
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 6fbba01416a..103ec27e7d7 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -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`, `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`, `third-party` at line 5 column 1
+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`, `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: aborting due to previous error
 
diff --git a/tests/ui/auxiliary/proc_macro_attr.rs b/tests/ui/auxiliary/proc_macro_attr.rs
index e6626d57a77..01796d45f13 100644
--- a/tests/ui/auxiliary/proc_macro_attr.rs
+++ b/tests/ui/auxiliary/proc_macro_attr.rs
@@ -1,3 +1,4 @@
+// compile-flags: --emit=link
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs
index 05ffb55f620..3df8be6c232 100644
--- a/tests/ui/auxiliary/proc_macro_derive.rs
+++ b/tests/ui/auxiliary/proc_macro_derive.rs
@@ -1,3 +1,4 @@
+// compile-flags: --emit=link
 // no-prefer-dynamic
 
 #![crate_type = "proc-macro"]
diff --git a/tests/ui/crashes/associated-constant-ice.rs b/tests/ui/crashes/associated-constant-ice.rs
index 4bb833795bb..948deba3ea6 100644
--- a/tests/ui/crashes/associated-constant-ice.rs
+++ b/tests/ui/crashes/associated-constant-ice.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 /// Test for https://github.com/rust-lang/rust-clippy/issues/1698
 
 pub trait Trait {
diff --git a/tests/ui/crashes/auxiliary/proc_macro_crash.rs b/tests/ui/crashes/auxiliary/proc_macro_crash.rs
index 086548e58ed..619d11cefc4 100644
--- a/tests/ui/crashes/auxiliary/proc_macro_crash.rs
+++ b/tests/ui/crashes/auxiliary/proc_macro_crash.rs
@@ -1,3 +1,4 @@
+// compile-flags: --emit=link
 // no-prefer-dynamic
 // ^ compiletest by default builds all aux files as dylibs, but we don't want that for proc-macro
 // crates. If we don't set this, compiletest will override the `crate_type` attribute below and
diff --git a/tests/ui/crashes/cc_seme.rs b/tests/ui/crashes/cc_seme.rs
index c48c7e9e6c6..98588be9cf8 100644
--- a/tests/ui/crashes/cc_seme.rs
+++ b/tests/ui/crashes/cc_seme.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #[allow(dead_code)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/478
diff --git a/tests/ui/crashes/enum-glob-import-crate.rs b/tests/ui/crashes/enum-glob-import-crate.rs
index db1fa871afe..dca32aa3b56 100644
--- a/tests/ui/crashes/enum-glob-import-crate.rs
+++ b/tests/ui/crashes/enum-glob-import-crate.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![deny(clippy::all)]
 #![allow(unused_imports)]
 
diff --git a/tests/ui/crashes/ice-1588.rs b/tests/ui/crashes/ice-1588.rs
index 15d0f705b36..b0a3d11bce4 100644
--- a/tests/ui/crashes/ice-1588.rs
+++ b/tests/ui/crashes/ice-1588.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(clippy::all)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/1588
diff --git a/tests/ui/crashes/ice-1782.rs b/tests/ui/crashes/ice-1782.rs
index 1ca6b6976b3..81af88962a6 100644
--- a/tests/ui/crashes/ice-1782.rs
+++ b/tests/ui/crashes/ice-1782.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(dead_code, unused_variables)]
 
 /// Should not trigger an ICE in `SpanlessEq` / `consts::constant`
diff --git a/tests/ui/crashes/ice-1969.rs b/tests/ui/crashes/ice-1969.rs
index 837ec9df31a..96a8fe6c24d 100644
--- a/tests/ui/crashes/ice-1969.rs
+++ b/tests/ui/crashes/ice-1969.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(clippy::all)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/1969
diff --git a/tests/ui/crashes/ice-2499.rs b/tests/ui/crashes/ice-2499.rs
index ffef1631775..45b3b1869dd 100644
--- a/tests/ui/crashes/ice-2499.rs
+++ b/tests/ui/crashes/ice-2499.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(dead_code, clippy::char_lit_as_u8, clippy::needless_bool)]
 
 /// Should not trigger an ICE in `SpanlessHash` / `consts::constant`
diff --git a/tests/ui/crashes/ice-2594.rs b/tests/ui/crashes/ice-2594.rs
index ac19f1976e9..3f3986b6fc6 100644
--- a/tests/ui/crashes/ice-2594.rs
+++ b/tests/ui/crashes/ice-2594.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(dead_code, unused_variables)]
 
 /// Should not trigger an ICE in `SpanlessHash` / `consts::constant`
diff --git a/tests/ui/crashes/ice-2727.rs b/tests/ui/crashes/ice-2727.rs
index d832c286033..56024abc8f5 100644
--- a/tests/ui/crashes/ice-2727.rs
+++ b/tests/ui/crashes/ice-2727.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 /// Test for https://github.com/rust-lang/rust-clippy/issues/2727
 
 pub fn f(new: fn()) {
diff --git a/tests/ui/crashes/ice-2760.rs b/tests/ui/crashes/ice-2760.rs
index 9e5e299c336..f1a229f3f4f 100644
--- a/tests/ui/crashes/ice-2760.rs
+++ b/tests/ui/crashes/ice-2760.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(
     unused_variables,
     clippy::blacklisted_name,
diff --git a/tests/ui/crashes/ice-2774.rs b/tests/ui/crashes/ice-2774.rs
index 47f8e3b18ee..d44b0fae820 100644
--- a/tests/ui/crashes/ice-2774.rs
+++ b/tests/ui/crashes/ice-2774.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 use std::collections::HashSet;
 
 // See rust-lang/rust-clippy#2774.
diff --git a/tests/ui/crashes/ice-2862.rs b/tests/ui/crashes/ice-2862.rs
index 47324ce1831..8326e3663b0 100644
--- a/tests/ui/crashes/ice-2862.rs
+++ b/tests/ui/crashes/ice-2862.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 /// Test for https://github.com/rust-lang/rust-clippy/issues/2862
 
 pub trait FooMap {
diff --git a/tests/ui/crashes/ice-2865.rs b/tests/ui/crashes/ice-2865.rs
index c4f6c0fed68..6b1ceb50569 100644
--- a/tests/ui/crashes/ice-2865.rs
+++ b/tests/ui/crashes/ice-2865.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #[allow(dead_code)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/2865
diff --git a/tests/ui/crashes/ice-3151.rs b/tests/ui/crashes/ice-3151.rs
index ffad2d06b56..fef4d7db84d 100644
--- a/tests/ui/crashes/ice-3151.rs
+++ b/tests/ui/crashes/ice-3151.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 /// Test for https://github.com/rust-lang/rust-clippy/issues/2865
 
 #[derive(Clone)]
diff --git a/tests/ui/crashes/ice-3462.rs b/tests/ui/crashes/ice-3462.rs
index 95c7dff9be3..7d62e315da2 100644
--- a/tests/ui/crashes/ice-3462.rs
+++ b/tests/ui/crashes/ice-3462.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![warn(clippy::all)]
 #![allow(clippy::blacklisted_name)]
 #![allow(unused)]
diff --git a/tests/ui/crashes/ice-3741.rs b/tests/ui/crashes/ice-3741.rs
index a548415da62..1253ddcfaeb 100644
--- a/tests/ui/crashes/ice-3741.rs
+++ b/tests/ui/crashes/ice-3741.rs
@@ -1,5 +1,4 @@
 // aux-build:proc_macro_crash.rs
-// run-pass
 
 #![warn(clippy::suspicious_else_formatting)]
 
diff --git a/tests/ui/crashes/ice-3747.rs b/tests/ui/crashes/ice-3747.rs
index d0b44ebafee..cdf018cbc88 100644
--- a/tests/ui/crashes/ice-3747.rs
+++ b/tests/ui/crashes/ice-3747.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 /// Test for https://github.com/rust-lang/rust-clippy/issues/3747
 
 macro_rules! a {
diff --git a/tests/ui/crashes/ice-4727.rs b/tests/ui/crashes/ice-4727.rs
index cdb59caec67..2a4bc83f58a 100644
--- a/tests/ui/crashes/ice-4727.rs
+++ b/tests/ui/crashes/ice-4727.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![warn(clippy::use_self)]
 
 #[path = "auxiliary/ice-4727-aux.rs"]
diff --git a/tests/ui/crashes/ice-4760.rs b/tests/ui/crashes/ice-4760.rs
index ead67d5ed1b..08b06961760 100644
--- a/tests/ui/crashes/ice-4760.rs
+++ b/tests/ui/crashes/ice-4760.rs
@@ -1,4 +1,3 @@
-// run-pass
 const COUNT: usize = 2;
 struct Thing;
 trait Dummy {}
diff --git a/tests/ui/crashes/ice-700.rs b/tests/ui/crashes/ice-700.rs
index b06df83d51a..0cbceedbd6b 100644
--- a/tests/ui/crashes/ice-700.rs
+++ b/tests/ui/crashes/ice-700.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![deny(clippy::all)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/700
diff --git a/tests/ui/crashes/ice_exacte_size.rs b/tests/ui/crashes/ice_exacte_size.rs
index e02eb28ab86..30e4b11ec0b 100644
--- a/tests/ui/crashes/ice_exacte_size.rs
+++ b/tests/ui/crashes/ice_exacte_size.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![deny(clippy::all)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/1336
diff --git a/tests/ui/crashes/if_same_then_else.rs b/tests/ui/crashes/if_same_then_else.rs
index 4ef992b05e7..2f913292995 100644
--- a/tests/ui/crashes/if_same_then_else.rs
+++ b/tests/ui/crashes/if_same_then_else.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(clippy::comparison_chain)]
 #![deny(clippy::if_same_then_else)]
 
diff --git a/tests/ui/crashes/issue-825.rs b/tests/ui/crashes/issue-825.rs
index 3d4a88ab3c4..05696e3d7d5 100644
--- a/tests/ui/crashes/issue-825.rs
+++ b/tests/ui/crashes/issue-825.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(warnings)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/825
diff --git a/tests/ui/crashes/issues_loop_mut_cond.rs b/tests/ui/crashes/issues_loop_mut_cond.rs
index c4acd5cda1b..bb238c81ebc 100644
--- a/tests/ui/crashes/issues_loop_mut_cond.rs
+++ b/tests/ui/crashes/issues_loop_mut_cond.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(dead_code)]
 
 /// Issue: https://github.com/rust-lang/rust-clippy/issues/2596
diff --git a/tests/ui/crashes/match_same_arms_const.rs b/tests/ui/crashes/match_same_arms_const.rs
index 848f0ea52ca..94c939665e6 100644
--- a/tests/ui/crashes/match_same_arms_const.rs
+++ b/tests/ui/crashes/match_same_arms_const.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![deny(clippy::match_same_arms)]
 
 /// Test for https://github.com/rust-lang/rust-clippy/issues/2427
diff --git a/tests/ui/crashes/mut_mut_macro.rs b/tests/ui/crashes/mut_mut_macro.rs
index d8fbaa54146..a238e7896fc 100644
--- a/tests/ui/crashes/mut_mut_macro.rs
+++ b/tests/ui/crashes/mut_mut_macro.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![deny(clippy::mut_mut, clippy::zero_ptr, clippy::cmp_nan)]
 #![allow(dead_code)]
 
diff --git a/tests/ui/crashes/needless_borrow_fp.rs b/tests/ui/crashes/needless_borrow_fp.rs
index 48507efe1e9..4f61c76828d 100644
--- a/tests/ui/crashes/needless_borrow_fp.rs
+++ b/tests/ui/crashes/needless_borrow_fp.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #[deny(clippy::all)]
 #[derive(Debug)]
 pub enum Error {
diff --git a/tests/ui/crashes/needless_lifetimes_impl_trait.rs b/tests/ui/crashes/needless_lifetimes_impl_trait.rs
index bd1fa4a0b1e..676564b2445 100644
--- a/tests/ui/crashes/needless_lifetimes_impl_trait.rs
+++ b/tests/ui/crashes/needless_lifetimes_impl_trait.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![deny(clippy::needless_lifetimes)]
 #![allow(dead_code)]
 
diff --git a/tests/ui/crashes/procedural_macro.rs b/tests/ui/crashes/procedural_macro.rs
index f79d9ab6460..c7468493380 100644
--- a/tests/ui/crashes/procedural_macro.rs
+++ b/tests/ui/crashes/procedural_macro.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #[macro_use]
 extern crate clippy_mini_macro_test;
 
diff --git a/tests/ui/crashes/regressions.rs b/tests/ui/crashes/regressions.rs
index 3d5063d1a3a..a41bcb33b44 100644
--- a/tests/ui/crashes/regressions.rs
+++ b/tests/ui/crashes/regressions.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(clippy::blacklisted_name)]
 
 pub fn foo(bar: *const u8) {
diff --git a/tests/ui/crashes/returns.rs b/tests/ui/crashes/returns.rs
index f2153efc388..8021ed4607d 100644
--- a/tests/ui/crashes/returns.rs
+++ b/tests/ui/crashes/returns.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 /// Test for https://github.com/rust-lang/rust-clippy/issues/1346
 
 #[deny(warnings)]
diff --git a/tests/ui/crashes/single-match-else.rs b/tests/ui/crashes/single-match-else.rs
index 3a4bbe310cc..1ba7ac08213 100644
--- a/tests/ui/crashes/single-match-else.rs
+++ b/tests/ui/crashes/single-match-else.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![warn(clippy::single_match_else)]
 
 //! Test for https://github.com/rust-lang/rust-clippy/issues/1588
diff --git a/tests/ui/crashes/trivial_bounds.rs b/tests/ui/crashes/trivial_bounds.rs
index 2bb95c18a39..60105a8213f 100644
--- a/tests/ui/crashes/trivial_bounds.rs
+++ b/tests/ui/crashes/trivial_bounds.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![feature(trivial_bounds)]
 #![allow(unused, trivial_bounds)]
 
diff --git a/tests/ui/crashes/used_underscore_binding_macro.rs b/tests/ui/crashes/used_underscore_binding_macro.rs
index 265017c51d9..6d2124c12fe 100644
--- a/tests/ui/crashes/used_underscore_binding_macro.rs
+++ b/tests/ui/crashes/used_underscore_binding_macro.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 #![allow(clippy::useless_attribute)] //issue #2910
 
 #[macro_use]
diff --git a/tests/ui/explicit_counter_loop.rs b/tests/ui/explicit_counter_loop.rs
index aa6ef162fe4..81d8221bd13 100644
--- a/tests/ui/explicit_counter_loop.rs
+++ b/tests/ui/explicit_counter_loop.rs
@@ -38,54 +38,54 @@ mod issue_1219 {
         let text = "banana";
         let mut count = 0;
         for ch in text.chars() {
+            println!("{}", count);
             if ch == 'a' {
                 continue;
             }
             count += 1;
-            println!("{}", count);
         }
 
         // should not trigger the lint because the count is conditional
         let text = "banana";
         let mut count = 0;
         for ch in text.chars() {
+            println!("{}", count);
             if ch == 'a' {
                 count += 1;
             }
-            println!("{}", count);
         }
 
         // should trigger the lint because the count is not conditional
         let text = "banana";
         let mut count = 0;
         for ch in text.chars() {
+            println!("{}", count);
             count += 1;
             if ch == 'a' {
                 continue;
             }
-            println!("{}", count);
         }
 
         // should trigger the lint because the count is not conditional
         let text = "banana";
         let mut count = 0;
         for ch in text.chars() {
+            println!("{}", count);
             count += 1;
             for i in 0..2 {
                 let _ = 123;
             }
-            println!("{}", count);
         }
 
         // should not trigger the lint because the count is incremented multiple times
         let text = "banana";
         let mut count = 0;
         for ch in text.chars() {
+            println!("{}", count);
             count += 1;
             for i in 0..2 {
                 count += 1;
             }
-            println!("{}", count);
         }
     }
 }
@@ -96,30 +96,30 @@ mod issue_3308 {
         let mut skips = 0;
         let erasures = vec![];
         for i in 0..10 {
+            println!("{}", skips);
             while erasures.contains(&(i + skips)) {
                 skips += 1;
             }
-            println!("{}", skips);
         }
 
         // should not trigger the lint because the count is incremented multiple times
         let mut skips = 0;
         for i in 0..10 {
+            println!("{}", skips);
             let mut j = 0;
             while j < 5 {
                 skips += 1;
                 j += 1;
             }
-            println!("{}", skips);
         }
 
         // should not trigger the lint because the count is incremented multiple times
         let mut skips = 0;
         for i in 0..10 {
+            println!("{}", skips);
             for j in 0..5 {
                 skips += 1;
             }
-            println!("{}", skips);
         }
     }
 }
@@ -145,3 +145,16 @@ mod issue_4732 {
         let _closure = || println!("index: {}", index);
     }
 }
+
+mod issue_4677 {
+    pub fn test() {
+        let slice = &[1, 2, 3];
+
+        // should not trigger the lint because the count is used after incremented
+        let mut count = 0;
+        for _i in slice {
+            count += 1;
+            println!("{}", count);
+        }
+    }
+}
diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed
index 5fb568672d3..2045ffdb5f0 100644
--- a/tests/ui/or_fun_call.fixed
+++ b/tests/ui/or_fun_call.fixed
@@ -58,6 +58,12 @@ fn or_fun_call() {
     let without_default = Some(Foo);
     without_default.unwrap_or_else(Foo::new);
 
+    let mut map = HashMap::<u64, String>::new();
+    map.entry(42).or_insert_with(String::new);
+
+    let mut btree = BTreeMap::<u64, String>::new();
+    btree.entry(42).or_insert_with(String::new);
+
     let stringy = Some(String::from(""));
     let _ = stringy.unwrap_or_else(|| "".to_owned());
 
@@ -110,23 +116,4 @@ fn f() -> Option<()> {
     Some(())
 }
 
-// Issue 5886 - const fn (with no arguments)
-pub fn skip_const_fn_with_no_args() {
-    const fn foo() -> Option<i32> {
-        Some(42)
-    }
-    let _ = None.or(foo());
-
-    // See issue #5693.
-    let mut map = std::collections::HashMap::new();
-    map.insert(1, vec![1]);
-    map.entry(1).or_insert(vec![]);
-
-    let mut map = HashMap::<u64, String>::new();
-    map.entry(42).or_insert(String::new());
-
-    let mut btree = BTreeMap::<u64, String>::new();
-    btree.entry(42).or_insert(String::new());
-}
-
 fn main() {}
diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs
index 737b0f7e55b..522f31b72d0 100644
--- a/tests/ui/or_fun_call.rs
+++ b/tests/ui/or_fun_call.rs
@@ -58,6 +58,12 @@ fn or_fun_call() {
     let without_default = Some(Foo);
     without_default.unwrap_or(Foo::new());
 
+    let mut map = HashMap::<u64, String>::new();
+    map.entry(42).or_insert(String::new());
+
+    let mut btree = BTreeMap::<u64, String>::new();
+    btree.entry(42).or_insert(String::new());
+
     let stringy = Some(String::from(""));
     let _ = stringy.unwrap_or("".to_owned());
 
@@ -110,23 +116,4 @@ fn f() -> Option<()> {
     Some(())
 }
 
-// Issue 5886 - const fn (with no arguments)
-pub fn skip_const_fn_with_no_args() {
-    const fn foo() -> Option<i32> {
-        Some(42)
-    }
-    let _ = None.or(foo());
-
-    // See issue #5693.
-    let mut map = std::collections::HashMap::new();
-    map.insert(1, vec![1]);
-    map.entry(1).or_insert(vec![]);
-
-    let mut map = HashMap::<u64, String>::new();
-    map.entry(42).or_insert(String::new());
-
-    let mut btree = BTreeMap::<u64, String>::new();
-    btree.entry(42).or_insert(String::new());
-}
-
 fn main() {}
diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr
index b8a436993f3..bc5978b538f 100644
--- a/tests/ui/or_fun_call.stderr
+++ b/tests/ui/or_fun_call.stderr
@@ -60,23 +60,35 @@ error: use of `unwrap_or` followed by a function call
 LL |     without_default.unwrap_or(Foo::new());
    |                     ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)`
 
+error: use of `or_insert` followed by a function call
+  --> $DIR/or_fun_call.rs:62:19
+   |
+LL |     map.entry(42).or_insert(String::new());
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
+
+error: use of `or_insert` followed by a function call
+  --> $DIR/or_fun_call.rs:65:21
+   |
+LL |     btree.entry(42).or_insert(String::new());
+   |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
+
 error: use of `unwrap_or` followed by a function call
-  --> $DIR/or_fun_call.rs:62:21
+  --> $DIR/or_fun_call.rs:68:21
    |
 LL |     let _ = stringy.unwrap_or("".to_owned());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())`
 
 error: use of `or` followed by a function call
-  --> $DIR/or_fun_call.rs:87:35
+  --> $DIR/or_fun_call.rs:93:35
    |
 LL |     let _ = Some("a".to_string()).or(Some("b".to_string()));
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))`
 
 error: use of `or` followed by a function call
-  --> $DIR/or_fun_call.rs:91:10
+  --> $DIR/or_fun_call.rs:97:10
    |
 LL |         .or(Some(Bar(b, Duration::from_secs(2))));
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some(Bar(b, Duration::from_secs(2))))`
 
-error: aborting due to 13 previous errors
+error: aborting due to 15 previous errors
 
diff --git a/tests/ui/print_stdout_build_script.rs b/tests/ui/print_stdout_build_script.rs
new file mode 100644
index 00000000000..997ebef8a69
--- /dev/null
+++ b/tests/ui/print_stdout_build_script.rs
@@ -0,0 +1,12 @@
+// compile-flags: --crate-name=build_script_build
+
+#![warn(clippy::print_stdout)]
+
+fn main() {
+    // Fix #6041
+    //
+    // The `print_stdout` lint shouldn't emit in `build.rs`
+    // as these methods are used for the build script.
+    println!("Hello");
+    print!("Hello");
+}
diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs
index b4a931043b0..ac4c1bc6597 100644
--- a/tests/ui/temporary_assignment.rs
+++ b/tests/ui/temporary_assignment.rs
@@ -1,5 +1,4 @@
 #![warn(clippy::temporary_assignment)]
-#![allow(const_item_mutation)]
 
 use std::ops::{Deref, DerefMut};
 
diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr
index 4cc32c79f05..7d79901a28d 100644
--- a/tests/ui/temporary_assignment.stderr
+++ b/tests/ui/temporary_assignment.stderr
@@ -1,5 +1,5 @@
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:48:5
+  --> $DIR/temporary_assignment.rs:47:5
    |
 LL |     Struct { field: 0 }.field = 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     Struct { field: 0 }.field = 1;
    = note: `-D clippy::temporary-assignment` implied by `-D warnings`
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:49:5
+  --> $DIR/temporary_assignment.rs:48:5
    |
 LL | /     MultiStruct {
 LL | |         structure: Struct { field: 0 },
@@ -17,13 +17,13 @@ LL | |     .field = 1;
    | |______________^
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:54:5
+  --> $DIR/temporary_assignment.rs:53:5
    |
 LL |     ArrayStruct { array: [0] }.array[0] = 1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: assignment to temporary
-  --> $DIR/temporary_assignment.rs:55:5
+  --> $DIR/temporary_assignment.rs:54:5
    |
 LL |     (0, 0).0 = 1;
    |     ^^^^^^^^^^^^
diff --git a/util/dev b/util/dev
deleted file mode 100755
index 319de217e0d..00000000000
--- a/util/dev
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/sh
-CARGO_TARGET_DIR=$(pwd)/target/
-export CARGO_TARGET_DIR
-
-echo 'Deprecated! `util/dev` usage is deprecated, please use `cargo dev` instead.'
-
-cd clippy_dev && cargo run -- "$@"