@@ -393,34 +393,47 @@ fn find_type_parameters(ty: &ast::Ty,
393
393
}
394
394
395
395
impl < ' a > TraitDef < ' a > {
396
- pub fn expand ( & self ,
396
+ pub fn expand ( self ,
397
397
cx : & mut ExtCtxt ,
398
398
mitem : & ast:: MetaItem ,
399
399
item : & ' a Annotatable ,
400
400
push : & mut FnMut ( Annotatable ) ) {
401
401
self . expand_ext ( cx, mitem, item, push, false ) ;
402
402
}
403
403
404
- pub fn expand_ext ( & self ,
404
+ pub fn expand_ext ( self ,
405
405
cx : & mut ExtCtxt ,
406
406
mitem : & ast:: MetaItem ,
407
407
item : & ' a Annotatable ,
408
408
push : & mut FnMut ( Annotatable ) ,
409
409
from_scratch : bool ) {
410
410
match * item {
411
411
Annotatable :: Item ( ref item) => {
412
+ let is_packed = item. attrs . iter ( ) . any ( |attr| {
413
+ attr:: find_repr_attrs ( & cx. parse_sess . span_diagnostic , attr)
414
+ . contains ( & attr:: ReprPacked )
415
+ } ) ;
416
+ let use_temporaries = is_packed;
412
417
let newitem = match item. node {
413
418
ast:: ItemKind :: Struct ( ref struct_def, ref generics) => {
414
- self . expand_struct_def ( cx, & struct_def, item. ident , generics, from_scratch)
419
+ self . expand_struct_def ( cx, & struct_def, item. ident , generics, from_scratch,
420
+ use_temporaries)
415
421
}
416
422
ast:: ItemKind :: Enum ( ref enum_def, ref generics) => {
423
+ // We ignore `use_temporaries` here, because
424
+ // `repr(packed)` enums cause an error later on.
425
+ //
426
+ // This can only cause further compilation errors
427
+ // downstream in blatantly illegal code, so it
428
+ // is fine.
417
429
self . expand_enum_def ( cx, enum_def, & item. attrs ,
418
430
item. ident , generics, from_scratch)
419
431
}
420
432
ast:: ItemKind :: Union ( ref struct_def, ref generics) => {
421
433
if self . supports_unions {
422
434
self . expand_struct_def ( cx, & struct_def, item. ident ,
423
- generics, from_scratch)
435
+ generics, from_scratch,
436
+ use_temporaries)
424
437
} else {
425
438
cx. span_err ( mitem. span ,
426
439
"this trait cannot be derived for unions" ) ;
@@ -675,7 +688,8 @@ impl<'a> TraitDef<'a> {
675
688
struct_def : & ' a VariantData ,
676
689
type_ident : Ident ,
677
690
generics : & Generics ,
678
- from_scratch : bool )
691
+ from_scratch : bool ,
692
+ use_temporaries : bool )
679
693
-> P < ast:: Item > {
680
694
let field_tys: Vec < P < ast:: Ty > > = struct_def. fields ( )
681
695
. iter ( )
@@ -701,7 +715,8 @@ impl<'a> TraitDef<'a> {
701
715
struct_def,
702
716
type_ident,
703
717
& self_args[ ..] ,
704
- & nonself_args[ ..] )
718
+ & nonself_args[ ..] ,
719
+ use_temporaries)
705
720
} ;
706
721
707
722
method_def. create_method ( cx,
@@ -958,14 +973,31 @@ impl<'a> MethodDef<'a> {
958
973
/// }
959
974
/// }
960
975
/// }
976
+ ///
977
+ /// // or if A is repr(packed) - note fields are matched by-value
978
+ /// // instead of by-reference.
979
+ /// impl PartialEq for A {
980
+ /// fn eq(&self, __arg_1: &A) -> bool {
981
+ /// match *self {
982
+ /// A {x: __self_0_0, y: __self_0_1} => {
983
+ /// match __arg_1 {
984
+ /// A {x: __self_1_0, y: __self_1_1} => {
985
+ /// __self_0_0.eq(&__self_1_0) && __self_0_1.eq(&__self_1_1)
986
+ /// }
987
+ /// }
988
+ /// }
989
+ /// }
990
+ /// }
991
+ /// }
961
992
/// ```
962
993
fn expand_struct_method_body < ' b > ( & self ,
963
994
cx : & mut ExtCtxt ,
964
995
trait_ : & TraitDef < ' b > ,
965
996
struct_def : & ' b VariantData ,
966
997
type_ident : Ident ,
967
998
self_args : & [ P < Expr > ] ,
968
- nonself_args : & [ P < Expr > ] )
999
+ nonself_args : & [ P < Expr > ] ,
1000
+ use_temporaries : bool )
969
1001
-> P < Expr > {
970
1002
971
1003
let mut raw_fields = Vec :: new ( ) ; // Vec<[fields of self],
@@ -977,7 +1009,8 @@ impl<'a> MethodDef<'a> {
977
1009
struct_path,
978
1010
struct_def,
979
1011
& format ! ( "__self_{}" , i) ,
980
- ast:: Mutability :: Immutable ) ;
1012
+ ast:: Mutability :: Immutable ,
1013
+ use_temporaries) ;
981
1014
patterns. push ( pat) ;
982
1015
raw_fields. push ( ident_expr) ;
983
1016
}
@@ -1140,7 +1173,6 @@ impl<'a> MethodDef<'a> {
1140
1173
self_args : Vec < P < Expr > > ,
1141
1174
nonself_args : & [ P < Expr > ] )
1142
1175
-> P < Expr > {
1143
-
1144
1176
let sp = trait_. span ;
1145
1177
let variants = & enum_def. variants ;
1146
1178
@@ -1512,12 +1544,18 @@ impl<'a> TraitDef<'a> {
1512
1544
fn create_subpatterns ( & self ,
1513
1545
cx : & mut ExtCtxt ,
1514
1546
field_paths : Vec < ast:: SpannedIdent > ,
1515
- mutbl : ast:: Mutability )
1547
+ mutbl : ast:: Mutability ,
1548
+ use_temporaries : bool )
1516
1549
-> Vec < P < ast:: Pat > > {
1517
1550
field_paths. iter ( )
1518
1551
. map ( |path| {
1552
+ let binding_mode = if use_temporaries {
1553
+ ast:: BindingMode :: ByValue ( ast:: Mutability :: Immutable )
1554
+ } else {
1555
+ ast:: BindingMode :: ByRef ( mutbl)
1556
+ } ;
1519
1557
cx. pat ( path. span ,
1520
- PatKind :: Ident ( ast :: BindingMode :: ByRef ( mutbl ) , ( * path) . clone ( ) , None ) )
1558
+ PatKind :: Ident ( binding_mode , ( * path) . clone ( ) , None ) )
1521
1559
} )
1522
1560
. collect ( )
1523
1561
}
@@ -1528,8 +1566,10 @@ impl<'a> TraitDef<'a> {
1528
1566
struct_path : ast:: Path ,
1529
1567
struct_def : & ' a VariantData ,
1530
1568
prefix : & str ,
1531
- mutbl : ast:: Mutability )
1532
- -> ( P < ast:: Pat > , Vec < ( Span , Option < Ident > , P < Expr > , & ' a [ ast:: Attribute ] ) > ) {
1569
+ mutbl : ast:: Mutability ,
1570
+ use_temporaries : bool )
1571
+ -> ( P < ast:: Pat > , Vec < ( Span , Option < Ident > , P < Expr > , & ' a [ ast:: Attribute ] ) > )
1572
+ {
1533
1573
let mut paths = Vec :: new ( ) ;
1534
1574
let mut ident_exprs = Vec :: new ( ) ;
1535
1575
for ( i, struct_field) in struct_def. fields ( ) . iter ( ) . enumerate ( ) {
@@ -1539,12 +1579,18 @@ impl<'a> TraitDef<'a> {
1539
1579
span : sp,
1540
1580
node : ident,
1541
1581
} ) ;
1542
- let val = cx. expr_deref ( sp, cx. expr_path ( cx. path_ident ( sp, ident) ) ) ;
1582
+ let val = cx. expr_path ( cx. path_ident ( sp, ident) ) ;
1583
+ let val = if use_temporaries {
1584
+ val
1585
+ } else {
1586
+ cx. expr_deref ( sp, val)
1587
+ } ;
1543
1588
let val = cx. expr ( sp, ast:: ExprKind :: Paren ( val) ) ;
1589
+
1544
1590
ident_exprs. push ( ( sp, struct_field. ident , val, & struct_field. attrs [ ..] ) ) ;
1545
1591
}
1546
1592
1547
- let subpats = self . create_subpatterns ( cx, paths, mutbl) ;
1593
+ let subpats = self . create_subpatterns ( cx, paths, mutbl, use_temporaries ) ;
1548
1594
let pattern = match * struct_def {
1549
1595
VariantData :: Struct ( ..) => {
1550
1596
let field_pats = subpats. into_iter ( )
@@ -1588,7 +1634,9 @@ impl<'a> TraitDef<'a> {
1588
1634
let variant_ident = variant. node . name ;
1589
1635
let sp = variant. span . with_ctxt ( self . span . ctxt ( ) ) ;
1590
1636
let variant_path = cx. path ( sp, vec ! [ enum_ident, variant_ident] ) ;
1591
- self . create_struct_pattern ( cx, variant_path, & variant. node . data , prefix, mutbl)
1637
+ let use_temporaries = false ; // enums can't be repr(packed)
1638
+ self . create_struct_pattern ( cx, variant_path, & variant. node . data , prefix, mutbl,
1639
+ use_temporaries)
1592
1640
}
1593
1641
}
1594
1642
0 commit comments