diff --git a/clippy_lints/src/unit_types/let_unit_value.rs b/clippy_lints/src/unit_types/let_unit_value.rs index 424aa14cd686..2645e94358e1 100644 --- a/clippy_lints/src/unit_types/let_unit_value.rs +++ b/clippy_lints/src/unit_types/let_unit_value.rs @@ -90,11 +90,12 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, format_args: &FormatArgsStorag let mut has_in_format_capture = false; suggestions.extend(visitor.spans.into_iter().filter_map(|span| match span { - MaybeInFormatCapture::Yes => { + VariableUsage::FormatCapture => { has_in_format_capture = true; None }, - MaybeInFormatCapture::No(span) => Some((span, "()".to_string())), + VariableUsage::Normal(span) => Some((span, "()".to_string())), + VariableUsage::FieldShorthand(span) => Some((span.shrink_to_hi(), ": ()".to_string())), })); if has_in_format_capture { @@ -141,19 +142,30 @@ struct UnitVariableCollector<'a, 'tcx> { cx: &'a LateContext<'tcx>, format_args: &'a FormatArgsStorage, id: HirId, - spans: Vec, + spans: Vec, macro_call: Option<&'a FormatArgs>, } -/// Whether the unit variable is captured in a `format!`: -/// -/// ```ignore -/// let unit = (); -/// eprintln!("{unit}"); -/// ``` -enum MaybeInFormatCapture { - Yes, - No(Span), +/// How the unit variable is used +enum VariableUsage { + Normal(Span), + /// Captured in a `format!`: + /// + /// ```ignore + /// let unit = (); + /// eprintln!("{unit}"); + /// ``` + FormatCapture, + /// In a field shorthand init: + /// + /// ```ignore + /// struct Foo { + /// unit: (), + /// } + /// let unit = (); + /// Foo { unit }; + /// ``` + FieldShorthand(Span), } impl<'a, 'tcx> UnitVariableCollector<'a, 'tcx> { @@ -193,9 +205,17 @@ impl<'tcx> Visitor<'tcx> for UnitVariableCollector<'_, 'tcx> { matches!(arg.kind, FormatArgumentKind::Captured(_)) && find_format_arg_expr(ex, arg).is_some() }) { - self.spans.push(MaybeInFormatCapture::Yes); + self.spans.push(VariableUsage::FormatCapture); } else { - self.spans.push(MaybeInFormatCapture::No(path.span)); + let parent = self.cx.tcx.parent_hir_node(ex.hir_id); + match parent { + Node::ExprField(expr_field) if expr_field.is_shorthand => { + self.spans.push(VariableUsage::FieldShorthand(ex.span)); + }, + _ => { + self.spans.push(VariableUsage::Normal(path.span)); + }, + } } } diff --git a/tests/ui/let_unit.fixed b/tests/ui/let_unit.fixed index e8517f18e788..6d984a495d2b 100644 --- a/tests/ui/let_unit.fixed +++ b/tests/ui/let_unit.fixed @@ -229,3 +229,13 @@ fn issue_15784() { takes_unit(()); println!("{res:?}"); } + +fn issue15789() { + struct Foo { + value: (), + } + println!(); + //~^ let_unit_value + + Foo { value: () }; +} diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index 3f6f0139b2fe..a0e32f0b67a0 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -227,3 +227,13 @@ fn issue_15784() { takes_unit(res); println!("{res:?}"); } + +fn issue15789() { + struct Foo { + value: (), + } + let value = println!(); + //~^ let_unit_value + + Foo { value }; +} diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index 8ced32ab828f..6e7b958df4d9 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -114,5 +114,19 @@ LL | LL ~ takes_unit(()); | -error: aborting due to 8 previous errors +error: this let-binding has unit value + --> tests/ui/let_unit.rs:235:5 + | +LL | let value = println!(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: omit the `let` binding and replace variable usages with `()` + | +LL ~ println!(); +LL | +LL | +LL ~ Foo { value: () }; + | + +error: aborting due to 9 previous errors