11use  clippy_utils:: diagnostics:: span_lint_and_sugg; 
22use  clippy_utils:: macros:: macro_backtrace; 
3- use  clippy_utils:: source:: snippet_opt; 
43use  clippy_utils:: ty:: expr_sig; 
54use  clippy_utils:: { is_default_equivalent,  path_def_id} ; 
65use  rustc_errors:: Applicability ; 
@@ -9,20 +8,16 @@ use rustc_hir::intravisit::{walk_ty, Visitor};
98use  rustc_hir:: { Block ,  Expr ,  ExprKind ,  Local ,  Node ,  QPath ,  Ty ,  TyKind } ; 
109use  rustc_lint:: { LateContext ,  LateLintPass ,  LintContext } ; 
1110use  rustc_middle:: lint:: in_external_macro; 
12- use  rustc_middle:: ty:: print:: with_forced_trimmed_paths; 
13- use  rustc_middle:: ty:: IsSuggestable ; 
1411use  rustc_session:: declare_lint_pass; 
1512use  rustc_span:: sym; 
1613
1714declare_clippy_lint !  { 
1815    /// ### What it does 
19-      /// checks for `Box::new(T ::default())`, which is better  written as 
20-      /// `Box::<T>:: default()`. 
16+      /// checks for `Box::new(Default ::default())`, which can be  written as 
17+      /// `Box::default()`. 
2118     /// 
2219     /// ### Why is this bad? 
23-      /// First, it's more complex, involving two calls instead of one. 
24-      /// Second, `Box::default()` can be faster 
25-      /// [in certain cases](https://nnethercote.github.io/perf-book/standard-library-types.html#box). 
20+      /// `Box::default()` is equivalent and more concise. 
2621     /// 
2722     /// ### Example 
2823     /// ```no_run 
@@ -34,7 +29,7 @@ declare_clippy_lint! {
3429     /// ``` 
3530     #[ clippy:: version = "1.66.0" ] 
3631    pub  BOX_DEFAULT , 
37-     perf , 
32+     style , 
3833    "Using Box::new(T::default()) instead of Box::default()" 
3934} 
4035
@@ -53,38 +48,22 @@ impl LateLintPass<'_> for BoxDefault {
5348            && path_def_id ( cx,  ty) . map_or ( false ,  |id| Some ( id)  == cx. tcx . lang_items ( ) . owned_box ( ) ) 
5449            // And the single argument to the call is another function call 
5550            // This is the `T::default()` of `Box::new(T::default())` 
56-             && let  ExprKind :: Call ( arg_path,  inner_call_args )  = arg. kind 
51+             && let  ExprKind :: Call ( arg_path,  _ )  = arg. kind 
5752            // And we are not in a foreign crate's macro 
5853            && !in_external_macro ( cx. sess ( ) ,  expr. span ) 
5954            // And the argument expression has the same context as the outer call expression 
6055            // or that we are inside a `vec!` macro expansion 
6156            && ( expr. span . eq_ctxt ( arg. span )  || is_local_vec_expn ( cx,  arg,  expr) ) 
62-             // And the argument is equivalent to  `Default::default()` 
63-             && is_default_equivalent ( cx,  arg) 
57+             // And the argument is `Default::default()` or the type is specified  
58+             && ( is_plain_default ( cx ,  arg_path )  ||  ( given_type ( cx ,  expr )  &&  is_default_equivalent ( cx,  arg) ) ) 
6459        { 
6560            span_lint_and_sugg ( 
6661                cx, 
6762                BOX_DEFAULT , 
6863                expr. span , 
6964                "`Box::new(_)` of default value" , 
7065                "try" , 
71-                 if  is_plain_default ( cx,  arg_path)  || given_type ( cx,  expr)  { 
72-                     "Box::default()" . into ( ) 
73-                 }  else  if  let  Some ( arg_ty)  = cx. typeck_results ( ) . expr_ty ( arg) . make_suggestable ( cx. tcx ,  true )  { 
74-                     // Check if we can copy from the source expression in the replacement. 
75-                     // We need the call to have no argument (see `explicit_default_type`). 
76-                     if  inner_call_args. is_empty ( ) 
77-                         && let  Some ( ty)  = explicit_default_type ( arg_path) 
78-                         && let  Some ( s)  = snippet_opt ( cx,  ty. span ) 
79-                     { 
80-                         format ! ( "Box::<{s}>::default()" ) 
81-                     }  else  { 
82-                         // Otherwise, use the inferred type's formatting. 
83-                         with_forced_trimmed_paths ! ( format!( "Box::<{arg_ty}>::default()" ) ) 
84-                     } 
85-                 }  else  { 
86-                     return ; 
87-                 } , 
66+                 "Box::default()" . into ( ) , 
8867                Applicability :: MachineApplicable , 
8968            ) ; 
9069        } 
@@ -103,20 +82,6 @@ fn is_plain_default(cx: &LateContext<'_>, arg_path: &Expr<'_>) -> bool {
10382    } 
10483} 
10584
106- // Checks whether the call is of the form `A::B::f()`. Returns `A::B` if it is. 
107- // 
108- // In the event we have this kind of construct, it's easy to use `A::B` as a replacement in the 
109- // quickfix. `f` must however have no parameter. Should `f` have some, then some of the type of 
110- // `A::B` may be inferred from the arguments. This would be the case for `Vec::from([0; false])`, 
111- // where the argument to `from` allows inferring this is a `Vec<bool>` 
112- fn  explicit_default_type < ' a > ( arg_path :  & ' a  Expr < ' _ > )  -> Option < & ' a  Ty < ' a > >  { 
113-     if  let  ExprKind :: Path ( QPath :: TypeRelative ( ty,  _) )  = & arg_path. kind  { 
114-         Some ( ty) 
115-     }  else  { 
116-         None 
117-     } 
118- } 
119- 
12085fn  is_local_vec_expn ( cx :  & LateContext < ' _ > ,  expr :  & Expr < ' _ > ,  ref_expr :  & Expr < ' _ > )  -> bool  { 
12186    macro_backtrace ( expr. span ) . next ( ) . map_or ( false ,  |call| { 
12287        cx. tcx . is_diagnostic_item ( sym:: vec_macro,  call. def_id )  && call. span . eq_ctxt ( ref_expr. span ) 
0 commit comments