Improve code style further
This commit is contained in:
parent
9b2fc8e2a2
commit
20f501a9d9
@ -55,19 +55,14 @@ fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
|||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
|
impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
// Catching:
|
match expr.kind {
|
||||||
// (fn_ptr as *<const/mut> <ty>).is_null()
|
ExprKind::MethodCall(method_name, receiver, _, _)
|
||||||
if let ExprKind::MethodCall(method_name, receiver, _, _) = expr.kind
|
if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) =>
|
||||||
&& method_name.ident.as_str() == "is_null"
|
|
||||||
&& is_fn_ptr_cast(cx, receiver)
|
|
||||||
{
|
{
|
||||||
lint_expr(cx, expr);
|
lint_expr(cx, expr);
|
||||||
return;
|
},
|
||||||
}
|
|
||||||
|
|
||||||
if let ExprKind::Binary(op, left, right) = expr.kind
|
ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
|
||||||
&& let BinOpKind::Eq = op.node
|
|
||||||
{
|
|
||||||
let to_check: &Expr<'_>;
|
let to_check: &Expr<'_>;
|
||||||
if is_fn_ptr_cast(cx, left) {
|
if is_fn_ptr_cast(cx, left) {
|
||||||
to_check = right;
|
to_check = right;
|
||||||
@ -77,28 +72,33 @@ impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Catching:
|
match to_check.kind {
|
||||||
// (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
|
|
||||||
let c = constant(cx, cx.typeck_results(), to_check);
|
|
||||||
if let Some((Constant::RawPtr(0), _)) = c {
|
|
||||||
lint_expr(cx, expr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catching:
|
// Catching:
|
||||||
// (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
|
// (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
|
||||||
if let ExprKind::Cast(cast_expr, _) = to_check.kind && is_integer_literal(cast_expr, 0) {
|
ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => {
|
||||||
lint_expr(cx, expr);
|
lint_expr(cx, expr);
|
||||||
return;
|
},
|
||||||
}
|
|
||||||
|
|
||||||
// Catching:
|
// Catching:
|
||||||
// (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
|
// (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
|
||||||
if let ExprKind::Call(func, []) = to_check.kind &&
|
ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => {
|
||||||
is_path_diagnostic_item(cx, func, sym::ptr_null)
|
lint_expr(cx, expr);
|
||||||
|
},
|
||||||
|
|
||||||
|
// Catching:
|
||||||
|
// (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
|
||||||
|
_ if matches!(
|
||||||
|
constant(cx, cx.typeck_results(), to_check),
|
||||||
|
Some((Constant::RawPtr(0), _))
|
||||||
|
) =>
|
||||||
{
|
{
|
||||||
lint_expr(cx, expr);
|
lint_expr(cx, expr);
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,13 @@ const NOTE_MSG: &str = "this transmute results in undefined behavior";
|
|||||||
const HELP_MSG: &str =
|
const HELP_MSG: &str =
|
||||||
"try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value";
|
"try wrapping your function pointer type in `Option<T>` instead, and using `None` as a null pointer value";
|
||||||
|
|
||||||
|
fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||||
|
span_lint_and_then(cx, TRANSMUTE_NULL_TO_FN, expr.span, LINT_MSG, |diag| {
|
||||||
|
diag.span_label(expr.span, NOTE_MSG);
|
||||||
|
diag.help(HELP_MSG);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'tcx Expr<'_>, to_ty: Ty<'tcx>) -> bool {
|
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'tcx Expr<'_>, to_ty: Ty<'tcx>) -> bool {
|
||||||
if !to_ty.is_fn() {
|
if !to_ty.is_fn() {
|
||||||
return false;
|
return false;
|
||||||
@ -21,42 +28,34 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arg: &'t
|
|||||||
// Catching:
|
// Catching:
|
||||||
// transmute over constants that resolve to `null`.
|
// transmute over constants that resolve to `null`.
|
||||||
let mut const_eval_context = constant_context(cx, cx.typeck_results());
|
let mut const_eval_context = constant_context(cx, cx.typeck_results());
|
||||||
if let ExprKind::Path(ref _qpath) = arg.kind &&
|
|
||||||
let Some(Constant::RawPtr(0)) = const_eval_context.expr(arg)
|
match arg.kind {
|
||||||
{
|
ExprKind::Path(ref _qpath) if matches!(const_eval_context.expr(arg), Some(Constant::RawPtr(0))) => {
|
||||||
span_lint_and_then(cx, TRANSMUTE_NULL_TO_FN, expr.span, LINT_MSG, |diag| {
|
lint_expr(cx, expr);
|
||||||
diag.span_label(expr.span, NOTE_MSG);
|
true
|
||||||
diag.help(HELP_MSG);
|
},
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catching:
|
// Catching:
|
||||||
// `std::mem::transmute(0 as *const i32)`
|
// `std::mem::transmute(0 as *const i32)`
|
||||||
if let ExprKind::Cast(inner_expr, _cast_ty) = arg.kind && is_integer_literal(inner_expr, 0) {
|
ExprKind::Cast(inner_expr, _cast_ty) if is_integer_literal(inner_expr, 0) => {
|
||||||
span_lint_and_then(cx, TRANSMUTE_NULL_TO_FN, expr.span, LINT_MSG, |diag| {
|
lint_expr(cx, expr);
|
||||||
diag.span_label(expr.span, NOTE_MSG);
|
true
|
||||||
diag.help(HELP_MSG);
|
},
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catching:
|
// Catching:
|
||||||
// `std::mem::transmute(std::ptr::null::<i32>())`
|
// `std::mem::transmute(std::ptr::null::<i32>())`
|
||||||
if let ExprKind::Call(func1, []) = arg.kind &&
|
ExprKind::Call(func1, []) if is_path_diagnostic_item(cx, func1, sym::ptr_null) => {
|
||||||
is_path_diagnostic_item(cx, func1, sym::ptr_null)
|
lint_expr(cx, expr);
|
||||||
{
|
true
|
||||||
span_lint_and_then(cx, TRANSMUTE_NULL_TO_FN, expr.span, LINT_MSG, |diag| {
|
},
|
||||||
diag.span_label(expr.span, NOTE_MSG);
|
|
||||||
diag.help(HELP_MSG);
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
_ => {
|
||||||
// FIXME:
|
// FIXME:
|
||||||
// Also catch transmutations of variables which are known nulls.
|
// Also catch transmutations of variables which are known nulls.
|
||||||
// To do this, MIR const propagation seems to be the better tool.
|
// To do this, MIR const propagation seems to be the better tool.
|
||||||
// Whenever MIR const prop routines are more developed, this will
|
// Whenever MIR const prop routines are more developed, this will
|
||||||
// become available. As of this writing (25/03/19) it is not yet.
|
// become available. As of this writing (25/03/19) it is not yet.
|
||||||
false
|
false
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user