Don't suggest unnameable types in box_default, let_underscore_untyped

This commit is contained in:
Alex Macleod 2023-05-18 12:33:52 +00:00
parent 22b319606f
commit cfa5aa2aad
6 changed files with 35 additions and 18 deletions

View File

@ -8,7 +8,9 @@ use rustc_hir::{
Block, Expr, ExprKind, Local, Node, QPath, TyKind, Block, Expr, ExprKind, Local, Node, QPath, TyKind,
}; };
use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::{lint::in_external_macro, ty::print::with_forced_trimmed_paths}; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::print::with_forced_trimmed_paths;
use rustc_middle::ty::IsSuggestable;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym; use rustc_span::sym;
@ -49,7 +51,6 @@ impl LateLintPass<'_> for BoxDefault {
&& path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box()) && path_def_id(cx, ty).map_or(false, |id| Some(id) == cx.tcx.lang_items().owned_box())
&& is_default_equivalent(cx, arg) && is_default_equivalent(cx, arg)
{ {
let arg_ty = cx.typeck_results().expr_ty(arg);
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
BOX_DEFAULT, BOX_DEFAULT,
@ -58,8 +59,10 @@ impl LateLintPass<'_> for BoxDefault {
"try", "try",
if is_plain_default(arg_path) || given_type(cx, expr) { if is_plain_default(arg_path) || given_type(cx, expr) {
"Box::default()".into() "Box::default()".into()
} else { } else if let Some(arg_ty) = cx.typeck_results().expr_ty(arg).make_suggestable(cx.tcx, true) {
with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()")) with_forced_trimmed_paths!(format!("Box::<{arg_ty}>::default()"))
} else {
return
}, },
Applicability::MachineApplicable Applicability::MachineApplicable
); );

View File

@ -2,10 +2,11 @@ use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::is_from_proc_macro; use clippy_utils::is_from_proc_macro;
use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type}; use clippy_utils::ty::{implements_trait, is_must_use_ty, match_type};
use clippy_utils::{is_must_use_func_call, paths}; use clippy_utils::{is_must_use_func_call, paths};
use rustc_hir::{ExprKind, Local, PatKind}; use rustc_hir::{Local, PatKind};
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::lint::in_external_macro; use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::subst::GenericArgKind;
use rustc_middle::ty::IsSuggestable;
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::{BytePos, Span}; use rustc_span::{BytePos, Span};
@ -192,14 +193,12 @@ impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
if local.pat.default_binding_modes && local.ty.is_none() { if local.pat.default_binding_modes && local.ty.is_none() {
// When `default_binding_modes` is true, the `let` keyword is present. // When `default_binding_modes` is true, the `let` keyword is present.
// Ignore function calls that return impl traits... // Ignore unnameable types
if let Some(init) = local.init && if let Some(init) = local.init
matches!(init.kind, ExprKind::Call(_, _) | ExprKind::MethodCall(_, _, _, _)) { && !cx.typeck_results().expr_ty(init).is_suggestable(cx.tcx, true)
let expr_ty = cx.typeck_results().expr_ty(init); {
if expr_ty.is_impl_trait() { return;
return; }
}
}
// Ignore if it is from a procedural macro... // Ignore if it is from a procedural macro...
if is_from_proc_macro(cx, init) { if is_from_proc_macro(cx, init) {

View File

@ -1,6 +1,6 @@
//@run-rustfix //@run-rustfix
#![warn(clippy::box_default)] #![warn(clippy::box_default)]
#![allow(clippy::default_constructed_unit_structs)] #![allow(unused, clippy::default_constructed_unit_structs)]
#[derive(Default)] #[derive(Default)]
struct ImplementsDefault; struct ImplementsDefault;
@ -35,6 +35,13 @@ fn main() {
let _more = ret_ty_fn(); let _more = ret_ty_fn();
call_ty_fn(Box::default()); call_ty_fn(Box::default());
issue_10381(); issue_10381();
// `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
// `Box::<Option<[closure@...]>::default()`
//
// Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
let mut unnameable = Box::new(Option::default());
let _ = unnameable.insert(|| {});
} }
fn ret_ty_fn() -> Box<bool> { fn ret_ty_fn() -> Box<bool> {

View File

@ -1,6 +1,6 @@
//@run-rustfix //@run-rustfix
#![warn(clippy::box_default)] #![warn(clippy::box_default)]
#![allow(clippy::default_constructed_unit_structs)] #![allow(unused, clippy::default_constructed_unit_structs)]
#[derive(Default)] #[derive(Default)]
struct ImplementsDefault; struct ImplementsDefault;
@ -35,6 +35,13 @@ fn main() {
let _more = ret_ty_fn(); let _more = ret_ty_fn();
call_ty_fn(Box::new(u8::default())); call_ty_fn(Box::new(u8::default()));
issue_10381(); issue_10381();
// `Box::<Option<_>>::default()` would be valid here, but not `Box::default()` or
// `Box::<Option<[closure@...]>::default()`
//
// Would have a suggestion after https://github.com/rust-lang/rust/blob/fdd030127cc68afec44a8d3f6341525dd34e50ae/compiler/rustc_middle/src/ty/diagnostics.rs#L554-L563
let mut unnameable = Box::new(Option::default());
let _ = unnameable.insert(|| {});
} }
fn ret_ty_fn() -> Box<bool> { fn ret_ty_fn() -> Box<bool> {

View File

@ -73,25 +73,25 @@ LL | call_ty_fn(Box::new(u8::default()));
| ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()` | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::default()`
error: `Box::new(_)` of default value error: `Box::new(_)` of default value
--> $DIR/box_default.rs:41:5 --> $DIR/box_default.rs:48:5
| |
LL | Box::new(bool::default()) LL | Box::new(bool::default())
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()` | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<bool>::default()`
error: `Box::new(_)` of default value error: `Box::new(_)` of default value
--> $DIR/box_default.rs:58:28 --> $DIR/box_default.rs:65:28
| |
LL | let _: Box<dyn Read> = Box::new(ImplementsDefault::default()); LL | let _: Box<dyn Read> = Box::new(ImplementsDefault::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<ImplementsDefault>::default()`
error: `Box::new(_)` of default value error: `Box::new(_)` of default value
--> $DIR/box_default.rs:67:17 --> $DIR/box_default.rs:74:17
| |
LL | let _ = Box::new(WeirdPathed::default()); LL | let _ = Box::new(WeirdPathed::default());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()` | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<WeirdPathed>::default()`
error: `Box::new(_)` of default value error: `Box::new(_)` of default value
--> $DIR/box_default.rs:79:18 --> $DIR/box_default.rs:86:18
| |
LL | Some(Box::new(Foo::default())) LL | Some(Box::new(Foo::default()))
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Foo>::default()` | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::<Foo>::default()`

View File

@ -54,6 +54,7 @@ fn main() {
let _ = e(); let _ = e();
let _ = f(); let _ = f();
let _ = g(); let _ = g();
let closure = || {};
_ = a(); _ = a();
_ = b(1); _ = b(1);