diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 74bcac2b5414d..8c2f52172ee70 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1881,7 +1881,18 @@ impl<T, A: Allocator> Vec<T, A> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn clear(&mut self) {
-        self.truncate(0)
+        let elems: *mut [T] = self.as_mut_slice();
+
+        // SAFETY:
+        // - `elems` comes directly from `as_mut_slice` and is therefore valid.
+        // - Setting `self.len` before calling `drop_in_place` means that,
+        //   if an element's `Drop` impl panics, the vector's `Drop` impl will
+        //   do nothing (leaking the rest of the elements) instead of dropping
+        //   some twice.
+        unsafe {
+            self.len = 0;
+            ptr::drop_in_place(elems);
+        }
     }
 
     /// Returns the number of elements in the vector, also referred to
diff --git a/src/test/codegen/vec-clear.rs b/src/test/codegen/vec-clear.rs
deleted file mode 100644
index 15bfe421e9d35..0000000000000
--- a/src/test/codegen/vec-clear.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-// compile-flags: -O
-
-#![crate_type = "lib"]
-
-// CHECK-LABEL: @vec_clear
-#[no_mangle]
-pub fn vec_clear(x: &mut Vec<u32>) {
-    // CHECK-NOT: load
-    // CHECK-NOT: icmp
-    x.clear()
-}