Auto merge of #106884 - clubby789:fieldless-enum-debug, r=michaelwoerister
Simplify `derive(Debug)` output for fieldless enums Fixes #106875
This commit is contained in:
commit
b22aa57fd5
12 changed files with 130 additions and 47 deletions
|
@ -82,7 +82,7 @@ pub fn expand_deriving_clone(
|
||||||
nonself_args: Vec::new(),
|
nonself_args: Vec::new(),
|
||||||
ret_ty: Self_,
|
ret_ty: Self_,
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: false,
|
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
|
||||||
combine_substructure: substructure,
|
combine_substructure: substructure,
|
||||||
}],
|
}],
|
||||||
associated_types: Vec::new(),
|
associated_types: Vec::new(),
|
||||||
|
@ -177,7 +177,9 @@ fn cs_clone(
|
||||||
all_fields = af;
|
all_fields = af;
|
||||||
vdata = &variant.data;
|
vdata = &variant.data;
|
||||||
}
|
}
|
||||||
EnumTag(..) => cx.span_bug(trait_span, &format!("enum tags in `derive({})`", name,)),
|
EnumTag(..) | AllFieldlessEnum(..) => {
|
||||||
|
cx.span_bug(trait_span, &format!("enum tags in `derive({})`", name,))
|
||||||
|
}
|
||||||
StaticEnum(..) | StaticStruct(..) => {
|
StaticEnum(..) | StaticStruct(..) => {
|
||||||
cx.span_bug(trait_span, &format!("associated function in `derive({})`", name))
|
cx.span_bug(trait_span, &format!("associated function in `derive({})`", name))
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ pub fn expand_deriving_eq(
|
||||||
nonself_args: vec![],
|
nonself_args: vec![],
|
||||||
ret_ty: Unit,
|
ret_ty: Unit,
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: true,
|
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||||
cs_total_eq_assert(a, b, c)
|
cs_total_eq_assert(a, b, c)
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -29,7 +29,7 @@ pub fn expand_deriving_ord(
|
||||||
nonself_args: vec![(self_ref(), sym::other)],
|
nonself_args: vec![(self_ref(), sym::other)],
|
||||||
ret_ty: Path(path_std!(cmp::Ordering)),
|
ret_ty: Path(path_std!(cmp::Ordering)),
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: true,
|
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||||
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))),
|
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_cmp(a, b, c))),
|
||||||
}],
|
}],
|
||||||
associated_types: Vec::new(),
|
associated_types: Vec::new(),
|
||||||
|
|
|
@ -76,7 +76,7 @@ pub fn expand_deriving_partial_eq(
|
||||||
nonself_args: vec![(self_ref(), sym::other)],
|
nonself_args: vec![(self_ref(), sym::other)],
|
||||||
ret_ty: Path(path_local!(bool)),
|
ret_ty: Path(path_local!(bool)),
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: true,
|
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||||
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_eq(a, b, c))),
|
combine_substructure: combine_substructure(Box::new(|a, b, c| cs_eq(a, b, c))),
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,7 @@ pub fn expand_deriving_partial_ord(
|
||||||
nonself_args: vec![(self_ref(), sym::other)],
|
nonself_args: vec![(self_ref(), sym::other)],
|
||||||
ret_ty,
|
ret_ty,
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: true,
|
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||||
combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
|
combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
|
||||||
cs_partial_cmp(cx, span, substr)
|
cs_partial_cmp(cx, span, substr)
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -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(),
|
||||||
unify_fieldless_variants: false,
|
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)
|
||||||
})),
|
})),
|
||||||
|
@ -43,16 +45,18 @@ pub fn expand_deriving_debug(
|
||||||
}
|
}
|
||||||
|
|
||||||
fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
|
||||||
|
// We want to make sure we have the ctxt set so that we can use unstable methods
|
||||||
|
let span = cx.with_def_site_ctxt(span);
|
||||||
|
|
||||||
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(enum_def) => return show_fieldless_enum(cx, span, enum_def, substr),
|
||||||
EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
|
EnumTag(..) | StaticStruct(..) | StaticEnum(..) => {
|
||||||
cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
|
cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// We want to make sure we have the ctxt set so that we can use unstable methods
|
|
||||||
let span = cx.with_def_site_ctxt(span);
|
|
||||||
let name = cx.expr_str(span, ident.name);
|
let name = cx.expr_str(span, ident.name);
|
||||||
let fmt = substr.nonselflike_args[0].clone();
|
let fmt = substr.nonselflike_args[0].clone();
|
||||||
|
|
||||||
|
@ -173,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]))
|
||||||
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ pub fn expand_deriving_rustc_decodable(
|
||||||
PathKind::Std,
|
PathKind::Std,
|
||||||
)),
|
)),
|
||||||
attributes: ast::AttrVec::new(),
|
attributes: ast::AttrVec::new(),
|
||||||
unify_fieldless_variants: false,
|
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
|
||||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||||
decodable_substructure(a, b, c, krate)
|
decodable_substructure(a, b, c, krate)
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -34,7 +34,7 @@ pub fn expand_deriving_default(
|
||||||
nonself_args: Vec::new(),
|
nonself_args: Vec::new(),
|
||||||
ret_ty: Self_,
|
ret_ty: Self_,
|
||||||
attributes: attrs,
|
attributes: attrs,
|
||||||
unify_fieldless_variants: false,
|
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
|
||||||
combine_substructure: combine_substructure(Box::new(|cx, trait_span, substr| {
|
combine_substructure: combine_substructure(Box::new(|cx, trait_span, substr| {
|
||||||
match substr.fields {
|
match substr.fields {
|
||||||
StaticStruct(_, fields) => {
|
StaticStruct(_, fields) => {
|
||||||
|
|
|
@ -133,7 +133,7 @@ pub fn expand_deriving_rustc_encodable(
|
||||||
PathKind::Std,
|
PathKind::Std,
|
||||||
)),
|
)),
|
||||||
attributes: AttrVec::new(),
|
attributes: AttrVec::new(),
|
||||||
unify_fieldless_variants: false,
|
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
|
||||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||||
encodable_substructure(a, b, c, krate)
|
encodable_substructure(a, b, c, krate)
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -222,14 +222,27 @@ pub struct MethodDef<'a> {
|
||||||
|
|
||||||
pub attributes: ast::AttrVec,
|
pub attributes: ast::AttrVec,
|
||||||
|
|
||||||
/// Can we combine fieldless variants for enums into a single match arm?
|
pub fieldless_variants_strategy: FieldlessVariantsStrategy,
|
||||||
/// If true, indicates that the trait operation uses the enum tag in some
|
|
||||||
/// way.
|
|
||||||
pub unify_fieldless_variants: bool,
|
|
||||||
|
|
||||||
pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
|
pub combine_substructure: RefCell<CombineSubstructureFunc<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// How to handle fieldless enum variants.
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
pub enum FieldlessVariantsStrategy {
|
||||||
|
/// Combine fieldless variants into a single match arm.
|
||||||
|
/// This assumes that relevant information has been handled
|
||||||
|
/// by looking at the enum's discriminant.
|
||||||
|
Unify,
|
||||||
|
/// Don't do anything special about fieldless variants. They are
|
||||||
|
/// handled like any other variant.
|
||||||
|
Default,
|
||||||
|
/// If all variants of the enum are fieldless, expand the special
|
||||||
|
/// `AllFieldLessEnum` substructure, so that the entire enum can be handled
|
||||||
|
/// at once.
|
||||||
|
SpecializeIfAllVariantsFieldless,
|
||||||
|
}
|
||||||
|
|
||||||
/// All the data about the data structure/method being derived upon.
|
/// All the data about the data structure/method being derived upon.
|
||||||
pub struct Substructure<'a> {
|
pub struct Substructure<'a> {
|
||||||
/// ident of self
|
/// ident of self
|
||||||
|
@ -264,9 +277,14 @@ pub enum StaticFields {
|
||||||
|
|
||||||
/// A summary of the possible sets of fields.
|
/// A summary of the possible sets of fields.
|
||||||
pub enum SubstructureFields<'a> {
|
pub enum SubstructureFields<'a> {
|
||||||
/// A non-static method with `Self` is a struct.
|
/// A non-static method where `Self` is a struct.
|
||||||
Struct(&'a ast::VariantData, Vec<FieldInfo>),
|
Struct(&'a ast::VariantData, Vec<FieldInfo>),
|
||||||
|
|
||||||
|
/// A non-static method handling the entire enum at once
|
||||||
|
/// (after it has been determined that none of the enum
|
||||||
|
/// variants has any fields).
|
||||||
|
AllFieldlessEnum(&'a ast::EnumDef),
|
||||||
|
|
||||||
/// Matching variants of the enum: variant index, variant count, ast::Variant,
|
/// Matching variants of the enum: variant index, variant count, ast::Variant,
|
||||||
/// fields: the field name is only non-`None` in the case of a struct
|
/// fields: the field name is only non-`None` in the case of a struct
|
||||||
/// variant.
|
/// variant.
|
||||||
|
@ -1086,8 +1104,8 @@ impl<'a> MethodDef<'a> {
|
||||||
/// ```
|
/// ```
|
||||||
/// Creates a tag check combined with a match for a tuple of all
|
/// Creates a tag check combined with a match for a tuple of all
|
||||||
/// `selflike_args`, with an arm for each variant with fields, possibly an
|
/// `selflike_args`, with an arm for each variant with fields, possibly an
|
||||||
/// arm for each fieldless variant (if `!unify_fieldless_variants` is not
|
/// arm for each fieldless variant (if `unify_fieldless_variants` is not
|
||||||
/// true), and possibly a default arm.
|
/// `Unify`), and possibly a default arm.
|
||||||
fn expand_enum_method_body<'b>(
|
fn expand_enum_method_body<'b>(
|
||||||
&self,
|
&self,
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
|
@ -1101,7 +1119,8 @@ impl<'a> MethodDef<'a> {
|
||||||
let variants = &enum_def.variants;
|
let variants = &enum_def.variants;
|
||||||
|
|
||||||
// Traits that unify fieldless variants always use the tag(s).
|
// Traits that unify fieldless variants always use the tag(s).
|
||||||
let uses_tags = self.unify_fieldless_variants;
|
let unify_fieldless_variants =
|
||||||
|
self.fieldless_variants_strategy == FieldlessVariantsStrategy::Unify;
|
||||||
|
|
||||||
// There is no sensible code to be generated for *any* deriving on a
|
// There is no sensible code to be generated for *any* deriving on a
|
||||||
// zero-variant enum. So we just generate a failing expression.
|
// zero-variant enum. So we just generate a failing expression.
|
||||||
|
@ -1161,7 +1180,9 @@ impl<'a> MethodDef<'a> {
|
||||||
// match is necessary.
|
// match is necessary.
|
||||||
let all_fieldless = variants.iter().all(|v| v.data.fields().is_empty());
|
let all_fieldless = variants.iter().all(|v| v.data.fields().is_empty());
|
||||||
if all_fieldless {
|
if all_fieldless {
|
||||||
if uses_tags && variants.len() > 1 {
|
if variants.len() > 1 {
|
||||||
|
match self.fieldless_variants_strategy {
|
||||||
|
FieldlessVariantsStrategy::Unify => {
|
||||||
// If the type is fieldless and the trait uses the tag and
|
// If the type is fieldless and the trait uses the tag and
|
||||||
// there are multiple variants, we need just an operation on
|
// there are multiple variants, we need just an operation on
|
||||||
// the tag(s).
|
// the tag(s).
|
||||||
|
@ -1176,8 +1197,18 @@ impl<'a> MethodDef<'a> {
|
||||||
tag_let_stmts.append(&mut tag_check.0);
|
tag_let_stmts.append(&mut tag_check.0);
|
||||||
return BlockOrExpr(tag_let_stmts, tag_check.1);
|
return BlockOrExpr(tag_let_stmts, tag_check.1);
|
||||||
}
|
}
|
||||||
|
FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless => {
|
||||||
if variants.len() == 1 {
|
return self.call_substructure_method(
|
||||||
|
cx,
|
||||||
|
trait_,
|
||||||
|
type_ident,
|
||||||
|
nonselflike_args,
|
||||||
|
&AllFieldlessEnum(enum_def),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
FieldlessVariantsStrategy::Default => (),
|
||||||
|
}
|
||||||
|
} else if variants.len() == 1 {
|
||||||
// If there is a single variant, we don't need an operation on
|
// If there is a single variant, we don't need an operation on
|
||||||
// the tag(s). Just use the most degenerate result.
|
// the tag(s). Just use the most degenerate result.
|
||||||
return self.call_substructure_method(
|
return self.call_substructure_method(
|
||||||
|
@ -1187,7 +1218,7 @@ impl<'a> MethodDef<'a> {
|
||||||
nonselflike_args,
|
nonselflike_args,
|
||||||
&EnumMatching(0, 1, &variants[0], Vec::new()),
|
&EnumMatching(0, 1, &variants[0], Vec::new()),
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// These arms are of the form:
|
// These arms are of the form:
|
||||||
|
@ -1198,7 +1229,7 @@ impl<'a> MethodDef<'a> {
|
||||||
let mut match_arms: Vec<ast::Arm> = variants
|
let mut match_arms: Vec<ast::Arm> = variants
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.filter(|&(_, v)| !(self.unify_fieldless_variants && v.data.fields().is_empty()))
|
.filter(|&(_, v)| !(unify_fieldless_variants && v.data.fields().is_empty()))
|
||||||
.map(|(index, variant)| {
|
.map(|(index, variant)| {
|
||||||
// A single arm has form (&VariantK, &VariantK, ...) => BodyK
|
// A single arm has form (&VariantK, &VariantK, ...) => BodyK
|
||||||
// (see "Final wrinkle" note below for why.)
|
// (see "Final wrinkle" note below for why.)
|
||||||
|
@ -1249,7 +1280,7 @@ impl<'a> MethodDef<'a> {
|
||||||
// Add a default arm to the match, if necessary.
|
// Add a default arm to the match, if necessary.
|
||||||
let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty());
|
let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty());
|
||||||
let default = match first_fieldless {
|
let default = match first_fieldless {
|
||||||
Some(v) if self.unify_fieldless_variants => {
|
Some(v) if unify_fieldless_variants => {
|
||||||
// We need a default case that handles all the fieldless
|
// We need a default case that handles all the fieldless
|
||||||
// variants. The index and actual variant aren't meaningful in
|
// variants. The index and actual variant aren't meaningful in
|
||||||
// this case, so just use dummy values.
|
// this case, so just use dummy values.
|
||||||
|
@ -1296,7 +1327,7 @@ impl<'a> MethodDef<'a> {
|
||||||
// If the trait uses the tag and there are multiple variants, we need
|
// If the trait uses the tag and there are multiple variants, we need
|
||||||
// to add a tag check operation before the match. Otherwise, the match
|
// to add a tag check operation before the match. Otherwise, the match
|
||||||
// is enough.
|
// is enough.
|
||||||
if uses_tags && variants.len() > 1 {
|
if unify_fieldless_variants && variants.len() > 1 {
|
||||||
let (tag_field, mut tag_let_stmts) = get_tag_pieces(cx);
|
let (tag_field, mut tag_let_stmts) = get_tag_pieces(cx);
|
||||||
|
|
||||||
// Combine a tag check with the match.
|
// Combine a tag check with the match.
|
||||||
|
@ -1580,5 +1611,6 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
|
StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
|
||||||
|
AllFieldlessEnum(..) => cx.span_bug(trait_span, "fieldless enum in `derive`"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ pub fn expand_deriving_hash(
|
||||||
nonself_args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)],
|
nonself_args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)],
|
||||||
ret_ty: Unit,
|
ret_ty: Unit,
|
||||||
attributes: AttrVec::new(),
|
attributes: AttrVec::new(),
|
||||||
unify_fieldless_variants: true,
|
fieldless_variants_strategy: FieldlessVariantsStrategy::Unify,
|
||||||
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
combine_substructure: combine_substructure(Box::new(|a, b, c| {
|
||||||
hash_substructure(a, b, c)
|
hash_substructure(a, b, c)
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -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 {
|
||||||
|
::core::fmt::Formatter::write_str(f,
|
||||||
match self {
|
match self {
|
||||||
Fieldless::A => ::core::fmt::Formatter::write_str(f, "A"),
|
Fieldless::A => "A",
|
||||||
Fieldless::B => ::core::fmt::Formatter::write_str(f, "B"),
|
Fieldless::B => "B",
|
||||||
Fieldless::C => ::core::fmt::Formatter::write_str(f, "C"),
|
Fieldless::C => "C",
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue