From 3af7ad5f422e0fa9511d34e111169ec2be2427c1 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 10 Apr 2015 19:00:38 +0200 Subject: [PATCH] Incorporate repr-attr into deriving(PartialOrd) to avoid truncation errors. --- src/libsyntax/ext/deriving/generic/mod.rs | 40 +++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index de77baa0ef21f..eb2cbe31480d0 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -201,6 +201,7 @@ use ext::base::ExtCtxt; use ext::build::AstBuilder; use codemap::{self, DUMMY_SP}; use codemap::Span; +use diagnostic::SpanHandler; use fold::MoveMap; use owned_slice::OwnedSlice; use parse::token::InternedString; @@ -391,6 +392,7 @@ impl<'a> TraitDef<'a> { ast::ItemEnum(ref enum_def, ref generics) => { self.expand_enum_def(cx, enum_def, + &item.attrs[..], item.ident, generics) } @@ -653,6 +655,7 @@ impl<'a> TraitDef<'a> { fn expand_enum_def(&self, cx: &mut ExtCtxt, enum_def: &EnumDef, + type_attrs: &[ast::Attribute], type_ident: Ident, generics: &Generics) -> P { let mut field_tys = Vec::new(); @@ -687,6 +690,7 @@ impl<'a> TraitDef<'a> { method_def.expand_enum_method_body(cx, self, enum_def, + type_attrs, type_ident, self_args, &nonself_args[..]) @@ -706,6 +710,32 @@ impl<'a> TraitDef<'a> { } } +fn find_repr_type_name(diagnostic: &SpanHandler, + type_attrs: &[ast::Attribute]) -> &'static str { + let mut repr_type_name = "i32"; + for a in type_attrs { + for r in &attr::find_repr_attrs(diagnostic, a) { + repr_type_name = match *r { + attr::ReprAny | attr::ReprPacked => continue, + attr::ReprExtern => "i32", + + attr::ReprInt(_, attr::SignedInt(ast::TyIs)) => "isize", + attr::ReprInt(_, attr::SignedInt(ast::TyI8)) => "i8", + attr::ReprInt(_, attr::SignedInt(ast::TyI16)) => "i16", + attr::ReprInt(_, attr::SignedInt(ast::TyI32)) => "i32", + attr::ReprInt(_, attr::SignedInt(ast::TyI64)) => "i64", + + attr::ReprInt(_, attr::UnsignedInt(ast::TyUs)) => "usize", + attr::ReprInt(_, attr::UnsignedInt(ast::TyU8)) => "u8", + attr::ReprInt(_, attr::UnsignedInt(ast::TyU16)) => "u16", + attr::ReprInt(_, attr::UnsignedInt(ast::TyU32)) => "u32", + attr::ReprInt(_, attr::UnsignedInt(ast::TyU64)) => "u64", + } + } + } + repr_type_name +} + impl<'a> MethodDef<'a> { fn call_substructure_method(&self, cx: &mut ExtCtxt, @@ -974,12 +1004,13 @@ impl<'a> MethodDef<'a> { cx: &mut ExtCtxt, trait_: &TraitDef, enum_def: &EnumDef, + type_attrs: &[ast::Attribute], type_ident: Ident, self_args: Vec>, nonself_args: &[P]) -> P { self.build_enum_match_tuple( - cx, trait_, enum_def, type_ident, self_args, nonself_args) + cx, trait_, enum_def, type_attrs, type_ident, self_args, nonself_args) } @@ -1013,6 +1044,7 @@ impl<'a> MethodDef<'a> { cx: &mut ExtCtxt, trait_: &TraitDef, enum_def: &EnumDef, + type_attrs: &[ast::Attribute], type_ident: Ident, self_args: Vec>, nonself_args: &[P]) -> P { @@ -1168,6 +1200,10 @@ impl<'a> MethodDef<'a> { // std::intrinsics::discriminant_value(&__arg2) } as isize; // ``` let mut index_let_stmts: Vec> = Vec::new(); + + let target_type_name = + find_repr_type_name(&cx.parse_sess.span_diagnostic, type_attrs); + for (&ident, self_arg) in vi_idents.iter().zip(self_args.iter()) { let path = vec![cx.ident_of_std("core"), cx.ident_of("intrinsics"), @@ -1192,7 +1228,7 @@ impl<'a> MethodDef<'a> { // What it should do is lookup whether the enum has an // repr-attribute and cast to that if necessary. But // attributes are not yet available to this function. - let target_ty = cx.ty_ident(sp, cx.ident_of("isize")); + let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name)); let variant_disr = cx.expr_cast(sp, variant_value, target_ty); let let_stmt = cx.stmt_let(sp, false, ident, variant_disr); index_let_stmts.push(let_stmt);