Skip to content

Commit e648adf

Browse files
committed
Auto merge of #3674 - sinkuu:fmt_rustup, r=oli-obk
Catch up with `format_args` change Catches up with a change in rust-lang/rust#57537. (Since the optimization is optional, this clippy PR can be merged before the rustc PR.) Happened to fix a bug in `expect_fun_call`, that is the lint ignores more than one arguments to `format`. ``` warning: use of `expect` followed by a function call --> src/main.rs:2:17 | 2 | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1))` | ```
2 parents 751d82e + 2ee713d commit e648adf

File tree

5 files changed

+31
-18
lines changed

5 files changed

+31
-18
lines changed

clippy_lints/src/format.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
5353
ExprKind::Call(ref fun, ref args) => {
5454
if_chain! {
5555
if let ExprKind::Path(ref qpath) = fun.node;
56-
if args.len() == 3;
5756
if let Some(fun_def_id) = opt_def_id(resolve_node(cx, qpath, fun.hir_id));
58-
if match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1FORMATTED);
57+
let new_v1 = match_def_path(cx.tcx, fun_def_id, &paths::FMT_ARGUMENTS_NEWV1);
58+
let new_v1_fmt = match_def_path(
59+
cx.tcx,
60+
fun_def_id,
61+
&paths::FMT_ARGUMENTS_NEWV1FORMATTED
62+
);
63+
if new_v1 || new_v1_fmt;
5964
if check_single_piece(&args[0]);
6065
if let Some(format_arg) = get_single_string_arg(cx, &args[1]);
61-
if check_unformatted(&args[2]);
66+
if new_v1 || check_unformatted(&args[2]);
6267
if let ExprKind::AddrOf(_, ref format_arg) = format_arg.node;
6368
then {
6469
let (message, sugg) = if_chain! {

clippy_lints/src/methods/mod.rs

+13-14
Original file line numberDiff line numberDiff line change
@@ -1148,7 +1148,7 @@ fn lint_or_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Spa
11481148

11491149
/// Checks for the `EXPECT_FUN_CALL` lint.
11501150
fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span: Span, name: &str, args: &[hir::Expr]) {
1151-
fn extract_format_args(arg: &hir::Expr) -> Option<&hir::HirVec<hir::Expr>> {
1151+
fn extract_format_args(arg: &hir::Expr) -> Option<(&hir::Expr, &hir::Expr)> {
11521152
let arg = match &arg.node {
11531153
hir::ExprKind::AddrOf(_, expr) => expr,
11541154
hir::ExprKind::MethodCall(method_name, _, args)
@@ -1161,8 +1161,8 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
11611161

11621162
if let hir::ExprKind::Call(ref inner_fun, ref inner_args) = arg.node {
11631163
if is_expn_of(inner_fun.span, "format").is_some() && inner_args.len() == 1 {
1164-
if let hir::ExprKind::Call(_, ref format_args) = inner_args[0].node {
1165-
return Some(format_args);
1164+
if let hir::ExprKind::Call(_, format_args) = &inner_args[0].node {
1165+
return Some((&format_args[0], &format_args[1]));
11661166
}
11671167
}
11681168
}
@@ -1174,17 +1174,19 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
11741174
cx: &LateContext<'_, '_>,
11751175
a: &hir::Expr,
11761176
applicability: &mut Applicability,
1177-
) -> String {
1177+
) -> Vec<String> {
11781178
if let hir::ExprKind::AddrOf(_, ref format_arg) = a.node {
11791179
if let hir::ExprKind::Match(ref format_arg_expr, _, _) = format_arg.node {
11801180
if let hir::ExprKind::Tup(ref format_arg_expr_tup) = format_arg_expr.node {
1181-
return snippet_with_applicability(cx, format_arg_expr_tup[0].span, "..", applicability)
1182-
.into_owned();
1181+
return format_arg_expr_tup
1182+
.iter()
1183+
.map(|a| snippet_with_applicability(cx, a.span, "..", applicability).into_owned())
1184+
.collect();
11831185
}
11841186
}
11851187
};
11861188

1187-
snippet(cx, a.span, "..").into_owned()
1189+
unreachable!()
11881190
}
11891191

11901192
fn check_general_case(
@@ -1233,14 +1235,11 @@ fn lint_expect_fun_call(cx: &LateContext<'_, '_>, expr: &hir::Expr, method_span:
12331235
};
12341236
let span_replace_word = method_span.with_hi(span.hi());
12351237

1236-
if let Some(format_args) = extract_format_args(arg) {
1238+
if let Some((fmt_spec, fmt_args)) = extract_format_args(arg) {
12371239
let mut applicability = Applicability::MachineApplicable;
1238-
let args_len = format_args.len();
1239-
let args: Vec<String> = format_args
1240-
.into_iter()
1241-
.take(args_len - 1)
1242-
.map(|a| generate_format_arg_snippet(cx, a, &mut applicability))
1243-
.collect();
1240+
let mut args = vec![snippet(cx, fmt_spec.span, "..").into_owned()];
1241+
1242+
args.extend(generate_format_arg_snippet(cx, fmt_args, &mut applicability));
12441243

12451244
let sugg = args.join(", ");
12461245

clippy_lints/src/utils/paths.rs

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub const DOUBLE_ENDED_ITERATOR: [&str; 4] = ["core", "iter", "traits", "DoubleE
2626
pub const DROP: [&str; 3] = ["core", "mem", "drop"];
2727
pub const DURATION: [&str; 3] = ["core", "time", "Duration"];
2828
pub const EARLY_CONTEXT: [&str; 4] = ["rustc", "lint", "context", "EarlyContext"];
29+
pub const FMT_ARGUMENTS_NEWV1: [&str; 4] = ["core", "fmt", "Arguments", "new_v1"];
2930
pub const FMT_ARGUMENTS_NEWV1FORMATTED: [&str; 4] = ["core", "fmt", "Arguments", "new_v1_formatted"];
3031
pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"];
3132
pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"];

tests/ui/expect_fun_call.rs

+2
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ fn expect_fun_call() {
5757

5858
Some("foo").expect({ &format!("error") });
5959
Some("foo").expect(format!("error").as_ref());
60+
61+
Some("foo").expect(format!("{} {}", 1, 2).as_ref());
6062
}
6163

6264
fn main() {}

tests/ui/expect_fun_call.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -36,5 +36,11 @@ error: use of `expect` followed by a function call
3636
LL | Some("foo").expect(format!("error").as_ref());
3737
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("error"))`
3838

39-
error: aborting due to 6 previous errors
39+
error: use of `expect` followed by a function call
40+
--> $DIR/expect_fun_call.rs:61:17
41+
|
42+
LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref());
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| panic!("{} {}", 1, 2))`
44+
45+
error: aborting due to 7 previous errors
4046

0 commit comments

Comments
 (0)