What is Rustc{Decodable,Encodable} and why is it stable/

I was browsing through the standard library docs to work on my implementation of rust (specifically in libcore), and I noticed the macro's core::RustcDecodable and core::RustcEncodable. These seemed afully suspicious, so I looked at their docs, and " Unstable implementation detail of the rustc compiler, do not use" is what it says.

My question is, is there a reason this is in libcore, and any reason it is not #[unstable(feature="rustc_<whatever>")] (and even if so, is there a reason it cannot be made unstable). The fact it's stable means it's technically part of the standard library, and I'd rather not implement a rustc implementation detail if I don't absolutely have to (aside from reasonable things that the implementation can make use of as well, such as lang items).

The TL;DR (from user standpoint) is that #[derive(RustcEncodable, RustcDecodable)] and rustc-serialize was a precursor to the serde serialization framework.

IIUC, at 1.0.0 these were widely used (and used by rustc) to support serialization, and there was no way to make them unstable. I still don't know whether the machinery for (derive) macros to be unstable is available yet, tbh. That said, #[derive(Encodable)] was available, deprecated, nominally stable, and theoretically usable up until 1.37 (it disappeared in 1.38), so there is precedent for removing these artifacts. That said, I'm kind of surprised that these aren't marked #[deprecated] yet.

You can see the implementation here: rustc_builtin_macros::deriving::encodable and rustc_builtin_macros::deriving::decodable

rustc_serialize is still used within rustc to implement persistence, IIUC.

Though I could not figure out how this is gated but they are not stable at that location and there is a test for that fact (sic! btw since it tests for RustcDecodable twice and does not test for RustcEncodable). However; huh

// Compiles fine.
use std::prelude::v1::RustcDecodable;

Also, just unprefixed use is stably accessible as well. #[derive(RustcEndocable, RustcDecodable)] has "worked"[1] on stable since 1.0.0.

[1]: expanded, anyway, and needs the crate rustc_serializable

Does it always require rustc_serializable, and is the crate stable? Yup, I missed that. It's on crates.io. Thank you rustc, very cool.

In any case, thank you rustc for leaving an implementation-detail public and stable. It seems like the best case is I define a macro that takes a tt, then throw #![__lccc::builtin_macro] on it, and make it expand to a compile error. Now I have to figure out how the heck the derive macro works.

The rustc-serialize currently used by rustc is quite different from the one on crates.io. While the exact traits that RustcEncodable and RustcDecodable derive are still compatible, the encoder/decoder interface is quite a bit different. In addition it is possible to specialize the Encodable and Decodable implementation on the specific encoder and decoder used.

1 Like

Honestly, unless one of your goals with lccc is to compile rustc, just ignore #[derive(RustcEndocable, RustcDecodable)]. I think everyone agrees that these aren't actually stably usable by consumers, even if rustc does label them as stable due to a historical quirk.

The nice thing to do would probably to be to provide a library derive macro at the exported path that always expands to an error.

3 Likes

Makes sense.

Compiling rustc would certainly be a good target, but to my knowledge rustc uses more than a few internal features, so unless and until that's fixed, it's probably a non-starter anyways.

I intend to modify crater (and have preemptively forked it for that purpose) to detect regressions from rustc to lccc when it is done. That being the case it's probably easier to write the macro to expand to a compile error, and then figure out the implementation if it causes legitimate problems in the field.