@@ -104,99 +104,51 @@ fn is_operation_we_care_about<'tcx>(
104104 deref_assign_or_addr_of ( e) . or_else ( || ptr_write ( cx, e) )
105105}
106106
107- fn is_cast_from_const_to_mut < ' tcx > ( cx : & LateContext < ' tcx > , e : & ' tcx Expr < ' tcx > ) -> bool {
108- let e = e. peel_blocks ( ) ;
107+ fn is_cast_from_const_to_mut < ' tcx > ( cx : & LateContext < ' tcx > , orig_expr : & ' tcx Expr < ' tcx > ) -> bool {
108+ let mut need_check_freeze = false ;
109+ let mut e = orig_expr;
109110
110- fn from_casts < ' tcx > (
111- cx : & LateContext < ' tcx > ,
112- e : & ' tcx Expr < ' tcx > ,
113- need_check_freeze : & mut bool ,
114- ) -> Option < & ' tcx Expr < ' tcx > > {
115- // <expr> as *mut ...
116- let mut e = if let ExprKind :: Cast ( e, t) = e. kind
117- && let ty:: RawPtr ( TypeAndMut { mutbl : Mutability :: Mut , .. } ) = cx. typeck_results ( ) . node_type ( t. hir_id ) . kind ( ) {
118- e
119- // <expr>.cast_mut()
111+ let end_ty = cx. typeck_results ( ) . node_type ( orig_expr. hir_id ) ;
112+
113+ // Bail out early if the end type is **not** a mutable pointer.
114+ if !matches ! ( end_ty. kind( ) , ty:: RawPtr ( TypeAndMut { ty: _, mutbl: Mutability :: Mut } ) ) {
115+ return false ;
116+ }
117+
118+ loop {
119+ e = e. peel_blocks ( ) ;
120+ // <expr> as ...
121+ e = if let ExprKind :: Cast ( expr, _) = e. kind {
122+ expr
123+ // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
120124 } else if let ExprKind :: MethodCall ( _, expr, [ ] , _) = e. kind
121125 && let Some ( def_id) = cx. typeck_results ( ) . type_dependent_def_id ( e. hir_id )
122- && cx. tcx . is_diagnostic_item ( sym:: ptr_cast_mut, def_id) {
126+ && matches ! (
127+ cx. tcx. get_diagnostic_name( def_id) ,
128+ Some ( sym:: ptr_cast | sym:: const_ptr_cast | sym:: ptr_cast_mut | sym:: ptr_cast_const)
129+ )
130+ {
123131 expr
124- // UnsafeCell::raw_get(<expr>)
132+ // ptr::from_ref(<expr>), UnsafeCell::raw_get(<expr>) or mem::transmute<_, _> (<expr>)
125133 } else if let ExprKind :: Call ( path, [ arg] ) = e. kind
126134 && let ExprKind :: Path ( ref qpath) = path. kind
127135 && let Some ( def_id) = cx. qpath_res ( qpath, path. hir_id ) . opt_def_id ( )
128- && cx. tcx . is_diagnostic_item ( sym:: unsafe_cell_raw_get, def_id)
136+ && matches ! (
137+ cx. tcx. get_diagnostic_name( def_id) ,
138+ Some ( sym:: ptr_from_ref | sym:: unsafe_cell_raw_get | sym:: transmute)
139+ )
129140 {
130- * need_check_freeze = true ;
141+ if cx. tcx . is_diagnostic_item ( sym:: unsafe_cell_raw_get, def_id) {
142+ need_check_freeze = true ;
143+ }
131144 arg
132145 } else {
133- return None ;
146+ break ;
134147 } ;
135-
136- let mut had_at_least_one_cast = false ;
137- loop {
138- e = e. peel_blocks ( ) ;
139- // <expr> as *mut/const ... or <expr> as <uint>
140- e = if let ExprKind :: Cast ( expr, t) = e. kind
141- && matches ! ( cx. typeck_results( ) . node_type( t. hir_id) . kind( ) , ty:: RawPtr ( _) | ty:: Uint ( _) ) {
142- had_at_least_one_cast = true ;
143- expr
144- // <expr>.cast(), <expr>.cast_mut() or <expr>.cast_const()
145- } else if let ExprKind :: MethodCall ( _, expr, [ ] , _) = e. kind
146- && let Some ( def_id) = cx. typeck_results ( ) . type_dependent_def_id ( e. hir_id )
147- && matches ! (
148- cx. tcx. get_diagnostic_name( def_id) ,
149- Some ( sym:: ptr_cast | sym:: const_ptr_cast | sym:: ptr_cast_mut | sym:: ptr_cast_const)
150- )
151- {
152- had_at_least_one_cast = true ;
153- expr
154- // ptr::from_ref(<expr>) or UnsafeCell::raw_get(<expr>)
155- } else if let ExprKind :: Call ( path, [ arg] ) = e. kind
156- && let ExprKind :: Path ( ref qpath) = path. kind
157- && let Some ( def_id) = cx. qpath_res ( qpath, path. hir_id ) . opt_def_id ( )
158- && matches ! (
159- cx. tcx. get_diagnostic_name( def_id) ,
160- Some ( sym:: ptr_from_ref | sym:: unsafe_cell_raw_get)
161- )
162- {
163- if cx. tcx . is_diagnostic_item ( sym:: unsafe_cell_raw_get, def_id) {
164- * need_check_freeze = true ;
165- }
166- return Some ( arg) ;
167- } else if had_at_least_one_cast {
168- return Some ( e) ;
169- } else {
170- return None ;
171- } ;
172- }
173148 }
174149
175- fn from_transmute < ' tcx > (
176- cx : & LateContext < ' tcx > ,
177- e : & ' tcx Expr < ' tcx > ,
178- ) -> Option < & ' tcx Expr < ' tcx > > {
179- // mem::transmute::<_, *mut _>(<expr>)
180- if let ExprKind :: Call ( path, [ arg] ) = e. kind
181- && let ExprKind :: Path ( ref qpath) = path. kind
182- && let Some ( def_id) = cx. qpath_res ( qpath, path. hir_id ) . opt_def_id ( )
183- && cx. tcx . is_diagnostic_item ( sym:: transmute, def_id)
184- && let ty:: RawPtr ( TypeAndMut { mutbl : Mutability :: Mut , .. } ) = cx. typeck_results ( ) . node_type ( e. hir_id ) . kind ( ) {
185- Some ( arg)
186- } else {
187- None
188- }
189- }
190-
191- let mut need_check_freeze = false ;
192- let Some ( e) = from_casts ( cx, e, & mut need_check_freeze) . or_else ( || from_transmute ( cx, e) )
193- else {
194- return false ;
195- } ;
196-
197- let e = e. peel_blocks ( ) ;
198- let node_type = cx. typeck_results ( ) . node_type ( e. hir_id ) ;
199- if let ty:: Ref ( _, inner_ty, Mutability :: Not ) = node_type. kind ( ) {
150+ let start_ty = cx. typeck_results ( ) . node_type ( e. hir_id ) ;
151+ if let ty:: Ref ( _, inner_ty, Mutability :: Not ) = start_ty. kind ( ) {
200152 // If an UnsafeCell method is involved we need to additionaly check the
201153 // inner type for the presence of the Freeze trait (ie does NOT contain
202154 // an UnsafeCell), since in that case we would incorrectly lint on valid casts.
0 commit comments