diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 4ba09335cb7ab..9865b6a72ee69 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1134,9 +1134,14 @@ impl<'a> MethodDef<'a> {
trait_: &TraitDef<'b>,
enum_def: &'b EnumDef,
type_ident: Ident,
- selflike_args: ThinVec
>,
+ mut selflike_args: ThinVec
>,
nonselflike_args: &[P],
) -> BlockOrExpr {
+ assert!(
+ !selflike_args.is_empty(),
+ "static methods must use `expand_static_enum_method_body`",
+ );
+
let span = trait_.span;
let variants = &enum_def.variants;
@@ -1144,10 +1149,15 @@ impl<'a> MethodDef<'a> {
let unify_fieldless_variants =
self.fieldless_variants_strategy == FieldlessVariantsStrategy::Unify;
- // There is no sensible code to be generated for *any* deriving on a
- // zero-variant enum. So we just generate a failing expression.
+ // For zero-variant enum, this function body is unreachable. Generate
+ // `match *self {}`. This produces machine code identical to `unsafe {
+ // core::intrinsics::unreachable() }` while being safe and stable.
if variants.is_empty() {
- return BlockOrExpr(ThinVec::new(), Some(deriving::call_unreachable(cx, span)));
+ selflike_args.truncate(1);
+ let match_arg = cx.expr_deref(span, selflike_args.pop().unwrap());
+ let match_arms = ThinVec::new();
+ let expr = cx.expr_match(span, match_arg, match_arms);
+ return BlockOrExpr(ThinVec::new(), Some(expr));
}
let prefixes = iter::once("__self".to_string())
diff --git a/tests/ui/deriving/deriving-all-codegen.stdout b/tests/ui/deriving/deriving-all-codegen.stdout
index d6a2c80cc06b6..6bfc859bfe807 100644
--- a/tests/ui/deriving/deriving-all-codegen.stdout
+++ b/tests/ui/deriving/deriving-all-codegen.stdout
@@ -798,14 +798,14 @@ impl ::core::marker::Copy for Enum0 { }
#[automatically_derived]
impl ::core::fmt::Debug for Enum0 {
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
- unsafe { ::core::intrinsics::unreachable() }
+ match *self {}
}
}
#[automatically_derived]
impl ::core::hash::Hash for Enum0 {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
- unsafe { ::core::intrinsics::unreachable() }
+ match *self {}
}
}
#[automatically_derived]
@@ -813,9 +813,7 @@ impl ::core::marker::StructuralPartialEq for Enum0 { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Enum0 {
#[inline]
- fn eq(&self, other: &Enum0) -> bool {
- unsafe { ::core::intrinsics::unreachable() }
- }
+ fn eq(&self, other: &Enum0) -> bool { match *self {} }
}
#[automatically_derived]
impl ::core::marker::StructuralEq for Enum0 { }
@@ -831,15 +829,13 @@ impl ::core::cmp::PartialOrd for Enum0 {
#[inline]
fn partial_cmp(&self, other: &Enum0)
-> ::core::option::Option<::core::cmp::Ordering> {
- unsafe { ::core::intrinsics::unreachable() }
+ match *self {}
}
}
#[automatically_derived]
impl ::core::cmp::Ord for Enum0 {
#[inline]
- fn cmp(&self, other: &Enum0) -> ::core::cmp::Ordering {
- unsafe { ::core::intrinsics::unreachable() }
- }
+ fn cmp(&self, other: &Enum0) -> ::core::cmp::Ordering { match *self {} }
}
// A single-variant enum.