Special case derive(Debug)
for fieldless enums
This commit is contained in:
parent
97cf1713d1
commit
95a824c02c
@ -2,6 +2,7 @@ use crate::deriving::generic::ty::*;
|
|||||||
use crate::deriving::generic::*;
|
use crate::deriving::generic::*;
|
||||||
use crate::deriving::path_std;
|
use crate::deriving::path_std;
|
||||||
|
|
||||||
|
use ast::EnumDef;
|
||||||
use rustc_ast::{self as ast, MetaItem};
|
use rustc_ast::{self as ast, MetaItem};
|
||||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||||
@ -31,7 +32,8 @@ pub fn expand_deriving_debug(
|
|||||||
nonself_args: vec![(fmtr, sym::f)],
|
nonself_args: vec![(fmtr, sym::f)],
|
||||||
ret_ty: Path(path_std!(fmt::Result)),
|
ret_ty: Path(path_std!(fmt::Result)),
|
||||||
attributes: ast::AttrVec::new(),
|
attributes: ast::AttrVec::new(),
|
||||||
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
|
fieldless_variants_strategy:
|
||||||
|
FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless,
|
||||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||||
show_substructure(a, b, c)
|
show_substructure(a, b, c)
|
||||||
})),
|
})),
|
||||||
@ -49,7 +51,8 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
|||||||
let (ident, vdata, fields) = match substr.fields {
|
let (ident, vdata, fields) = match substr.fields {
|
||||||
Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
|
Struct(vdata, fields) => (substr.type_ident, *vdata, fields),
|
||||||
EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields),
|
EnumMatching(_, _, v, fields) => (v.ident, &v.data, fields),
|
||||||
AllFieldlessEnum(..) | EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
|
AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, substr),
|
||||||
|
EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
|
||||||
cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
|
cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -174,3 +177,47 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
|||||||
BlockOrExpr::new_mixed(stmts, Some(expr))
|
BlockOrExpr::new_mixed(stmts, Some(expr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Special case for enums with no fields. Builds:
|
||||||
|
/// ```text
|
||||||
|
/// impl ::core::fmt::Debug for A {
|
||||||
|
/// fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||||
|
/// ::core::fmt::Formatter::write_str(f,
|
||||||
|
/// match self {
|
||||||
|
/// A::A => "A",
|
||||||
|
/// A::B() => "B",
|
||||||
|
/// A::C {} => "C",
|
||||||
|
/// })
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
fn show_fieldless_enum(
|
||||||
|
cx: &mut ExtCtxt<'_>,
|
||||||
|
span: Span,
|
||||||
|
def: &EnumDef,
|
||||||
|
substr: &Substructure<'_>,
|
||||||
|
) -> BlockOrExpr {
|
||||||
|
let fmt = substr.nonselflike_args[0].clone();
|
||||||
|
let arms = def
|
||||||
|
.variants
|
||||||
|
.iter()
|
||||||
|
.map(|v| {
|
||||||
|
let variant_path = cx.path(span, vec![substr.type_ident, v.ident]);
|
||||||
|
let pat = match &v.data {
|
||||||
|
ast::VariantData::Tuple(fields, _) => {
|
||||||
|
debug_assert!(fields.is_empty());
|
||||||
|
cx.pat_tuple_struct(span, variant_path, vec![])
|
||||||
|
}
|
||||||
|
ast::VariantData::Struct(fields, _) => {
|
||||||
|
debug_assert!(fields.is_empty());
|
||||||
|
cx.pat_struct(span, variant_path, vec![])
|
||||||
|
}
|
||||||
|
ast::VariantData::Unit(_) => cx.pat_path(span, variant_path),
|
||||||
|
};
|
||||||
|
cx.arm(span, pat, cx.expr_str(span, v.ident.name))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
let name = cx.expr_match(span, cx.expr_self(span), arms);
|
||||||
|
let fn_path_write_str = cx.std_path(&[sym::fmt, sym::Formatter, sym::write_str]);
|
||||||
|
BlockOrExpr::new_expr(cx.expr_call_global(span, fn_path_write_str, vec![fmt, name]))
|
||||||
|
}
|
||||||
|
@ -731,11 +731,12 @@ impl ::core::marker::Copy for Fieldless { }
|
|||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl ::core::fmt::Debug for Fieldless {
|
impl ::core::fmt::Debug for Fieldless {
|
||||||
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
|
||||||
match self {
|
::core::fmt::Formatter::write_str(f,
|
||||||
Fieldless::A => ::core::fmt::Formatter::write_str(f, "A"),
|
match self {
|
||||||
Fieldless::B => ::core::fmt::Formatter::write_str(f, "B"),
|
Fieldless::A => "A",
|
||||||
Fieldless::C => ::core::fmt::Formatter::write_str(f, "C"),
|
Fieldless::B => "B",
|
||||||
}
|
Fieldless::C => "C",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user