about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md1
-rw-r--r--clippy_lints/src/lib.rs5
-rw-r--r--clippy_lints/src/size_of_in_element_count.rs146
-rw-r--r--clippy_lints/src/utils/paths.rs10
-rw-r--r--tests/ui/size_of_in_element_count.rs61
-rw-r--r--tests/ui/size_of_in_element_count.stderr195
6 files changed, 418 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e65e7cc639f..c7e02aaf4e1 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2057,6 +2057,7 @@ Released 2018-09-13
 [`single_element_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_element_loop
 [`single_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match
 [`single_match_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#single_match_else
+[`size_of_in_element_count`]: https://rust-lang.github.io/rust-clippy/master/index.html#size_of_in_element_count
 [`skip_while_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#skip_while_next
 [`slow_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#slow_vector_initialization
 [`stable_sort_primitive`]: https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 167e5b6b87f..4ef595bcffd 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -306,6 +306,7 @@ mod self_assignment;
 mod serde_api;
 mod shadow;
 mod single_component_path_imports;
+mod size_of_in_element_count;
 mod slow_vector_initialization;
 mod stable_sort_primitive;
 mod strings;
@@ -847,6 +848,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         &shadow::SHADOW_SAME,
         &shadow::SHADOW_UNRELATED,
         &single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS,
+        &size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
         &slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
         &stable_sort_primitive::STABLE_SORT_PRIMITIVE,
         &strings::STRING_ADD,
@@ -998,6 +1000,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
     store.register_late_pass(move || box matches::Matches::new(msrv));
     store.register_early_pass(move || box manual_non_exhaustive::ManualNonExhaustive::new(msrv));
     store.register_late_pass(move || box manual_strip::ManualStrip::new(msrv));
+    store.register_late_pass(|| box size_of_in_element_count::SizeOfInElementCount);
     store.register_late_pass(|| box map_clone::MapClone);
     store.register_late_pass(|| box map_err_ignore::MapErrIgnore);
     store.register_late_pass(|| box shadow::Shadow);
@@ -1559,6 +1562,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&self_assignment::SELF_ASSIGNMENT),
         LintId::of(&serde_api::SERDE_API_MISUSE),
         LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
+        LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
         LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
         LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE),
         LintId::of(&strings::STRING_FROM_UTF8_AS_BYTES),
@@ -1868,6 +1872,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
         LintId::of(&regex::INVALID_REGEX),
         LintId::of(&self_assignment::SELF_ASSIGNMENT),
         LintId::of(&serde_api::SERDE_API_MISUSE),
+        LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
         LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
         LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
         LintId::of(&swap::ALMOST_SWAPPED),
diff --git a/clippy_lints/src/size_of_in_element_count.rs b/clippy_lints/src/size_of_in_element_count.rs
new file mode 100644
index 00000000000..210cf5773e1
--- /dev/null
+++ b/clippy_lints/src/size_of_in_element_count.rs
@@ -0,0 +1,146 @@
+//! Lint on use of `size_of` or `size_of_val` of T in an expression
+//! expecting a count of T
+
+use crate::utils::{match_def_path, paths, span_lint_and_help};
+use if_chain::if_chain;
+use rustc_hir::BinOpKind;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_middle::ty::{self, Ty, TyS, TypeAndMut};
+use rustc_session::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// **What it does:** Detects expressions where
+    /// size_of::<T> or size_of_val::<T> is used as a
+    /// count of elements of type T
+    ///
+    /// **Why is this bad?** These functions expect a count
+    /// of T and not a number of bytes
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust,no_run
+    /// # use std::ptr::copy_nonoverlapping;
+    /// # use std::mem::size_of;
+    ///
+    /// const SIZE: usize = 128;
+    /// let x = [2u8; SIZE];
+    /// let mut y = [2u8; SIZE];
+    /// unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+    /// ```
+    pub SIZE_OF_IN_ELEMENT_COUNT,
+    correctness,
+    "using size_of::<T> or size_of_val::<T> where a count of elements of T is expected"
+}
+
+declare_lint_pass!(SizeOfInElementCount => [SIZE_OF_IN_ELEMENT_COUNT]);
+
+fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Ty<'tcx>> {
+    match expr.kind {
+        ExprKind::Call(count_func, _func_args) => {
+            if_chain! {
+                if let ExprKind::Path(ref count_func_qpath) = count_func.kind;
+                if let Some(def_id) = cx.qpath_res(count_func_qpath, count_func.hir_id).opt_def_id();
+                if match_def_path(cx, def_id, &paths::MEM_SIZE_OF)
+                    || match_def_path(cx, def_id, &paths::MEM_SIZE_OF_VAL);
+                then {
+                    cx.typeck_results().node_substs(count_func.hir_id).types().next()
+                } else {
+                    None
+                }
+            }
+        },
+        ExprKind::Binary(op, left, right) if BinOpKind::Mul == op.node || BinOpKind::Div == op.node => {
+            get_size_of_ty(cx, left).or_else(|| get_size_of_ty(cx, right))
+        },
+        ExprKind::Cast(expr, _) => get_size_of_ty(cx, expr),
+        _ => None,
+    }
+}
+
+fn get_pointee_ty_and_count_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> {
+    const FUNCTIONS: [&[&str]; 8] = [
+        &paths::COPY_NONOVERLAPPING,
+        &paths::COPY,
+        &paths::WRITE_BYTES,
+        &paths::PTR_SWAP_NONOVERLAPPING,
+        &paths::PTR_SLICE_FROM_RAW_PARTS,
+        &paths::PTR_SLICE_FROM_RAW_PARTS_MUT,
+        &paths::SLICE_FROM_RAW_PARTS,
+        &paths::SLICE_FROM_RAW_PARTS_MUT,
+    ];
+    const METHODS: [&str; 11] = [
+        "write_bytes",
+        "copy_to",
+        "copy_from",
+        "copy_to_nonoverlapping",
+        "copy_from_nonoverlapping",
+        "add",
+        "wrapping_add",
+        "sub",
+        "wrapping_sub",
+        "offset",
+        "wrapping_offset",
+    ];
+
+    if_chain! {
+        // Find calls to ptr::{copy, copy_nonoverlapping}
+        // and ptr::{swap_nonoverlapping, write_bytes},
+        if let ExprKind::Call(func, [.., count]) = expr.kind;
+        if let ExprKind::Path(ref func_qpath) = func.kind;
+        if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
+        if FUNCTIONS.iter().any(|func_path| match_def_path(cx, def_id, func_path));
+
+        // Get the pointee type
+        if let Some(pointee_ty) = cx.typeck_results().node_substs(func.hir_id).types().next();
+        then {
+            return Some((pointee_ty, count));
+        }
+    };
+    if_chain! {
+        // Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
+        if let ExprKind::MethodCall(method_path, _, [ptr_self, .., count], _) = expr.kind;
+        let method_ident = method_path.ident.as_str();
+        if METHODS.iter().any(|m| *m == &*method_ident);
+
+        // Get the pointee type
+        if let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) =
+            cx.typeck_results().expr_ty(ptr_self).kind();
+        then {
+            return Some((pointee_ty, count));
+        }
+    };
+    None
+}
+
+impl<'tcx> LateLintPass<'tcx> for SizeOfInElementCount {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        const HELP_MSG: &str = "use a count of elements instead of a count of bytes\
+            , it already gets multiplied by the size of the type";
+
+        const LINT_MSG: &str = "found a count of bytes \
+             instead of a count of elements of T";
+
+        if_chain! {
+            // Find calls to functions with an element count parameter and get
+            // the pointee type and count parameter expression
+            if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr);
+
+            // Find a size_of call in the count parameter expression and
+            // check that it's the same type
+            if let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr);
+            if TyS::same_type(pointee_ty, ty_used_for_size_of);
+            then {
+                span_lint_and_help(
+                    cx,
+                    SIZE_OF_IN_ELEMENT_COUNT,
+                    count_expr.span,
+                    LINT_MSG,
+                    None,
+                    HELP_MSG
+                );
+            }
+        };
+    }
+}
diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs
index 16e6a016c9e..6fdc7b4587f 100644
--- a/clippy_lints/src/utils/paths.rs
+++ b/clippy_lints/src/utils/paths.rs
@@ -20,6 +20,8 @@ pub const CLONE_TRAIT: [&str; 3] = ["core", "clone", "Clone"];
 pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
 pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"];
 pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"];
