11use super :: SAME_ITEM_PUSH ;
2- use clippy_utils:: diagnostics:: span_lint_and_help ;
3- use clippy_utils:: path_to_local ;
2+ use clippy_utils:: diagnostics:: span_lint_and_then ;
3+ use clippy_utils:: msrvs :: Msrv ;
44use clippy_utils:: source:: snippet_with_context;
55use clippy_utils:: ty:: { implements_trait, is_type_diagnostic_item} ;
6+ use clippy_utils:: { msrvs, path_to_local, std_or_core} ;
67use rustc_data_structures:: fx:: FxHashSet ;
78use rustc_errors:: Applicability ;
89use rustc_hir:: def:: { DefKind , Res } ;
@@ -19,19 +20,30 @@ pub(super) fn check<'tcx>(
1920 _: & ' tcx Expr < ' _ > ,
2021 body : & ' tcx Expr < ' _ > ,
2122 _: & ' tcx Expr < ' _ > ,
23+ msrv : & Msrv ,
2224) {
23- fn emit_lint ( cx : & LateContext < ' _ > , vec : & Expr < ' _ > , pushed_item : & Expr < ' _ > , ctxt : SyntaxContext ) {
25+ fn emit_lint ( cx : & LateContext < ' _ > , vec : & Expr < ' _ > , pushed_item : & Expr < ' _ > , ctxt : SyntaxContext , msrv : & Msrv ) {
2426 let mut app = Applicability :: Unspecified ;
2527 let vec_str = snippet_with_context ( cx, vec. span , ctxt, "" , & mut app) . 0 ;
2628 let item_str = snippet_with_context ( cx, pushed_item. span , ctxt, "" , & mut app) . 0 ;
2729
28- span_lint_and_help (
30+ let secondary_help = if msrv. meets ( msrvs:: REPEAT_N )
31+ && let Some ( std_or_core) = std_or_core ( cx)
32+ {
33+ format ! ( "or `{vec_str}.extend({std_or_core}::iter::repeat_n({item_str}, SIZE))`" )
34+ } else {
35+ format ! ( "or `{vec_str}.resize(NEW_SIZE, {item_str})`" )
36+ } ;
37+
38+ span_lint_and_then (
2939 cx,
3040 SAME_ITEM_PUSH ,
3141 vec. span ,
32- "it looks like the same item is being pushed into this Vec" ,
33- None ,
34- format ! ( "consider using vec![{item_str};SIZE] or {vec_str}.resize(NEW_SIZE, {item_str})" ) ,
42+ "it looks like the same item is being pushed into this `Vec`" ,
43+ |diag| {
44+ diag. help ( format ! ( "consider using `vec![{item_str};SIZE]`" ) )
45+ . help ( secondary_help) ;
46+ } ,
3547 ) ;
3648 }
3749
@@ -67,23 +79,23 @@ pub(super) fn check<'tcx>(
6779 {
6880 match init. kind {
6981 // immutable bindings that are initialized with literal
70- ExprKind :: Lit ( ..) => emit_lint ( cx, vec, pushed_item, ctxt) ,
82+ ExprKind :: Lit ( ..) => emit_lint ( cx, vec, pushed_item, ctxt, msrv ) ,
7183 // immutable bindings that are initialized with constant
7284 ExprKind :: Path ( ref path) => {
7385 if let Res :: Def ( DefKind :: Const , ..) = cx. qpath_res ( path, init. hir_id ) {
74- emit_lint ( cx, vec, pushed_item, ctxt) ;
86+ emit_lint ( cx, vec, pushed_item, ctxt, msrv ) ;
7587 }
7688 } ,
7789 _ => { } ,
7890 }
7991 }
8092 } ,
8193 // constant
82- Res :: Def ( DefKind :: Const , ..) => emit_lint ( cx, vec, pushed_item, ctxt) ,
94+ Res :: Def ( DefKind :: Const , ..) => emit_lint ( cx, vec, pushed_item, ctxt, msrv ) ,
8395 _ => { } ,
8496 }
8597 } ,
86- ExprKind :: Lit ( ..) => emit_lint ( cx, vec, pushed_item, ctxt) ,
98+ ExprKind :: Lit ( ..) => emit_lint ( cx, vec, pushed_item, ctxt, msrv ) ,
8799 _ => { } ,
88100 }
89101 }
0 commit comments