|
1 | 1 | use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method, walk_ptrs_ty}; |
2 | | -use rustc::ty::{Adt, Dynamic, Opaque, Param, RawPtr, Ref, Ty, TypeAndMut}; |
| 2 | +use rustc::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut}; |
3 | 3 | use rustc_hir as hir; |
4 | 4 | use rustc_lint::{LateContext, LateLintPass}; |
5 | 5 | use rustc_session::{declare_lint_pass, declare_tool_lint}; |
@@ -101,21 +101,24 @@ fn check_ty<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, span: Span, ty: Ty<'tcx>) { |
101 | 101 | if [&paths::HASHMAP, &paths::BTREEMAP, &paths::HASHSET, &paths::BTREESET] |
102 | 102 | .iter() |
103 | 103 | .any(|path| match_def_path(cx, def.did, &**path)) |
| 104 | + && is_mutable_type(cx, substs.type_at(0), span) |
104 | 105 | { |
105 | | - let key_type = concrete_type(substs.type_at(0)); |
106 | | - if let Some(key_type) = key_type { |
107 | | - if !key_type.is_freeze(cx.tcx, cx.param_env, span) { |
108 | | - span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type"); |
109 | | - } |
110 | | - } |
| 106 | + span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type"); |
111 | 107 | } |
112 | 108 | } |
113 | 109 | } |
114 | 110 |
|
115 | | -fn concrete_type(ty: Ty<'_>) -> Option<Ty<'_>> { |
| 111 | +fn is_mutable_type<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>, span: Span) -> bool { |
116 | 112 | match ty.kind { |
117 | | - RawPtr(TypeAndMut { ty: inner_ty, .. }) | Ref(_, inner_ty, _) => concrete_type(inner_ty), |
118 | | - Dynamic(..) | Opaque(..) | Param(..) => None, |
119 | | - _ => Some(ty), |
| 113 | + RawPtr(TypeAndMut { ty: inner_ty, mutbl }) | Ref(_, inner_ty, mutbl) => { |
| 114 | + mutbl == hir::Mutability::Mut || is_mutable_type(cx, inner_ty, span) |
| 115 | + }, |
| 116 | + Slice(inner_ty) => is_mutable_type(cx, inner_ty, span), |
| 117 | + Array(inner_ty, size) => { |
| 118 | + size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_mutable_type(cx, inner_ty, span) |
| 119 | + }, |
| 120 | + Tuple(..) => ty.tuple_fields().any(|ty| is_mutable_type(cx, ty, span)), |
| 121 | + Adt(..) => cx.tcx.layout_of(cx.param_env.and(ty)).is_ok() && !ty.is_freeze(cx.tcx, cx.param_env, span), |
| 122 | + _ => false, |
120 | 123 | } |
121 | 124 | } |
0 commit comments