Skip to content

Commit 7f4599a

Browse files
committed
Auto merge of rust-lang#6557 - rail-rain:extending_cast_ptr_alignment, r=phansch
Catch `pointer::cast` too in `cast_ptr_alignment` Fixes rust-lang#4708 Although there were some discussion in the issue, this PR implements the original feature. I think `cast_ptr_alignment` should exist as it is, separated from `ptr_as_ptr`. --- changelog: Extend `cast_ptr_alignment` lint for the `pointer::cast` method
2 parents 1eed27f + 53f8731 commit 7f4599a

File tree

4 files changed

+52
-13
lines changed

4 files changed

+52
-13
lines changed

clippy_lints/src/types.rs

+23-12
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use if_chain::if_chain;
88
use rustc_ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy};
99
use rustc_errors::{Applicability, DiagnosticBuilder};
1010
use rustc_hir as hir;
11-
use rustc_hir::def::Res;
1211
use rustc_hir::intravisit::{walk_body, walk_expr, walk_ty, FnKind, NestedVisitorMap, Visitor};
1312
use rustc_hir::{
1413
BinOpKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, GenericBounds, GenericParamKind, HirId,
@@ -33,9 +32,9 @@ use crate::consts::{constant, Constant};
3332
use crate::utils::paths;
3433
use crate::utils::sugg::Sugg;
3534
use crate::utils::{
36-
clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_type_diagnostic_item,
37-
last_path_segment, match_def_path, match_path, meets_msrv, method_chain_args, multispan_sugg,
38-
numeric_literal::NumericLiteral, qpath_res, reindent_multiline, sext, snippet, snippet_opt,
35+
clip, comparisons, differing_macro_contexts, higher, in_constant, indent_of, int_bits, is_hir_ty_cfg_dependant,
36+
is_type_diagnostic_item, last_path_segment, match_def_path, match_path, meets_msrv, method_chain_args,
37+
multispan_sugg, numeric_literal::NumericLiteral, qpath_res, reindent_multiline, sext, snippet, snippet_opt,
3938
snippet_with_applicability, snippet_with_macro_callsite, span_lint, span_lint_and_help, span_lint_and_sugg,
4039
span_lint_and_then, unsext,
4140
};
@@ -1282,8 +1281,8 @@ declare_clippy_lint! {
12821281
}
12831282

12841283
declare_clippy_lint! {
1285-
/// **What it does:** Checks for casts from a less-strictly-aligned pointer to a
1286-
/// more-strictly-aligned pointer
1284+
/// **What it does:** Checks for casts, using `as` or `pointer::cast`,
1285+
/// from a less-strictly-aligned pointer to a more-strictly-aligned pointer
12871286
///
12881287
/// **Why is this bad?** Dereferencing the resulting pointer may be undefined
12891288
/// behavior.
@@ -1296,6 +1295,9 @@ declare_clippy_lint! {
12961295
/// ```rust
12971296
/// let _ = (&1u8 as *const u8) as *const u16;
12981297
/// let _ = (&mut 1u8 as *mut u8) as *mut u16;
1298+
///
1299+
/// (&1u8 as *const u8).cast::<u16>();
1300+
/// (&mut 1u8 as *mut u8).cast::<u16>();
12991301
/// ```
13001302
pub CAST_PTR_ALIGNMENT,
13011303
pedantic,
@@ -1637,12 +1639,8 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
16371639
return;
16381640
}
16391641
if let ExprKind::Cast(ref ex, cast_to) = expr.kind {
1640-
if let TyKind::Path(QPath::Resolved(_, path)) = cast_to.kind {
1641-
if let Res::Def(_, def_id) = path.res {
1642-
if cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr) {
1643-
return;
1644-
}
1645-
}
1642+
if is_hir_ty_cfg_dependant(cx, cast_to) {
1643+
return;
16461644
}
16471645
let (cast_from, cast_to) = (cx.typeck_results().expr_ty(ex), cx.typeck_results().expr_ty(expr));
16481646
lint_fn_to_numeric_cast(cx, expr, ex, cast_from, cast_to);
@@ -1692,6 +1690,19 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
16921690
}
16931691

16941692
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
1693+
} else if let ExprKind::MethodCall(method_path, _, args, _) = expr.kind {
1694+
if_chain! {
1695+
if method_path.ident.name == sym!(cast);
1696+
if let Some(generic_args) = method_path.args;
1697+
if let [GenericArg::Type(cast_to)] = generic_args.args;
1698+
// There probably is no obvious reason to do this, just to be consistent with `as` cases.
1699+
if !is_hir_ty_cfg_dependant(cx, cast_to);
1700+
then {
1701+
let (cast_from, cast_to) =
1702+
(cx.typeck_results().expr_ty(&args[0]), cx.typeck_results().expr_ty(expr));
1703+
lint_cast_ptr_alignment(cx, expr, cast_from, cast_to);
1704+
}
1705+
}
16951706
}
16961707
}
16971708
}

clippy_lints/src/utils/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1686,6 +1686,18 @@ macro_rules! unwrap_cargo_metadata {
16861686
}};
16871687
}
16881688

1689+
pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
1690+
if_chain! {
1691+
if let TyKind::Path(QPath::Resolved(_, path)) = ty.kind;
1692+
if let Res::Def(_, def_id) = path.res;
1693+
then {
1694+
cx.tcx.has_attr(def_id, sym::cfg) || cx.tcx.has_attr(def_id, sym::cfg_attr)
1695+
} else {
1696+
false
1697+
}
1698+
}
1699+
}
1700+
16891701
#[cfg(test)]
16901702
mod test {
16911703
use super::{reindent_multiline, without_block_comments};

tests/ui/cast_alignment.rs

+4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ fn main() {
1212
(&1u8 as *const u8) as *const u16;
1313
(&mut 1u8 as *mut u8) as *mut u16;
1414

15+
// cast to more-strictly-aligned type, but with the `pointer::cast` function.
16+
(&1u8 as *const u8).cast::<u16>();
17+
(&mut 1u8 as *mut u8).cast::<u16>();
18+
1519
/* These should be ok */
1620

1721
// not a pointer type

tests/ui/cast_alignment.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,17 @@ error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1
1212
LL | (&mut 1u8 as *mut u8) as *mut u16;
1313
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1414

15-
error: aborting due to 2 previous errors
15+
error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes)
16+
--> $DIR/cast_alignment.rs:16:5
17+
|
18+
LL | (&1u8 as *const u8).cast::<u16>();
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes)
22+
--> $DIR/cast_alignment.rs:17:5
23+
|
24+
LL | (&mut 1u8 as *mut u8).cast::<u16>();
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26+
27+
error: aborting due to 4 previous errors
1628

0 commit comments

Comments
 (0)