@@ -13,6 +13,13 @@ const NOTE_MSG: &str = "this transmute results in undefined behavior";
1313const HELP_MSG : & str =
1414 "try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value" ;
1515
16+ fn lint_expr ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) {
17+ span_lint_and_then ( cx, TRANSMUTE_NULL_TO_FN , expr. span , LINT_MSG , |diag| {
18+ diag. span_label ( expr. span , NOTE_MSG ) ;
19+ diag. help ( HELP_MSG ) ;
20+ } ) ;
21+ }
22+
1623pub ( super ) fn check < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > , arg : & ' tcx Expr < ' _ > , to_ty : Ty < ' tcx > ) -> bool {
1724 if !to_ty. is_fn ( ) {
1825 return false ;
@@ -21,42 +28,34 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
2128 // Catching:
2229 // transmute over constants that resolve to `null`.
2330 let mut const_eval_context = constant_context ( cx, cx. typeck_results ( ) ) ;
24- if let ExprKind :: Path ( ref _qpath) = arg. kind &&
25- let Some ( Constant :: RawPtr ( 0 ) ) = const_eval_context. expr ( arg)
26- {
27- span_lint_and_then ( cx, TRANSMUTE_NULL_TO_FN , expr. span , LINT_MSG , |diag| {
28- diag. span_label ( expr. span , NOTE_MSG ) ;
29- diag. help ( HELP_MSG ) ;
30- } ) ;
31- return true ;
32- }
3331
34- // Catching:
35- // `std::mem::transmute(0 as *const i32)`
36- if let ExprKind :: Cast ( inner_expr, _cast_ty) = arg. kind && is_integer_literal ( inner_expr, 0 ) {
37- span_lint_and_then ( cx, TRANSMUTE_NULL_TO_FN , expr. span , LINT_MSG , |diag| {
38- diag. span_label ( expr. span , NOTE_MSG ) ;
39- diag. help ( HELP_MSG ) ;
40- } ) ;
41- return true ;
42- }
32+ match arg. kind {
33+ ExprKind :: Path ( ref _qpath) if matches ! ( const_eval_context. expr( arg) , Some ( Constant :: RawPtr ( 0 ) ) ) => {
34+ lint_expr ( cx, expr) ;
35+ true
36+ } ,
4337
44- // Catching:
45- // `std::mem::transmute(std::ptr::null::<i32>())`
46- if let ExprKind :: Call ( func1, [ ] ) = arg. kind &&
47- is_path_diagnostic_item ( cx, func1, sym:: ptr_null)
48- {
49- span_lint_and_then ( cx, TRANSMUTE_NULL_TO_FN , expr. span , LINT_MSG , |diag| {
50- diag. span_label ( expr. span , NOTE_MSG ) ;
51- diag. help ( HELP_MSG ) ;
52- } ) ;
53- return true ;
54- }
38+ // Catching:
39+ // `std::mem::transmute(0 as *const i32)`
40+ ExprKind :: Cast ( inner_expr, _cast_ty) if is_integer_literal ( inner_expr, 0 ) => {
41+ lint_expr ( cx, expr) ;
42+ true
43+ } ,
5544
56- // FIXME:
57- // Also catch transmutations of variables which are known nulls.
58- // To do this, MIR const propagation seems to be the better tool.
59- // Whenever MIR const prop routines are more developed, this will
60- // become available. As of this writing (25/03/19) it is not yet.
61- false
45+ // Catching:
46+ // `std::mem::transmute(std::ptr::null::<i32>())`
47+ ExprKind :: Call ( func1, [ ] ) if is_path_diagnostic_item ( cx, func1, sym:: ptr_null) => {
48+ lint_expr ( cx, expr) ;
49+ true
50+ } ,
51+
52+ _ => {
53+ // FIXME:
54+ // Also catch transmutations of variables which are known nulls.
55+ // To do this, MIR const propagation seems to be the better tool.
56+ // Whenever MIR const prop routines are more developed, this will
57+ // become available. As of this writing (25/03/19) it is not yet.
58+ false
59+ } ,
60+ }
6261}
0 commit comments