Skip to content

Commit 41140f2

Browse files
committed
Use discriminant_value instead of casting
1 parent f1021ed commit 41140f2

File tree

2 files changed

+55
-26
lines changed

2 files changed

+55
-26
lines changed

compiler/rustc_builtin_macros/src/deriving/debug.rs

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use crate::deriving::generic::ty::*;
22
use crate::deriving::generic::*;
33
use crate::deriving::path_std;
44

5-
use ast::EnumDef;
6-
use rustc_ast::{self as ast, MetaItem};
5+
use rustc_ast::{self as ast, token, EnumDef, ExprKind, MetaItem, TyKind};
6+
77
use rustc_expand::base::{Annotatable, ExtCtxt};
88
use rustc_span::symbol::{sym, Ident, Symbol};
99
use rustc_span::Span;
@@ -152,15 +152,13 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
152152
let path_debug = cx.path_global(span, cx.std_path(&[sym::fmt, sym::Debug]));
153153
let ty_dyn_debug = cx.ty(
154154
span,
155-
ast::TyKind::TraitObject(
155+
TyKind::TraitObject(
156156
vec![cx.trait_bound(path_debug, false)],
157157
ast::TraitObjectSyntax::Dyn,
158158
),
159159
);
160-
let ty_slice = cx.ty(
161-
span,
162-
ast::TyKind::Slice(cx.ty_ref(span, ty_dyn_debug, None, ast::Mutability::Not)),
163-
);
160+
let ty_slice =
161+
cx.ty(span, TyKind::Slice(cx.ty_ref(span, ty_dyn_debug, None, ast::Mutability::Not)));
164162
let values_let = cx.stmt_let_ty(
165163
span,
166164
false,
@@ -251,7 +249,10 @@ fn show_fieldless_enum(
251249
/// ```text
252250
/// impl ::core::fmt::Debug for A {
253251
/// fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
254-
/// ::core::fmt::Formatter::write_str(f, ["A", "B", "C"][*self as usize])
252+
/// ::core::fmt::Formatter::write_str(f, {
253+
/// const __NAMES: [&str; 3] = ["A", "B", "C"];
254+
/// __NAMES[::core::intrinsics::discriminant_value(self) as usize]
255+
/// })
255256
/// }
256257
/// }
257258
/// ```
@@ -260,31 +261,55 @@ fn show_fieldless_enum_array(
260261
span: Span,
261262
def: &EnumDef,
262263
) -> Option<ast::ptr::P<ast::Expr>> {
263-
let container_id = cx.current_expansion.id.expn_data().parent.expect_local();
264-
let has_derive_copy = cx.resolver.has_derive_copy(container_id);
265-
// FIXME(clubby789): handle repr(xx) enums too
266-
if !has_derive_copy {
267-
return None;
268-
}
269264
if def.variants.len() >= cx.sess.target.pointer_width as usize {
270265
return None;
271266
}
272-
// FIXME(clubby789): handle enums with discriminants matching their indexes
273-
let name_array = def
267+
let names = def
274268
.variants
275269
.iter()
276270
.map(|v| if v.disr_expr.is_none() { Some(cx.expr_str(span, v.ident.name)) } else { None })
277271
.collect::<Option<ThinVec<_>>>()?;
278-
let name = cx.expr(
272+
let str_ty = cx.ty(
279273
span,
280-
ast::ExprKind::Index(
281-
cx.expr_array(span, name_array),
282-
cx.expr_cast(
283-
span,
284-
cx.expr_deref(span, cx.expr_self(span)),
285-
cx.ty_path(ast::Path::from_ident(Ident::with_dummy_span(sym::usize))),
286-
),
274+
TyKind::Ref(
275+
None,
276+
ast::MutTy {
277+
ty: cx.ty(
278+
span,
279+
TyKind::Path(None, ast::Path::from_ident(Ident::new(sym::str, span))),
280+
),
281+
mutbl: ast::Mutability::Not,
282+
},
287283
),
288284
);
289-
Some(name)
285+
286+
let size = cx.anon_const(
287+
span,
288+
ExprKind::Lit(token::Lit::new(
289+
token::LitKind::Integer,
290+
Symbol::intern(&def.variants.len().to_string()),
291+
None,
292+
)),
293+
);
294+
// Create a constant to prevent the array being stack-allocated
295+
let arr_name = Ident::from_str_and_span("__NAMES", span);
296+
let names_const = cx.item_const(
297+
span,
298+
arr_name,
299+
cx.ty(span, TyKind::Array(str_ty, size)),
300+
cx.expr_array(span, names),
301+
);
302+
let discrim_value = cx.std_path(&[sym::intrinsics, sym::discriminant_value]);
303+
304+
let index = cx.expr_cast(
305+
span,
306+
cx.expr_call_global(span, discrim_value, thin_vec![cx.expr_self(span)]),
307+
cx.ty_path(ast::Path::from_ident(Ident::new(sym::usize, span))),
308+
);
309+
let name = cx.expr(span, ExprKind::Index(cx.expr_ident(span, arr_name), index));
310+
Some(
311+
cx.expr_block(
312+
cx.block(span, thin_vec![cx.stmt_item(span, names_const), cx.stmt_expr(name)]),
313+
),
314+
)
290315
}

tests/ui/deriving/deriving-all-codegen.stdout

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -989,7 +989,11 @@ impl ::core::marker::Copy for Fieldless { }
989989
#[automatically_derived]
990990
impl ::core::fmt::Debug for Fieldless {
991991
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
992-
::core::fmt::Formatter::write_str(f, ["A", "B", "C"][*self as usize])
992+
::core::fmt::Formatter::write_str(f,
993+
{
994+
const __NAMES: [&str; 3] = ["A", "B", "C"];
995+
__NAMES[::core::intrinsics::discriminant_value(self) as usize]
996+
})
993997
}
994998
}
995999
#[automatically_derived]

0 commit comments

Comments
 (0)