diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 9a2560b0458..3e523fca92a 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -788,6 +788,11 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { is just used for rustc unit tests \ and will never be stable", cfg_fn!(rustc_attrs))), + ("rustc_serialize_exclude_null", Normal, Gated(Stability::Unstable, + "rustc_attrs", + "the `#[rustc_serialize_exclude_null]` attribute \ + is an internal-only feature", + cfg_fn!(rustc_attrs))), ("rustc_synthetic", Whitelisted, Gated(Stability::Unstable, "rustc_attrs", "this attribute \ diff --git a/src/libsyntax/json.rs b/src/libsyntax/json.rs index 7a8717ada4c..681e14a6137 100644 --- a/src/libsyntax/json.rs +++ b/src/libsyntax/json.rs @@ -108,6 +108,7 @@ struct Diagnostic { } #[derive(RustcEncodable)] +#[allow(unused_attributes)] struct DiagnosticSpan { file_name: String, byte_start: u32, @@ -129,6 +130,7 @@ struct DiagnosticSpan { /// that should be sliced in atop this span. suggested_replacement: Option, /// If the suggestion is approximate + #[rustc_serialize_exclude_null] suggestion_approximate: Option, /// Macro invocations that created the code at this span, if any. expansion: Option>, diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 3b4c5da10f2..9181cca215c 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -25,6 +25,7 @@ #![feature(match_default_bindings)] #![feature(i128_type)] #![feature(const_atomic_usize_new)] +#![feature(rustc_attrs)] // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] diff --git a/src/libsyntax_ext/deriving/encodable.rs b/src/libsyntax_ext/deriving/encodable.rs index 0e6e96438d8..743f22b6b31 100644 --- a/src/libsyntax_ext/deriving/encodable.rs +++ b/src/libsyntax_ext/deriving/encodable.rs @@ -190,7 +190,7 @@ fn encodable_substructure(cx: &mut ExtCtxt, Struct(_, ref fields) => { let emit_struct_field = cx.ident_of("emit_struct_field"); let mut stmts = Vec::new(); - for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() { + for (i, &FieldInfo { name, ref self_, span, attrs, .. }) in fields.iter().enumerate() { let name = match name { Some(id) => id.name, None => Symbol::intern(&format!("_field{}", i)), @@ -212,7 +212,19 @@ fn encodable_substructure(cx: &mut ExtCtxt, } else { cx.expr(span, ExprKind::Ret(Some(call))) }; - stmts.push(cx.stmt_expr(call)); + + // This exists for https://github.com/rust-lang/rust/pull/47540 + // + // If we decide to stabilize that flag this can be removed + let expr = if attrs.iter().any(|a| a.check_name("rustc_serialize_exclude_null")) { + let is_some = cx.ident_of("is_some"); + let condition = cx.expr_method_call(span, self_.clone(), is_some, vec![]); + cx.expr_if(span, condition, call, None) + } else { + call + }; + let stmt = cx.stmt_expr(expr); + stmts.push(stmt); } // unit structs have no fields and need to return Ok()