Use "bound" attribute instead of "where"

This commit is contained in:
David Tolnay 2016-06-05 10:47:40 -07:00
parent 45c51d3198
commit 578f34ecaf
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
5 changed files with 54 additions and 53 deletions

View File

@ -62,8 +62,8 @@ impl Name {
pub struct ContainerAttrs {
name: Name,
deny_unknown_fields: bool,
ser_where: Option<Vec<ast::WherePredicate>>,
de_where: Option<Vec<ast::WherePredicate>>,
ser_bound: Option<Vec<ast::WherePredicate>>,
de_bound: Option<Vec<ast::WherePredicate>>,
}
impl ContainerAttrs {
@ -72,8 +72,8 @@ impl ContainerAttrs {
let mut container_attrs = ContainerAttrs {
name: Name::new(item.ident),
deny_unknown_fields: false,
ser_where: None,
de_where: None,
ser_bound: None,
de_bound: None,
};
for meta_items in item.attrs().iter().filter_map(get_serde_meta_items) {
@ -100,18 +100,18 @@ impl ContainerAttrs {
container_attrs.deny_unknown_fields = true;
}
// Parse `#[serde(where="D: Serialize")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"where" => {
// Parse `#[serde(bound="D: Serialize")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => {
let where_predicates = try!(parse_lit_into_where(cx, name, lit));
container_attrs.ser_where = Some(where_predicates.clone());
container_attrs.de_where = Some(where_predicates.clone());
container_attrs.ser_bound = Some(where_predicates.clone());
container_attrs.de_bound = Some(where_predicates.clone());
}
// Parse `#[serde(where(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"where" => {
let (ser_where, de_where) = try!(get_where_predicates(cx, meta_items));
container_attrs.ser_where = ser_where;
container_attrs.de_where = de_where;
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
let (ser_bound, de_bound) = try!(get_where_predicates(cx, meta_items));
container_attrs.ser_bound = ser_bound;
container_attrs.de_bound = de_bound;
}
_ => {
@ -137,12 +137,12 @@ impl ContainerAttrs {
self.deny_unknown_fields
}
pub fn ser_where(&self) -> Option<&[ast::WherePredicate]> {
self.ser_where.as_ref().map(|vec| &vec[..])
pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_where(&self) -> Option<&[ast::WherePredicate]> {
self.de_where.as_ref().map(|vec| &vec[..])
pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
@ -207,8 +207,8 @@ pub struct FieldAttrs {
default_expr_if_missing: Option<P<ast::Expr>>,
serialize_with: Option<ast::Path>,
deserialize_with: Option<ast::Path>,
ser_where: Option<Vec<ast::WherePredicate>>,
de_where: Option<Vec<ast::WherePredicate>>,
ser_bound: Option<Vec<ast::WherePredicate>>,
de_bound: Option<Vec<ast::WherePredicate>>,
}
impl FieldAttrs {
@ -231,8 +231,8 @@ impl FieldAttrs {
default_expr_if_missing: None,
serialize_with: None,
deserialize_with: None,
ser_where: None,
de_where: None,
ser_bound: None,
de_bound: None,
};
for meta_items in field.attrs.iter().filter_map(get_serde_meta_items) {
@ -304,18 +304,18 @@ impl FieldAttrs {
field_attrs.deserialize_with = Some(path);
}
// Parse `#[serde(where="D: Serialize")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"where" => {
// Parse `#[serde(bound="D: Serialize")]`
ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"bound" => {
let where_predicates = try!(parse_lit_into_where(cx, name, lit));
field_attrs.ser_where = Some(where_predicates.clone());
field_attrs.de_where = Some(where_predicates.clone());
field_attrs.ser_bound = Some(where_predicates.clone());
field_attrs.de_bound = Some(where_predicates.clone());
}
// Parse `#[serde(where(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"where" => {
let (ser_where, de_where) = try!(get_where_predicates(cx, meta_items));
field_attrs.ser_where = ser_where;
field_attrs.de_where = de_where;
// Parse `#[serde(bound(serialize="D: Serialize", deserialize="D: Deserialize"))]`
ast::MetaItemKind::List(ref name, ref meta_items) if name == &"bound" => {
let (ser_bound, de_bound) = try!(get_where_predicates(cx, meta_items));
field_attrs.ser_bound = ser_bound;
field_attrs.de_bound = de_bound;
}
_ => {
@ -361,12 +361,12 @@ impl FieldAttrs {
self.deserialize_with.as_ref()
}
pub fn ser_where(&self) -> Option<&[ast::WherePredicate]> {
self.ser_where.as_ref().map(|vec| &vec[..])
pub fn ser_bound(&self) -> Option<&[ast::WherePredicate]> {
self.ser_bound.as_ref().map(|vec| &vec[..])
}
pub fn de_where(&self) -> Option<&[ast::WherePredicate]> {
self.de_where.as_ref().map(|vec| &vec[..])
pub fn de_bound(&self) -> Option<&[ast::WherePredicate]> {
self.de_bound.as_ref().map(|vec| &vec[..])
}
}
@ -434,7 +434,7 @@ fn get_where_predicates(
cx: &ExtCtxt,
items: &[P<ast::MetaItem>],
) -> Result<(Option<Vec<ast::WherePredicate>>, Option<Vec<ast::WherePredicate>>), Error> {
get_ser_and_de(cx, "where", items, parse_lit_into_where)
get_ser_and_de(cx, "bound", items, parse_lit_into_where)
}
pub fn get_serde_meta_items(attr: &ast::Attribute) -> Option<&[P<ast::MetaItem>]> {

View File

@ -168,15 +168,15 @@ fn contains_generic(ty: &ast::Ty, generics: &ast::Generics) -> bool {
// }
//
// This does not catch field types that are mutually recursive with some other
// type. For those, we require bounds to be specified by a `where` attribute if
// type. For those, we require bounds to be specified by a `bound` attribute if
// the inferred ones are not correct.
//
// struct Test<D> {
// #[serde(where="D: Serialize + Deserialize")]
// #[serde(bound="D: Serialize + Deserialize")]
// next: Box<Other<D>>,
// }
// struct Other<D> {
// #[serde(where="D: Serialize + Deserialize")]
// #[serde(bound="D: Serialize + Deserialize")]
// next: Box<Test<D>>,
// }
fn contains_recursion(ty: &ast::Ty, ident: ast::Ident) -> bool {

View File

@ -111,16 +111,16 @@ fn build_impl_generics(
let generics = try!(bound::with_where_predicates_from_fields(
cx, builder, item, &generics,
|attrs| attrs.de_where()));
|attrs| attrs.de_bound()));
match container_attrs.de_where() {
match container_attrs.de_bound() {
Some(predicates) => {
let generics = bound::with_where_predicates(builder, &generics, predicates);
Ok(generics)
}
None => {
let generics = try!(bound::with_bound(cx, builder, item, &generics,
deserialized_by_us,
needs_deserialize_bound,
&builder.path().ids(&["_serde", "de", "Deserialize"]).build()));
let generics = try!(bound::with_bound(cx, builder, item, &generics,
requires_default,
@ -131,12 +131,13 @@ fn build_impl_generics(
}
// Fields with a `skip_deserializing` or `deserialize_with` attribute are not
// deserialized by us. All other fields may need a `T: Deserialize` bound where
// T is the type of the field.
fn deserialized_by_us(_: &ast::StructField, attrs: &attr::FieldAttrs) -> bool {
// deserialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Deserialize` bound where T is the type of the field.
fn needs_deserialize_bound(_: &ast::StructField, attrs: &attr::FieldAttrs) -> bool {
!attrs.skip_deserializing_field()
&& attrs.deserialize_with().is_none()
&& attrs.de_where().is_none()
&& attrs.de_bound().is_none()
}
// Fields with a `default` attribute (not `default=...`), and fields with a

View File

@ -108,9 +108,9 @@ fn build_impl_generics(
let generics = try!(bound::with_where_predicates_from_fields(
cx, builder, item, &generics,
|attrs| attrs.ser_where()));
|attrs| attrs.ser_bound()));
match container_attrs.ser_where() {
match container_attrs.ser_bound() {
Some(predicates) => {
let generics = bound::with_where_predicates(builder, &generics, predicates);
Ok(generics)
@ -125,13 +125,13 @@ fn build_impl_generics(
}
// Fields with a `skip_serializing` or `serialize_with` attribute are not
// serialized by us so we do not generate a bound. Fields with a `where`
// serialized by us so we do not generate a bound. Fields with a `bound`
// attribute specify their own bound so we do not generate one. All other fields
// may need a `T: Serialize` bound where T is the type of the field.
fn needs_serialize_bound(_: &ast::StructField, attrs: &attr::FieldAttrs) -> bool {
!attrs.skip_serializing_field()
&& attrs.serialize_with().is_none()
&& attrs.ser_where().is_none()
&& attrs.ser_bound().is_none()
}
fn serialize_body(

View File

@ -92,19 +92,19 @@ struct ListNode<D> {
}
#[derive(Serialize, Deserialize)]
#[serde(where="D: SerializeWith + DeserializeWith")]
#[serde(bound="D: SerializeWith + DeserializeWith")]
struct WithTraits1<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with")]
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with",
where="E: SerializeWith + DeserializeWith")]
bound="E: SerializeWith + DeserializeWith")]
e: E,
}
#[derive(Serialize, Deserialize)]
#[serde(where(serialize="D: SerializeWith",
#[serde(bound(serialize="D: SerializeWith",
deserialize="D: DeserializeWith"))]
struct WithTraits2<D, E> {
#[serde(serialize_with="SerializeWith::serialize_with",
@ -112,7 +112,7 @@ struct WithTraits2<D, E> {
d: D,
#[serde(serialize_with="SerializeWith::serialize_with",
deserialize_with="DeserializeWith::deserialize_with",
where(serialize="E: SerializeWith",
bound(serialize="E: SerializeWith",
deserialize="E: DeserializeWith"))]
e: E,
}