@@ -826,7 +826,7 @@ struct FixedOffsetVar<'hir> {
826826}
827827
828828fn is_slice_like < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' _ > ) -> bool {
829- let is_slice = match ty. kind {
829+ let is_slice = match ty. kind ( ) {
830830 ty:: Ref ( _, subty, _) => is_slice_like ( cx, subty) ,
831831 ty:: Slice ( ..) | ty:: Array ( ..) => true ,
832832 _ => false ,
@@ -1003,7 +1003,7 @@ fn detect_manual_memcpy<'tcx>(
10031003 start : Some ( start) ,
10041004 end : Some ( end) ,
10051005 limits,
1006- } ) = higher:: range ( cx , arg)
1006+ } ) = higher:: range ( arg)
10071007 {
10081008 // the var must be a single name
10091009 if let PatKind :: Binding ( _, canonical_id, _, _) = pat. kind {
@@ -1140,23 +1140,95 @@ 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 mutated_variables ( pushed_item, cx) . map_or ( false , |mutvars| mutvars. is_empty ( ) ) {
1143+ let vec_ty = cx. typeck_results ( ) . expr_ty ( vec) ;
1144+ let ty = vec_ty. walk ( ) . nth ( 1 ) . unwrap ( ) . expect_ty ( ) ;
1145+ if cx
1146+ . tcx
1147+ . lang_items ( )
1148+ . clone_trait ( )
1149+ . map_or ( false , |id| implements_trait ( cx, ty, id, & [ ] ) )
1150+ {
1151+ // Make sure that the push does not involve possibly mutating values
11451152 if let PatKind :: Wild = pat. kind {
11461153 let vec_str = snippet_with_macro_callsite ( cx, vec. span , "" ) ;
11471154 let item_str = snippet_with_macro_callsite ( cx, pushed_item. span , "" ) ;
1148-
1149- span_lint_and_help (
1150- cx,
1151- SAME_ITEM_PUSH ,
1152- vec. span ,
1153- "it looks like the same item is being pushed into this Vec" ,
1154- None ,
1155- & format ! (
1156- "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1157- item_str, vec_str, item_str
1158- ) ,
1159- )
1155+ if let ExprKind :: Path ( ref qpath) = pushed_item. kind {
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+ _ => { } ,
1217+ }
1218+ } else if let ExprKind :: Lit ( ..) = pushed_item. kind {
1219+ // literal
1220+ span_lint_and_help (
1221+ cx,
1222+ SAME_ITEM_PUSH ,
1223+ vec. span ,
1224+ "it looks like the same item is being pushed into this Vec" ,
1225+ None ,
1226+ & format ! (
1227+ "try using vec![{};SIZE] or {}.resize(NEW_SIZE, {})" ,
1228+ item_str, vec_str, item_str
1229+ ) ,
1230+ )
1231+ }
11601232 }
11611233 }
11621234 }
@@ -1177,7 +1249,7 @@ fn check_for_loop_range<'tcx>(
11771249 start : Some ( start) ,
11781250 ref end,
11791251 limits,
1180- } ) = higher:: range ( cx , arg)
1252+ } ) = higher:: range ( arg)
11811253 {
11821254 // the var must be a single name
11831255 if let PatKind :: Binding ( _, canonical_id, ident, _) = pat. kind {
@@ -1355,7 +1427,7 @@ fn is_end_eq_array_len<'tcx>(
13551427 if_chain ! {
13561428 if let ExprKind :: Lit ( ref lit) = end. kind;
13571429 if let ast:: LitKind :: Int ( end_int, _) = lit. node;
1358- if let ty:: Array ( _, arr_len_const) = indexed_ty. kind;
1430+ if let ty:: Array ( _, arr_len_const) = indexed_ty. kind( ) ;
13591431 if let Some ( arr_len) = arr_len_const. try_eval_usize( cx. tcx, cx. param_env) ;
13601432 then {
13611433 return match limits {
@@ -1592,7 +1664,7 @@ fn check_for_loop_over_map_kv<'tcx>(
15921664 if let PatKind :: Tuple ( ref pat, _) = pat. kind {
15931665 if pat. len ( ) == 2 {
15941666 let arg_span = arg. span ;
1595- let ( new_pat_span, kind, ty, mutbl) = match cx. typeck_results ( ) . expr_ty ( arg) . kind {
1667+ let ( new_pat_span, kind, ty, mutbl) = match * cx. typeck_results ( ) . expr_ty ( arg) . kind ( ) {
15961668 ty:: Ref ( _, ty, mutbl) => match ( & pat[ 0 ] . kind , & pat[ 1 ] . kind ) {
15971669 ( key, _) if pat_is_wild ( key, body) => ( pat[ 1 ] . span , "value" , ty, mutbl) ,
15981670 ( _, value) if pat_is_wild ( value, body) => ( pat[ 0 ] . span , "key" , ty, Mutability :: Not ) ,
@@ -1679,7 +1751,7 @@ fn check_for_mut_range_bound(cx: &LateContext<'_>, arg: &Expr<'_>, body: &Expr<'
16791751 start : Some ( start) ,
16801752 end : Some ( end) ,
16811753 ..
1682- } ) = higher:: range ( cx , arg)
1754+ } ) = higher:: range ( arg)
16831755 {
16841756 let mut_ids = vec ! [ check_for_mutability( cx, start) , check_for_mutability( cx, end) ] ;
16851757 if mut_ids[ 0 ] . is_some ( ) || mut_ids[ 1 ] . is_some ( ) {
@@ -1920,7 +1992,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
19201992 for expr in args {
19211993 let ty = self . cx . typeck_results ( ) . expr_ty_adjusted ( expr) ;
19221994 self . prefer_mutable = false ;
1923- if let ty:: Ref ( _, _, mutbl) = ty. kind {
1995+ if let ty:: Ref ( _, _, mutbl) = * ty. kind ( ) {
19241996 if mutbl == Mutability :: Mut {
19251997 self . prefer_mutable = true ;
19261998 }
@@ -1932,7 +2004,7 @@ impl<'a, 'tcx> Visitor<'tcx> for VarVisitor<'a, 'tcx> {
19322004 let def_id = self . cx . typeck_results ( ) . type_dependent_def_id ( expr. hir_id ) . unwrap ( ) ;
19332005 for ( ty, expr) in self . cx . tcx . fn_sig ( def_id) . inputs ( ) . skip_binder ( ) . iter ( ) . zip ( args) {
19342006 self . prefer_mutable = false ;
1935- if let ty:: Ref ( _, _, mutbl) = ty. kind {
2007+ if let ty:: Ref ( _, _, mutbl) = * ty. kind ( ) {
19362008 if mutbl == Mutability :: Mut {
19372009 self . prefer_mutable = true ;
19382010 }
@@ -2030,7 +2102,7 @@ fn is_ref_iterable_type(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
20302102
20312103fn is_iterable_array < ' tcx > ( ty : Ty < ' tcx > , cx : & LateContext < ' tcx > ) -> bool {
20322104 // IntoIterator is currently only implemented for array sizes <= 32 in rustc
2033- match ty. kind {
2105+ match ty. kind ( ) {
20342106 ty:: Array ( _, n) => n
20352107 . try_eval_usize ( cx. tcx , cx. param_env )
20362108 . map_or ( false , |val| ( 0 ..=32 ) . contains ( & val) ) ,
0 commit comments