@@ -13,6 +13,13 @@ const NOTE_MSG: &str = "this transmute results in undefined behavior";
13
13
const HELP_MSG : & str =
14
14
"try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value" ;
15
15
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
+
16
23
pub ( super ) fn check < ' tcx > ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > , arg : & ' tcx Expr < ' _ > , to_ty : Ty < ' tcx > ) -> bool {
17
24
if !to_ty. is_fn ( ) {
18
25
return false ;
@@ -21,42 +28,34 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
21
28
// Catching:
22
29
// transmute over constants that resolve to `null`.
23
30
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
- }
33
31
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
+ } ,
43
37
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
+ } ,
55
44
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
+ }
62
61
}
0 commit comments