@@ -1153,27 +1153,70 @@ fn detect_same_item_push<'tcx>(
11531153 let vec_str = snippet_with_macro_callsite ( cx, vec. span , "" ) ;
11541154 let item_str = snippet_with_macro_callsite ( cx, pushed_item. span , "" ) ;
11551155 if let ExprKind :: Path ( ref qpath) = pushed_item. kind {
1156- if_chain ! {
1157- if let Res :: Local ( hir_id) = qpath_res( cx, qpath, pushed_item. hir_id) ;
1158- let node = cx. tcx. hir( ) . get( hir_id) ;
1159- if let Node :: Binding ( pat) = node;
1160- if let PatKind :: Binding ( bind_ann, ..) = pat. kind;
1161- if !matches!( bind_ann, BindingAnnotation :: RefMut | BindingAnnotation :: Mutable ) ;
1162- then {
1163- span_lint_and_help(
1164- cx,
1165- SAME_ITEM_PUSH ,
1166- vec. span,
1167- "it looks like the same item is being pushed into this Vec" ,
1168- None ,
1169- & format!(
1170- "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1171- item_str, vec_str, item_str
1172- ) ,
1173- )
1174- }
1156+ match qpath_res ( cx, qpath, pushed_item. hir_id ) {
1157+ // immutable bindings that are initialized with literal or constant
1158+ Res :: Local ( hir_id) => {
1159+ if_chain ! {
1160+ let node = cx. tcx. hir( ) . get( hir_id) ;
1161+ if let Node :: Binding ( pat) = node;
1162+ if let PatKind :: Binding ( bind_ann, ..) = pat. kind;
1163+ if !matches!( bind_ann, BindingAnnotation :: RefMut | BindingAnnotation :: Mutable ) ;
1164+ let parent_node = cx. tcx. hir( ) . get_parent_node( hir_id) ;
1165+ if let Some ( Node :: Local ( parent_let_expr) ) = cx. tcx. hir( ) . find( parent_node) ;
1166+ if let rustc_hir:: Local { init: Some ( init) , .. } = parent_let_expr;
1167+ then {
1168+ match init. kind {
1169+ // immutable bindings that are initialized with literal
1170+ ExprKind :: Lit ( ..) => {
1171+ span_lint_and_help(
1172+ cx,
1173+ SAME_ITEM_PUSH ,
1174+ vec. span,
1175+ "it looks like the same item is being pushed into this Vec" ,
1176+ None ,
1177+ & format!(
1178+ "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1179+ item_str, vec_str, item_str
1180+ ) ,
1181+ )
1182+ } ,
1183+ // immutable bindings that are initialized with constant
1184+ ExprKind :: Path ( ref path) => {
1185+ if let Res :: Def ( DefKind :: Const , ..) = qpath_res( cx, path, init. hir_id) {
1186+ span_lint_and_help(
1187+ cx,
1188+ SAME_ITEM_PUSH ,
1189+ vec. span,
1190+ "it looks like the same item is being pushed into this Vec" ,
1191+ None ,
1192+ & format!(
1193+ "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1194+ item_str, vec_str, item_str
1195+ ) ,
1196+ )
1197+ }
1198+ }
1199+ _ => { } ,
1200+ }
1201+ }
1202+ }
1203+ } ,
1204+ // constant
1205+ Res :: Def ( DefKind :: Const , ..) => span_lint_and_help (
1206+ cx,
1207+ SAME_ITEM_PUSH ,
1208+ vec. span ,
1209+ "it looks like the same item is being pushed into this Vec" ,
1210+ None ,
1211+ & format ! (
1212+ "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1213+ item_str, vec_str, item_str
1214+ ) ,
1215+ ) ,
1216+ _ => { } ,
11751217 }
1176- } else if mutated_variables ( pushed_item, cx) . map_or ( false , |mutvars| mutvars. is_empty ( ) ) {
1218+ } else if let ExprKind :: Lit ( ..) = pushed_item. kind {
1219+ // literal
11771220 span_lint_and_help (
11781221 cx,
11791222 SAME_ITEM_PUSH ,
0 commit comments