|
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