+pub const COPY: [&str; 3] = ["core", "intrinsics", "copy_nonoverlapping"];
+pub const COPY_NONOVERLAPPING: [&str; 3] = ["core", "intrinsics", "copy"];
 pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
 pub const CSTRING_AS_C_STR: [&str; 5] = ["std", "ffi", "c_str", "CString", "as_c_str"];
 pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
@@ -73,6 +75,8 @@ pub const MEM_MANUALLY_DROP: [&str; 4] = ["core", "mem", "manually_drop", "Manua
 pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"];
 pub const MEM_MAYBEUNINIT_UNINIT: [&str; 5] = ["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"];
 pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"];
+pub const MEM_SIZE_OF: [&str; 3] = ["core", "mem", "size_of"];
+pub const MEM_SIZE_OF_VAL: [&str; 3] = ["core", "mem", "size_of_val"];
 pub const MUTEX_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"];
 pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"];
 pub const OPS_MODULE: [&str; 2] = ["core", "ops"];
@@ -100,6 +104,9 @@ pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"];
 pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"];
 pub const PTR_NULL: [&str; 3] = ["core", "ptr", "null"];
 pub const PTR_NULL_MUT: [&str; 3] = ["core", "ptr", "null_mut"];
+pub const PTR_SLICE_FROM_RAW_PARTS: [&str; 3] = ["core", "ptr", "slice_from_raw_parts"];
+pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_raw_parts_mut"];
+pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"];
 pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
 pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"];
 pub const RC: [&str; 3] = ["alloc", "rc", "Rc"];
@@ -121,6 +128,8 @@ pub const RWLOCK_READ_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockReadGu
 pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"];
 pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
+pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
+pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"];
 pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
 pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"];
 pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];
