diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index ecd2b75ae4427..66af491607435 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1040,6 +1040,8 @@ pub fn copy<T: Copy>(x: &T) -> T {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_const_unstable(feature = "const_transmute_copy", issue = "83165")]
 pub const unsafe fn transmute_copy<T, U>(src: &T) -> U {
+    assert!(size_of::<T>() >= size_of::<U>(), "cannot transmute_copy if U is larger than T");
+
     // If U has a higher alignment requirement, src might not be suitably aligned.
     if align_of::<U>() > align_of::<T>() {
         // SAFETY: `src` is a reference which is guaranteed to be valid for reads.
diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs
index 3b13dc0832fa4..6856d1a1f51ae 100644
--- a/library/core/tests/mem.rs
+++ b/library/core/tests/mem.rs
@@ -97,6 +97,46 @@ fn test_transmute_copy() {
     assert_eq!(1, unsafe { transmute_copy(&1) });
 }
 
+#[test]
+fn test_transmute_copy_shrink() {
+    assert_eq!(0_u8, unsafe { transmute_copy(&0_u64) });
+}
+
+#[test]
+fn test_transmute_copy_unaligned() {
+    #[repr(C)]
+    #[derive(Default)]
+    struct Unaligned {
+        a: u8,
+        b: [u8; 8],
+    }
+
+    let u = Unaligned::default();
+    assert_eq!(0_u64, unsafe { transmute_copy(&u.b) });
+}
+
+#[test]
+#[cfg(panic = "unwind")]
+fn test_transmute_copy_grow_panics() {
+    use std::panic;
+
+    let err = panic::catch_unwind(panic::AssertUnwindSafe(|| unsafe {
+        let _unused: u64 = transmute_copy(&1_u8);
+    }));
+
+    match err {
+        Ok(_) => unreachable!(),
+        Err(payload) => {
+            payload
+                .downcast::<&'static str>()
+                .and_then(|s| {
+                    if *s == "cannot transmute_copy if U is larger than T" { Ok(s) } else { Err(s) }
+                })
+                .unwrap_or_else(|p| panic::resume_unwind(p));
+        }
+    }
+}
+
 #[test]
 #[allow(dead_code)]
 fn test_discriminant_send_sync() {