diff --git a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
index ea054a7e355..bbc7cd39627 100644
--- a/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/smart_ptr.rs
@@ -3,8 +3,9 @@ use std::mem::swap;
 use ast::HasAttrs;
 use rustc_ast::{
     self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem,
-    TraitBoundModifiers,
+    TraitBoundModifiers, VariantData,
 };
+use rustc_attr as attr;
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
@@ -24,11 +25,43 @@ pub fn expand_deriving_smart_ptr(
     _is_const: bool,
 ) {
     let (name_ident, generics) = if let Annotatable::Item(aitem) = item
-        && let ItemKind::Struct(_, g) = &aitem.kind
+        && let ItemKind::Struct(struct_data, g) = &aitem.kind
     {
+        let is_transparent = aitem.attrs.iter().any(|attr| {
+            attr::find_repr_attrs(cx.sess, attr)
+                .into_iter()
+                .any(|r| matches!(r, attr::ReprTransparent))
+        });
+        if !is_transparent {
+            cx.dcx()
+                .struct_span_err(
+                    span,
+                    "`SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`",
+                )
+                .emit();
+            return;
+        }
+        if !matches!(
+            struct_data,
+            VariantData::Struct { fields, recovered: _ } | VariantData::Tuple(fields, _)
+                if !fields.is_empty())
+        {
+            cx.dcx()
+                .struct_span_err(
+                    span,
+                    "`SmartPointer` can only be derived on `struct`s with at least one field",
+                )
+                .emit();
+            return;
+        }
         (aitem.ident, g)
     } else {
-        cx.dcx().struct_span_err(span, "`SmartPointer` can only be derived on `struct`s").emit();
+        cx.dcx()
+            .struct_span_err(
+                span,
+                "`SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`",
+            )
+            .emit();
         return;
     };
 
diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.rs b/tests/ui/deriving/deriving-smart-pointer-neg.rs
new file mode 100644
index 00000000000..bfb4e86b396
--- /dev/null
+++ b/tests/ui/deriving/deriving-smart-pointer-neg.rs
@@ -0,0 +1,45 @@
+#![feature(derive_smart_pointer, arbitrary_self_types)]
+
+use std::marker::SmartPointer;
+
+#[derive(SmartPointer)]
+//~^ ERROR: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
+enum NotStruct<'a, T: ?Sized> {
+    Variant(&'a T),
+}
+
+#[derive(SmartPointer)]
+//~^ ERROR: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits
+#[repr(transparent)]
+struct NoPointee<'a, T: ?Sized> {
+    ptr: &'a T,
+}
+
+#[derive(SmartPointer)]
+//~^ ERROR: `SmartPointer` can only be derived on `struct`s with at least one field
+#[repr(transparent)]
+struct NoField<'a, #[pointee] T: ?Sized> {}
+//~^ ERROR: lifetime parameter `'a` is never used
+//~| ERROR: type parameter `T` is never used
+
+#[derive(SmartPointer)]
+//~^ ERROR: `SmartPointer` can only be derived on `struct`s with at least one field
+#[repr(transparent)]
+struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
+//~^ ERROR: lifetime parameter `'a` is never used
+//~| ERROR: type parameter `T` is never used
+
+#[derive(SmartPointer)]
+//~^ ERROR: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
+struct NotTransparent<'a, #[pointee] T: ?Sized> {
+    ptr: &'a T,
+}
+
+// However, reordering attributes should work nevertheless.
+#[repr(transparent)]
+#[derive(SmartPointer)]
+struct ThisIsAPossibleSmartPointer<'a, #[pointee] T: ?Sized> {
+    ptr: &'a T,
+}
+
+fn main() {}
diff --git a/tests/ui/deriving/deriving-smart-pointer-neg.stderr b/tests/ui/deriving/deriving-smart-pointer-neg.stderr
new file mode 100644
index 00000000000..d994a6ee376
--- /dev/null
+++ b/tests/ui/deriving/deriving-smart-pointer-neg.stderr
@@ -0,0 +1,75 @@
+error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
+  --> $DIR/deriving-smart-pointer-neg.rs:5:10
+   |
+LL | #[derive(SmartPointer)]
+   |          ^^^^^^^^^^^^
+   |
+   = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: At least one generic type should be designated as `#[pointee]` in order to derive `SmartPointer` traits
+  --> $DIR/deriving-smart-pointer-neg.rs:11:10
+   |
+LL | #[derive(SmartPointer)]
+   |          ^^^^^^^^^^^^
+   |
+   = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `SmartPointer` can only be derived on `struct`s with at least one field
+  --> $DIR/deriving-smart-pointer-neg.rs:18:10
+   |
+LL | #[derive(SmartPointer)]
+   |          ^^^^^^^^^^^^
+   |
+   = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `SmartPointer` can only be derived on `struct`s with at least one field
+  --> $DIR/deriving-smart-pointer-neg.rs:25:10
+   |
+LL | #[derive(SmartPointer)]
+   |          ^^^^^^^^^^^^
+   |
+   = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: `SmartPointer` can only be derived on `struct`s with `#[repr(transparent)]`
+  --> $DIR/deriving-smart-pointer-neg.rs:32:10
+   |
+LL | #[derive(SmartPointer)]
+   |          ^^^^^^^^^^^^
+   |
+   = note: this error originates in the derive macro `SmartPointer` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0392]: lifetime parameter `'a` is never used
+  --> $DIR/deriving-smart-pointer-neg.rs:21:16
+   |
+LL | struct NoField<'a, #[pointee] T: ?Sized> {}
+   |                ^^ unused lifetime parameter
+   |
+   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
+
+error[E0392]: type parameter `T` is never used
+  --> $DIR/deriving-smart-pointer-neg.rs:21:31
+   |
+LL | struct NoField<'a, #[pointee] T: ?Sized> {}
+   |                               ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+
+error[E0392]: lifetime parameter `'a` is never used
+  --> $DIR/deriving-smart-pointer-neg.rs:28:20
+   |
+LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
+   |                    ^^ unused lifetime parameter
+   |
+   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
+
+error[E0392]: type parameter `T` is never used
+  --> $DIR/deriving-smart-pointer-neg.rs:28:35
+   |
+LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
+   |                                   ^ unused type parameter
+   |
+   = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
+
+error: aborting due to 9 previous errors
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/deriving/deriving-smart-pointer.rs b/tests/ui/deriving/deriving-smart-pointer.rs
index cfc3369850b..d34a502da68 100644
--- a/tests/ui/deriving/deriving-smart-pointer.rs
+++ b/tests/ui/deriving/deriving-smart-pointer.rs
@@ -4,6 +4,7 @@
 use std::marker::SmartPointer;
 
 #[derive(SmartPointer)]
