@@ -1140,43 +1140,51 @@ fn detect_same_item_push<'tcx>(
11401140 walk_expr ( & mut same_item_push_visitor, body) ;
11411141 if same_item_push_visitor. should_lint {
11421142 if let Some ( ( vec, pushed_item) ) = same_item_push_visitor. vec_push {
1143- // Make sure that the push does not involve possibly mutating values
1144- if let PatKind :: Wild = pat. kind {
1145- let vec_str = snippet_with_macro_callsite ( cx, vec. span , "" ) ;
1146- let item_str = snippet_with_macro_callsite ( cx, pushed_item. span , "" ) ;
1147- if let ExprKind :: Path ( ref qpath) = pushed_item. kind {
1148- if_chain ! {
1149- if let Res :: Local ( hir_id) = qpath_res( cx, qpath, pushed_item. hir_id) ;
1150- let node = cx. tcx. hir( ) . get( hir_id) ;
1151- if let Node :: Binding ( pat) = node;
1152- if let PatKind :: Binding ( bind_ann, ..) = pat. kind;
1153- if !matches!( bind_ann, BindingAnnotation :: RefMut | BindingAnnotation :: Mutable ) ;
1154- then {
1155- span_lint_and_help(
1156- cx,
1157- SAME_ITEM_PUSH ,
1158- vec. span,
1159- "it looks like the same item is being pushed into this Vec" ,
1160- None ,
1161- & format!(
1162- "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1163- item_str, vec_str, item_str
1164- ) ,
1165- )
1143+ let ty = cx. typeck_results ( ) . expr_ty ( pushed_item) ;
1144+ if cx
1145+ . tcx
1146+ . lang_items ( )
1147+ . clone_trait ( )
1148+ . map_or ( false , |id| implements_trait ( cx, ty, id, & [ ] ) )
1149+ {
1150+ // Make sure that the push does not involve possibly mutating values
1151+ if let PatKind :: Wild = pat. kind {
1152+ let vec_str = snippet_with_macro_callsite ( cx, vec. span , "" ) ;
1153+ let item_str = snippet_with_macro_callsite ( cx, pushed_item. span , "" ) ;
1154+ if let ExprKind :: Path ( ref qpath) = pushed_item. kind {
1155+ if_chain ! {
1156+ if let Res :: Local ( hir_id) = qpath_res( cx, qpath, pushed_item. hir_id) ;
1157+ let node = cx. tcx. hir( ) . get( hir_id) ;
1158+ if let Node :: Binding ( pat) = node;
1159+ if let PatKind :: Binding ( bind_ann, ..) = pat. kind;
1160+ if !matches!( bind_ann, BindingAnnotation :: RefMut | BindingAnnotation :: Mutable ) ;
1161+ then {
1162+ span_lint_and_help(
1163+ cx,
1164+ SAME_ITEM_PUSH ,
1165+ vec. span,
1166+ "it looks like the same item is being pushed into this Vec" ,
1167+ None ,
1168+ & format!(
1169+ "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1170+ item_str, vec_str, item_str
1171+ ) ,
1172+ )
1173+ }
11661174 }
1175+ } else if mutated_variables ( pushed_item, cx) . map_or ( false , |mutvars| mutvars. is_empty ( ) ) {
1176+ span_lint_and_help (
1177+ cx,
1178+ SAME_ITEM_PUSH ,
1179+ vec. span ,
1180+ "it looks like the same item is being pushed into this Vec" ,
1181+ None ,
1182+ & format ! (
1183+ "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1184+ item_str, vec_str, item_str
1185+ ) ,
1186+ )
11671187 }
1168- } else if mutated_variables ( pushed_item, cx) . map_or ( false , |mutvars| mutvars. is_empty ( ) ) {
1169- span_lint_and_help (
1170- cx,
1171- SAME_ITEM_PUSH ,
1172- vec. span ,
1173- "it looks like the same item is being pushed into this Vec" ,
1174- None ,
1175- & format ! (
1176- "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1177- item_str, vec_str, item_str
1178- ) ,
1179- )
11801188 }
11811189 }
11821190 }
0 commit comments