@@ -103,26 +103,39 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::
103103fn check_ty < ' tcx > ( cx : & LateContext < ' tcx > , span : Span , ty : Ty < ' tcx > ) {
104104 let ty = ty. peel_refs ( ) ;
105105 if let Adt ( def, substs) = ty. kind ( ) {
106- if [ sym:: hashmap_type, sym:: BTreeMap , sym:: hashset_type, sym:: BTreeMap ]
106+ let is_map_type = [ sym:: hashmap_type, sym:: BTreeMap , sym:: hashset_type, sym:: BTreeMap ]
107107 . iter ( )
108- . any ( |diag_item| cx. tcx . is_diagnostic_item ( * diag_item, def. did ) )
109- && is_mutable_type ( cx, substs. type_at ( 0 ) , span)
110- {
108+ . any ( |diag_item| cx. tcx . is_diagnostic_item ( * diag_item, def. did ) ) ;
109+ if is_map_type && is_mutable_type ( cx, substs. type_at ( 0 ) , span, true ) {
111110 span_lint ( cx, MUTABLE_KEY_TYPE , span, "mutable key type" ) ;
112111 }
113112 }
114113}
115114
116- fn is_mutable_type < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > , span : Span ) -> bool {
115+ fn is_mutable_type < ' tcx > ( cx : & LateContext < ' tcx > , ty : Ty < ' tcx > , span : Span , is_top_level_type : bool ) -> bool {
117116 match * ty. kind ( ) {
118- RawPtr ( TypeAndMut { ty : inner_ty, mutbl } ) | Ref ( _, inner_ty, mutbl) => {
119- mutbl == hir:: Mutability :: Mut || is_mutable_type ( cx, inner_ty, span)
117+ RawPtr ( TypeAndMut { ty : inner_ty, mutbl } ) => {
118+ if is_top_level_type {
119+ // Raw pointers are hashed by the address they point to, not what is pointed to.
120+ // Therefore, using a raw pointer to any type as the top-level key type is OK.
121+ // Using raw pointers _in_ the key type is not, because the wrapper type could
122+ // provide a custom `impl` for `Hash` (which could deref the raw pointer).
123+ //
124+ // see:
125+ // - clippy issue: https://github.com/rust-lang/rust-clippy/issues/6745
126+ // - std code: https://github.com/rust-lang/rust/blob/1.54.0/library/core/src/hash/mod.rs#L717-L736
127+ false
128+ } else {
129+ mutbl == hir:: Mutability :: Mut || is_mutable_type ( cx, inner_ty, span, false )
130+ }
120131 } ,
121- Slice ( inner_ty) => is_mutable_type ( cx, inner_ty, span) ,
132+ Ref ( _, inner_ty, mutbl) => mutbl == hir:: Mutability :: Mut || is_mutable_type ( cx, inner_ty, span, false ) ,
133+ Slice ( inner_ty) => is_mutable_type ( cx, inner_ty, span, false ) ,
122134 Array ( inner_ty, size) => {
123- size. try_eval_usize ( cx. tcx , cx. param_env ) . map_or ( true , |u| u != 0 ) && is_mutable_type ( cx, inner_ty, span)
135+ size. try_eval_usize ( cx. tcx , cx. param_env ) . map_or ( true , |u| u != 0 )
136+ && is_mutable_type ( cx, inner_ty, span, false )
124137 } ,
125- Tuple ( ..) => ty. tuple_fields ( ) . any ( |ty| is_mutable_type ( cx, ty, span) ) ,
138+ Tuple ( ..) => ty. tuple_fields ( ) . any ( |ty| is_mutable_type ( cx, ty, span, false ) ) ,
126139 Adt ( ..) => {
127140 !ty. has_escaping_bound_vars ( )
128141 && cx. tcx . layout_of ( cx. param_env . and ( ty) ) . is_ok ( )
0 commit comments