+#[repr(transparent)]
 struct MyPointer<'a, #[pointee] T: ?Sized> {
     ptr: &'a T,
 }
diff --git a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs
index ae8005592cd..3257a9ca624 100644
--- a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs
+++ b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.rs
@@ -1,6 +1,7 @@
 use std::marker::SmartPointer; //~ ERROR use of unstable library feature 'derive_smart_pointer'
 
 #[derive(SmartPointer)] //~ ERROR use of unstable library feature 'derive_smart_pointer'
+#[repr(transparent)]
 struct MyPointer<'a, #[pointee] T: ?Sized> {
     //~^ ERROR the `#[pointee]` attribute is an experimental feature
     ptr: &'a T,
diff --git a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr
index 0ffd82fb9e1..19501939dc5 100644
--- a/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr
+++ b/tests/ui/feature-gates/feature-gate-derive-smart-pointer.stderr
@@ -9,7 +9,7 @@ LL | #[derive(SmartPointer)]
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: the `#[pointee]` attribute is an experimental feature
-  --> $DIR/feature-gate-derive-smart-pointer.rs:4:22
+  --> $DIR/feature-gate-derive-smart-pointer.rs:5:22
    |
 LL | struct MyPointer<'a, #[pointee] T: ?Sized> {
    |                      ^^^^^^^^^^