about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-10 22:12:38 +0000
committerbors <bors@rust-lang.org>2020-08-10 22:12:38 +0000
commit16831891da49422e08c597a3857c2091ca220cbc (patch)
tree04c4f1120412dfeaffa6b5e21dc4fd62566d39de
parent41134532023a8e5bbbe621f2538e61049ceafe6b (diff)
parent5d66bd7bb3fd701d70ec11217e3f89fabe5cb0a7 (diff)
downloadrust-16831891da49422e08c597a3857c2091ca220cbc.tar.gz
rust-16831891da49422e08c597a3857c2091ca220cbc.zip
Auto merge of #5889 - ebroto:5886_or_fun_call_const_0_args, r=Manishearth
Avoid or_fun_call for const_fn with no args

Based on #5682 by @lzutao

This avoids a subset of false positives, specifically those related to `const fn`s that take no arguments.
For the rest, a much more involved fix would be needed, see https://github.com/rust-lang/rust-clippy/pull/5682#issuecomment-638681210.

So this does *not* solve #5658

changelog: Avoid triggering [`or_fun_call`] with `const fn`s that take no arguments.

Fixes #5886
-rw-r--r--clippy_lints/src/utils/mod.rs9
-rw-r--r--tests/ui/or_fun_call.fixed8
-rw-r--r--tests/ui/or_fun_call.rs8
3 files changed, 25 insertions, 0 deletions
diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs
index 9f967d59c8b..223628cc610 100644
--- a/clippy_lints/src/utils/mod.rs
+++ b/clippy_lints/src/utils/mod.rs
@@ -43,6 +43,7 @@ use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, Level, Lint, LintContext};
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, 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};
@@ -868,11 +869,19 @@ 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, 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/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed
index 2045ffdb5f0..67faa8bd4a0 100644
--- a/tests/ui/or_fun_call.fixed
+++ b/tests/ui/or_fun_call.fixed
@@ -116,4 +116,12 @@ 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());
+}
+
 fn main() {}
diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs
index 522f31b72d0..9867e2eedcf 100644
--- a/tests/ui/or_fun_call.rs
+++ b/tests/ui/or_fun_call.rs
@@ -116,4 +116,12 @@ 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());
+}
+
 fn main() {}