Skip to content

Commit dc0c0dc

Browse files
authored
Merge pull request #2079 from dtolnay/packedremote
Fix unaligned reference warnings on packed remote def
2 parents 55fdbea + 54102ee commit dc0c0dc

File tree

4 files changed

+35
-9
lines changed

4 files changed

+35
-9
lines changed

serde_derive/src/de.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ pub fn expand_derive_deserialize(
3636

3737
let impl_block = if let Some(remote) = cont.attrs.remote() {
3838
let vis = &input.vis;
39-
let used = pretend::pretend_used(&cont);
39+
let used = pretend::pretend_used(&cont, params.is_packed);
4040
quote! {
4141
impl #de_impl_generics #ident #ty_generics #where_clause {
4242
#vis fn deserialize<__D>(__deserializer: __D) -> #serde::__private::Result<#remote #ty_generics, __D::Error>
@@ -125,6 +125,9 @@ struct Parameters {
125125
/// At least one field has a serde(getter) attribute, implying that the
126126
/// remote type has a private field.
127127
has_getter: bool,
128+
129+
/// Type has a repr(packed) attribute.
130+
is_packed: bool,
128131
}
129132

130133
impl Parameters {
@@ -137,13 +140,15 @@ impl Parameters {
137140
let borrowed = borrowed_lifetimes(cont);
138141
let generics = build_generics(cont, &borrowed);
139142
let has_getter = cont.data.has_getter();
143+
let is_packed = cont.attrs.is_packed();
140144

141145
Parameters {
142146
local,
143147
this,
144148
generics,
145149
borrowed,
146150
has_getter,
151+
is_packed,
147152
}
148153
}
149154

serde_derive/src/pretend.rs

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use internals::ast::{Container, Data, Field, Style};
2020
// 8 | enum EnumDef { V }
2121
// | ^
2222
//
23-
pub fn pretend_used(cont: &Container) -> TokenStream {
24-
let pretend_fields = pretend_fields_used(cont);
23+
pub fn pretend_used(cont: &Container, is_packed: bool) -> TokenStream {
24+
let pretend_fields = pretend_fields_used(cont, is_packed);
2525
let pretend_variants = pretend_variants_used(cont);
2626

2727
quote! {
@@ -48,7 +48,7 @@ pub fn pretend_used(cont: &Container) -> TokenStream {
4848
// The `ref` is important in case the user has written a Drop impl on their
4949
// type. Rust does not allow destructuring a struct or enum that has a Drop
5050
// impl.
51-
fn pretend_fields_used(cont: &Container) -> TokenStream {
51+
fn pretend_fields_used(cont: &Container, is_packed: bool) -> TokenStream {
5252
let type_ident = &cont.ident;
5353
let (_, ty_generics, _) = cont.generics.split_for_impl();
5454

@@ -58,14 +58,14 @@ fn pretend_fields_used(cont: &Container) -> TokenStream {
5858
.filter_map(|variant| match variant.style {
5959
Style::Struct => {
6060
let variant_ident = &variant.ident;
61-
let pat = struct_pattern(&variant.fields);
61+
let pat = struct_pattern(&variant.fields, is_packed);
6262
Some(quote!(#type_ident::#variant_ident #pat))
6363
}
6464
_ => None,
6565
})
6666
.collect::<Vec<_>>(),
6767
Data::Struct(Style::Struct, fields) => {
68-
let pat = struct_pattern(fields);
68+
let pat = struct_pattern(fields, is_packed);
6969
vec![quote!(#type_ident #pat)]
7070
}
7171
Data::Struct(_, _) => {
@@ -132,9 +132,14 @@ fn pretend_variants_used(cont: &Container) -> TokenStream {
132132
quote!(#(#cases)*)
133133
}
134134

135-
fn struct_pattern(fields: &[Field]) -> TokenStream {
135+
fn struct_pattern(fields: &[Field], is_packed: bool) -> TokenStream {
136136
let members = fields.iter().map(|field| &field.member);
137137
let placeholders =
138138
(0..fields.len()).map(|i| Ident::new(&format!("__v{}", i), Span::call_site()));
139-
quote!({ #(#members: ref #placeholders),* })
139+
let take_reference = if is_packed {
140+
None
141+
} else {
142+
Some(quote!(ref))
143+
};
144+
quote!({ #(#members: #take_reference #placeholders),* })
140145
}

serde_derive/src/ser.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub fn expand_derive_serialize(
3030

3131
let impl_block = if let Some(remote) = cont.attrs.remote() {
3232
let vis = &input.vis;
33-
let used = pretend::pretend_used(&cont);
33+
let used = pretend::pretend_used(&cont, params.is_packed);
3434
quote! {
3535
impl #impl_generics #ident #ty_generics #where_clause {
3636
#vis fn serialize<__S>(__self: &#remote #ty_generics, __serializer: __S) -> #serde::__private::Result<__S::Ok, __S::Error>

test_suite/tests/test_gen.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,3 +846,19 @@ where
846846
{
847847
T::deserialize(deserializer)
848848
}
849+
850+
//////////////////////////////////////////////////////////////////////////
851+
852+
#[repr(packed)]
853+
pub struct RemotePacked {
854+
pub a: u8,
855+
pub b: u16,
856+
}
857+
858+
#[derive(Serialize, Deserialize)]
859+
#[repr(packed)]
860+
#[serde(remote = "RemotePacked")]
861+
pub struct RemotePackedDef {
862+
a: u8,
863+
b: u16,
864+
}

0 commit comments

Comments
 (0)