@@ -154,3 +163,4 @@ pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
 pub const VEC_RESIZE: [&str; 4] = ["alloc", "vec", "Vec", "resize"];
 pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"];
 pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"];
+pub const WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"];
diff --git a/tests/ui/size_of_in_element_count.rs b/tests/ui/size_of_in_element_count.rs
new file mode 100644
index 00000000000..b13e390705a
--- /dev/null
+++ b/tests/ui/size_of_in_element_count.rs
@@ -0,0 +1,61 @@
+#![warn(clippy::size_of_in_element_count)]
+#![allow(clippy::ptr_offset_with_cast)]
+
+use std::mem::{size_of, size_of_val};
+use std::ptr::{
+    copy, copy_nonoverlapping, slice_from_raw_parts, slice_from_raw_parts_mut, swap_nonoverlapping, write_bytes,
+};
+use std::slice::{from_raw_parts, from_raw_parts_mut};
+
+fn main() {
+    const SIZE: usize = 128;
+    const HALF_SIZE: usize = SIZE / 2;
+    const DOUBLE_SIZE: usize = SIZE * 2;
+    let mut x = [2u8; SIZE];
+    let mut y = [2u8; SIZE];
+
+    // Count is size_of (Should trigger the lint)
+    unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
+
+    unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
+    unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
+
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
+
+    unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
+    unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
+
+    unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
+
+    slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
+    slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
+
+    unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+    unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
+
+    unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
+    y.as_ptr().wrapping_sub(size_of::<u8>());
+    unsafe { y.as_ptr().add(size_of::<u8>()) };
+    y.as_mut_ptr().wrapping_add(size_of::<u8>());
+    unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
+    y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
+
+    // Count expression involving multiplication of size_of (Should trigger the lint)
+    unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+
+    // Count expression involving nested multiplications of size_of (Should trigger the lint)
+    unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
+
+    // Count expression involving divisions of size_of (Should trigger the lint)
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
+
+    // No size_of calls (Should not trigger the lint)
+    unsafe { copy(x.as_ptr(), y.as_mut_ptr(), SIZE) };
+
+    // Different types for pointee and size_of (Should not trigger the lint)
+    unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u16>() / 2 * SIZE) };
+}
diff --git a/tests/ui/size_of_in_element_count.stderr b/tests/ui/size_of_in_element_count.stderr
new file mode 100644
index 00000000000..b7f421ec997
--- /dev/null
+++ b/tests/ui/size_of_in_element_count.stderr
@@ -0,0 +1,195 @@
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:18:68
+   |
+LL |     unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+   |                                                                    ^^^^^^^^^^^^^^^
+   |
+   = note: `-D clippy::size-of-in-element-count` implied by `-D warnings`
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:19:62
+   |
+LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
+   |                                                              ^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:21:49
+   |
+LL |     unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
+   |                                                 ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:22:64
+   |
+LL |     unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
+   |                                                                ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:23:51
+   |
+LL |     unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
+   |                                                   ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:24:66
+   |
+LL |     unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
+   |                                                                  ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:26:47
+   |
+LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
+   |                                               ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:27:47
+   |
+LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
+   |                                               ^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:29:46
+   |
+LL |     unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:30:47
+   |
+LL |     unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:32:66
+   |
+LL |     unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
+   |                                                                  ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:34:46
+   |
+LL |     slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
+   |                                              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:35:38
+   |
+LL |     slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:37:49
+   |
+LL |     unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:38:41
+   |
+LL |     unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
+   |                                         ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:40:33
+   |
+LL |     unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
+   |                                 ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:41:29
+   |
+LL |     y.as_ptr().wrapping_sub(size_of::<u8>());
+   |                             ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:42:29
+   |
+LL |     unsafe { y.as_ptr().add(size_of::<u8>()) };
+   |                             ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:43:33
+   |
+LL |     y.as_mut_ptr().wrapping_add(size_of::<u8>());
+   |                                 ^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:44:32
+   |
+LL |     unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:45:36
+   |
+LL |     y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:48:62
+   |
+LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:51:62
+   |
+LL |     unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
+   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: found a count of bytes instead of a count of elements of T
+  --> $DIR/size_of_in_element_count.rs:54:47
+   |
+LL |     unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
+   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
+
+error: aborting due to 24 previous errors
+