Skip to content

Commit 781fc90

Browse files
committed
Incorporate repr-attr into deriving(PartialOrd) to avoid truncation errors.
remove out of date fixme.
1 parent afb7acf commit 781fc90

File tree

1 file changed

+38
-13
lines changed
  • src/libsyntax/ext/deriving/generic

1 file changed

+38
-13
lines changed

src/libsyntax/ext/deriving/generic/mod.rs

+38-13
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ use ext::base::ExtCtxt;
201201
use ext::build::AstBuilder;
202202
use codemap::{self, DUMMY_SP};
203203
use codemap::Span;
204+
use diagnostic::SpanHandler;
204205
use fold::MoveMap;
205206
use owned_slice::OwnedSlice;
206207
use parse::token::InternedString;
@@ -391,6 +392,7 @@ impl<'a> TraitDef<'a> {
391392
ast::ItemEnum(ref enum_def, ref generics) => {
392393
self.expand_enum_def(cx,
393394
enum_def,
395+
&item.attrs[..],
394396
item.ident,
395397
generics)
396398
}
@@ -653,6 +655,7 @@ impl<'a> TraitDef<'a> {
653655
fn expand_enum_def(&self,
654656
cx: &mut ExtCtxt,
655657
enum_def: &EnumDef,
658+
type_attrs: &[ast::Attribute],
656659
type_ident: Ident,
657660
generics: &Generics) -> P<ast::Item> {
658661
let mut field_tys = Vec::new();
@@ -687,6 +690,7 @@ impl<'a> TraitDef<'a> {
687690
method_def.expand_enum_method_body(cx,
688691
self,
689692
enum_def,
693+
type_attrs,
690694
type_ident,
691695
self_args,
692696
&nonself_args[..])
@@ -706,6 +710,32 @@ impl<'a> TraitDef<'a> {
706710
}
707711
}
708712

713+
fn find_repr_type_name(diagnostic: &SpanHandler,
714+
type_attrs: &[ast::Attribute]) -> &'static str {
715+
let mut repr_type_name = "i32";
716+
for a in type_attrs {
717+
for r in &attr::find_repr_attrs(diagnostic, a) {
718+
repr_type_name = match *r {
719+
attr::ReprAny | attr::ReprPacked => continue,
720+
attr::ReprExtern => "i32",
721+
722+
attr::ReprInt(_, attr::SignedInt(ast::TyIs)) => "isize",
723+
attr::ReprInt(_, attr::SignedInt(ast::TyI8)) => "i8",
724+
attr::ReprInt(_, attr::SignedInt(ast::TyI16)) => "i16",
725+
attr::ReprInt(_, attr::SignedInt(ast::TyI32)) => "i32",
726+
attr::ReprInt(_, attr::SignedInt(ast::TyI64)) => "i64",
727+
728+
attr::ReprInt(_, attr::UnsignedInt(ast::TyUs)) => "usize",
729+
attr::ReprInt(_, attr::UnsignedInt(ast::TyU8)) => "u8",
730+
attr::ReprInt(_, attr::UnsignedInt(ast::TyU16)) => "u16",
731+
attr::ReprInt(_, attr::UnsignedInt(ast::TyU32)) => "u32",
732+
attr::ReprInt(_, attr::UnsignedInt(ast::TyU64)) => "u64",
733+
}
734+
}
735+
}
736+
repr_type_name
737+
}
738+
709739
impl<'a> MethodDef<'a> {
710740
fn call_substructure_method(&self,
711741
cx: &mut ExtCtxt,
@@ -974,12 +1004,13 @@ impl<'a> MethodDef<'a> {
9741004
cx: &mut ExtCtxt,
9751005
trait_: &TraitDef,
9761006
enum_def: &EnumDef,
1007+
type_attrs: &[ast::Attribute],
9771008
type_ident: Ident,
9781009
self_args: Vec<P<Expr>>,
9791010
nonself_args: &[P<Expr>])
9801011
-> P<Expr> {
9811012
self.build_enum_match_tuple(
982-
cx, trait_, enum_def, type_ident, self_args, nonself_args)
1013+
cx, trait_, enum_def, type_attrs, type_ident, self_args, nonself_args)
9831014
}
9841015

9851016

@@ -1013,6 +1044,7 @@ impl<'a> MethodDef<'a> {
10131044
cx: &mut ExtCtxt,
10141045
trait_: &TraitDef,
10151046
enum_def: &EnumDef,
1047+
type_attrs: &[ast::Attribute],
10161048
type_ident: Ident,
10171049
self_args: Vec<P<Expr>>,
10181050
nonself_args: &[P<Expr>]) -> P<Expr> {
@@ -1168,6 +1200,10 @@ impl<'a> MethodDef<'a> {
11681200
// std::intrinsics::discriminant_value(&__arg2) } as isize;
11691201
// ```
11701202
let mut index_let_stmts: Vec<P<ast::Stmt>> = Vec::new();
1203+
1204+
let target_type_name =
1205+
find_repr_type_name(&cx.parse_sess.span_diagnostic, type_attrs);
1206+
11711207
for (&ident, self_arg) in vi_idents.iter().zip(self_args.iter()) {
11721208
let path = vec![cx.ident_of_std("core"),
11731209
cx.ident_of("intrinsics"),
@@ -1181,18 +1217,7 @@ impl<'a> MethodDef<'a> {
11811217
rules: ast::UnsafeBlock(ast::CompilerGenerated),
11821218
span: sp }));
11831219

1184-
// FIXME: This unconditionally casts to `isize`. However:
1185-
//
1186-
// 1. On 32-bit platforms, that will truncate 64-bit enums
1187-
// that are making use of the upper 32 bits, and
1188-
//
1189-
// 2. On all platforms, it will misinterpret the sign bit
1190-
// of a 64-bit enum.
1191-
//
1192-
// What it should do is lookup whether the enum has an
1193-
// repr-attribute and cast to that if necessary. But
1194-
// attributes are not yet available to this function.
1195-
let target_ty = cx.ty_ident(sp, cx.ident_of("isize"));
1220+
let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name));
11961221
let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
11971222
let let_stmt = cx.stmt_let(sp, false, ident, variant_disr);
11981223
index_let_stmts.push(let_stmt);

0 commit comments

Comments
 (0)