Skip to content

Commit cc1998f

Browse files
committed
Auto merge of #6077 - ebroto:revert_or_fun_call_const, r=matthiaskrgr
Revert: or_fun_call should lint calls to `const fn`s with no args The changes in #5889 and #5984 were done under the incorrect assumption that a `const fn` with no args was guaranteed to be evaluated at compile time. A `const fn` is only guaranteed to be evaluated at compile time if it's inside a const context (the initializer of a `const` or a `static`). See this [zulip conversation](https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/Common.20misconception.3A.20.60const.20fn.60.20and.20its.20effect.20on.20codegen/near/208059113) for more details on this common misconception. Given that none of the linted methods by `or_fun_call` can be called in const contexts, the lint should make no exceptions. changelog: [`or_fun_call`] lints again calls to `const fn` with no args
2 parents 019c0d5 + ce83d8d commit cc1998f

File tree

4 files changed

+28
-51
lines changed

4 files changed

+28
-51
lines changed

clippy_lints/src/utils/mod.rs

-9
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ use rustc_lint::{LateContext, Level, Lint, LintContext};
4646
use rustc_middle::hir::map::Map;
4747
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
4848
use rustc_middle::ty::{self, layout::IntegerExt, Ty, TyCtxt, TypeFoldable};
49-
use rustc_mir::const_eval;
5049
use rustc_span::hygiene::{ExpnKind, MacroKind};
5150
use rustc_span::source_map::original_sp;
5251
use rustc_span::symbol::{self, kw, Symbol};
@@ -883,19 +882,11 @@ pub fn is_copy<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool {
883882

884883
/// Checks if an expression is constructing a tuple-like enum variant or struct
885884
pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
886-
fn has_no_arguments(cx: &LateContext<'_>, def_id: DefId) -> bool {
887-
cx.tcx.fn_sig(def_id).skip_binder().inputs().is_empty()
888-
}
889-
890885
if let ExprKind::Call(ref fun, _) = expr.kind {
891886
if let ExprKind::Path(ref qp) = fun.kind {
892887
let res = cx.qpath_res(qp, fun.hir_id);
893888
return match res {
894889
def::Res::Def(DefKind::Variant | DefKind::Ctor(..), ..) => true,
895-
// FIXME: check the constness of the arguments, see https://github.com/rust-lang/rust-clippy/pull/5682#issuecomment-638681210
896-
def::Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) if has_no_arguments(cx, def_id) => {
897-
const_eval::is_const_fn(cx.tcx, def_id)
898-
},
899890
def::Res::Def(_, def_id) => cx.tcx.is_promotable_const_fn(def_id),
900891
_ => false,
901892
};

tests/ui/or_fun_call.fixed

+6-19
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ fn or_fun_call() {
5858
let without_default = Some(Foo);
5959
without_default.unwrap_or_else(Foo::new);
6060

61+
let mut map = HashMap::<u64, String>::new();
62+
map.entry(42).or_insert_with(String::new);
63+
64+
let mut btree = BTreeMap::<u64, String>::new();
65+
btree.entry(42).or_insert_with(String::new);
66+
6167
let stringy = Some(String::from(""));
6268
let _ = stringy.unwrap_or_else(|| "".to_owned());
6369

@@ -110,23 +116,4 @@ fn f() -> Option<()> {
110116
Some(())
111117
}
112118

113-
// Issue 5886 - const fn (with no arguments)
114-
pub fn skip_const_fn_with_no_args() {
115-
const fn foo() -> Option<i32> {
116-
Some(42)
117-
}
118-
let _ = None.or(foo());
119-
120-
// See issue #5693.
121-
let mut map = std::collections::HashMap::new();
122-
map.insert(1, vec![1]);
123-
map.entry(1).or_insert(vec![]);
124-
125-
let mut map = HashMap::<u64, String>::new();
126-
map.entry(42).or_insert(String::new());
127-
128-
let mut btree = BTreeMap::<u64, String>::new();
129-
btree.entry(42).or_insert(String::new());
130-
}
131-
132119
fn main() {}

tests/ui/or_fun_call.rs

+6-19
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ fn or_fun_call() {
5858
let without_default = Some(Foo);
5959
without_default.unwrap_or(Foo::new());
6060

61+
let mut map = HashMap::<u64, String>::new();
62+
map.entry(42).or_insert(String::new());
63+
64+
let mut btree = BTreeMap::<u64, String>::new();
65+
btree.entry(42).or_insert(String::new());
66+
6167
let stringy = Some(String::from(""));
6268
let _ = stringy.unwrap_or("".to_owned());
6369

@@ -110,23 +116,4 @@ fn f() -> Option<()> {
110116
Some(())
111117
}
112118

113-
// Issue 5886 - const fn (with no arguments)
114-
pub fn skip_const_fn_with_no_args() {
115-
const fn foo() -> Option<i32> {
116-
Some(42)
117-
}
118-
let _ = None.or(foo());
119-
120-
// See issue #5693.
121-
let mut map = std::collections::HashMap::new();
122-
map.insert(1, vec![1]);
123-
map.entry(1).or_insert(vec![]);
124-
125-
let mut map = HashMap::<u64, String>::new();
126-
map.entry(42).or_insert(String::new());
127-
128-
let mut btree = BTreeMap::<u64, String>::new();
129-
btree.entry(42).or_insert(String::new());
130-
}
131-
132119
fn main() {}

tests/ui/or_fun_call.stderr

+16-4
Original file line numberDiff line numberDiff line change
@@ -60,23 +60,35 @@ error: use of `unwrap_or` followed by a function call
6060
LL | without_default.unwrap_or(Foo::new());
6161
| ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)`
6262

63+
error: use of `or_insert` followed by a function call
64+
--> $DIR/or_fun_call.rs:62:19
65+
|
66+
LL | map.entry(42).or_insert(String::new());
67+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
68+
69+
error: use of `or_insert` followed by a function call
70+
--> $DIR/or_fun_call.rs:65:21
71+
|
72+
LL | btree.entry(42).or_insert(String::new());
73+
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)`
74+
6375
error: use of `unwrap_or` followed by a function call
64-
--> $DIR/or_fun_call.rs:62:21
76+
--> $DIR/or_fun_call.rs:68:21
6577
|
6678
LL | let _ = stringy.unwrap_or("".to_owned());
6779
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())`
6880

6981
error: use of `or` followed by a function call
70-
--> $DIR/or_fun_call.rs:87:35
82+
--> $DIR/or_fun_call.rs:93:35
7183
|
7284
LL | let _ = Some("a".to_string()).or(Some("b".to_string()));
7385
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))`
7486

7587
error: use of `or` followed by a function call
76-
--> $DIR/or_fun_call.rs:91:10
88+
--> $DIR/or_fun_call.rs:97:10
7789
|
7890
LL | .or(Some(Bar(b, Duration::from_secs(2))));
7991
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some(Bar(b, Duration::from_secs(2))))`
8092

81-
error: aborting due to 13 previous errors
93+
error: aborting due to 15 previous errors
8294

0 commit comments

Comments
 (0)