document various traits

This commit is contained in:
Jana Dönszelmann
2025-12-01 11:48:22 +01:00
parent fa5f075d1c
commit 8c7889bd18
6 changed files with 97 additions and 24 deletions
+67 -12
View File
@@ -72,25 +72,80 @@ pub fn extension(attr: TokenStream, input: TokenStream) -> TokenStream {
hash_stable::hash_stable_no_context_derive
);
decl_derive!([Decodable_NoContext] => serialize::decodable_nocontext_derive);
// Encoding and Decoding derives
decl_derive!([Decodable_NoContext] =>
/// See docs on derive [`Decodable`].
///
/// Derives `Decodable<D> for T where D: Decoder`.
serialize::decodable_nocontext_derive
);
decl_derive!([Encodable_NoContext] => serialize::encodable_nocontext_derive);
decl_derive!([Decodable] => serialize::decodable_derive);
decl_derive!([Decodable] =>
/// Derives `Decodable<D> for T where D: SpanDecoder`
///
/// # Deriving decoding traits
///
/// > Some shared docs about decoding traits, since this is likely the first trait you find
///
/// The difference between these derives can be subtle!
/// At a high level, there's the `T: Decodable<D>` trait that says some type `T`
/// can be decoded using a decoder `D`. There are various decoders!
/// The different derives place different *trait* bounds on this type `D`.
///
/// Even though this derive, based on its name, seems like the most vanilla one,
/// it actually places a pretty strict bound on `D`: `SpanDecoder`.
/// It means that types that derive this can contain spans, among other things,
/// and still be decoded. The reason this is hard is that at least in metadata,
/// spans can only be decoded later, once some information from the header
/// is already decoded to properly deal with spans.
///
/// The hierarchy is roughly:
///
/// - derive [`Decodable_NoContext`] is the most relaxed bounds that could be placed on `D`,
/// and is only really suited for structs and enums containing primitive types.
/// - derive [`BlobDecodable`] may be a better default, than deriving `Decodable`:
/// it places fewer requirements on `D`, while still allowing some complex types to be decoded.
/// - derive [`LazyDecodable`]: Only for types containing `Lazy{Array,Table,Value}`.
/// - derive [`Decodable`] for structures containing spans. Requires `D: SpanDecoder`
/// - derive [`TyDecodable`] for types that require access to the `TyCtxt` while decoding.
/// For example: arena allocated types.
serialize::decodable_derive
);
decl_derive!([Encodable] => serialize::encodable_derive);
decl_derive!([TyDecodable] => serialize::type_decodable_derive);
decl_derive!([TyDecodable] =>
/// See docs on derive [`Decodable`].
///
/// Derives `Decodable<D> for T where D: TyDecoder`.
serialize::type_decodable_derive
);
decl_derive!([TyEncodable] => serialize::type_encodable_derive);
decl_derive!([MetadataDecodable] =>
/// This constrains the decoder to be specifically the decoder that can decode LazyArrays in metadata.
/// Therefore, we only use this on things containing LazyArray really.
/// Anything else should either be `NoContext`, if possible `BlobDecodable`, or otherwise just `Decodable`.
serialize::meta_decodable_derive
decl_derive!([LazyDecodable] =>
/// See docs on derive [`Decodable`].
///
/// Derives `Decodable<D> for T where D: LazyDecoder`.
/// This constrains the decoder to be specifically the decoder that can decode
/// `LazyArray`s, `LazyValue`s amd `LazyTable`s in metadata.
/// Therefore, we only need this on things containing LazyArray really.
///
/// Most decodable derives mirror an encodable derive.
/// [`LazyDecodable`] and [`BlobDecodable`] together roughly mirror [`MetadataEncodable`]
serialize::lazy_decodable_derive
);
decl_derive!([BlobDecodable] =>
/// For anything that is "simple" to decode, without needing anything but the original data,
/// but for which the Decoder can customize some things
/// (unlike Decodable_NoContext which individual decoders can't customize).
/// See docs on derive [`Decodable`].
///
/// Derives `Decodable<D> for T where D: BlobDecoder`.
///
/// Most decodable derives mirror an encodable derive.
/// [`LazyDecodable`] and [`BlobDecodable`] together roughly mirror [`MetadataEncodable`]
serialize::blob_decodable_derive
);
decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive);
decl_derive!([MetadataEncodable] =>
/// Most encodable derives mirror a decodable derive.
/// [`MetadataEncodable`] is roughly mirrored by the combination of [`LazyDecodable`] and [`BlobDecodable`]
serialize::meta_encodable_derive
);
decl_derive!(
[TypeFoldable, attributes(type_foldable)] =>
/// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported).
+1 -1
View File
@@ -26,7 +26,7 @@ pub(super) fn blob_decodable_derive(
decodable_body(s, decoder_ty)
}
pub(super) fn meta_decodable_derive(
pub(super) fn lazy_decodable_derive(
mut s: synstructure::Structure<'_>,
) -> proc_macro2::TokenStream {
let decoder_ty = quote! { __D };
-1
View File
@@ -224,7 +224,6 @@
use rustc_data_structures::svh::Svh;
use rustc_errors::{DiagArgValue, IntoDiagArg};
use rustc_fs_util::try_canonicalize;
use rustc_middle::ty::TyCtxt;
use rustc_session::cstore::CrateSource;
use rustc_session::filesearch::FileSearch;
use rustc_session::search_paths::PathKind;
+9 -3
View File
@@ -155,15 +155,20 @@ struct ImportedSourceFile {
translated_source_file: Arc<rustc_span::SourceFile>,
}
/// Decode context used when we just have a blob,
/// and we still have to read the header etc.
/// Decode context used when we just have a blob of metadata from which we have to decode a header
/// and [`CrateRoot`]. After that, [`MetadataDecodeContext`] can be used.
/// Most notably, [`BlobDecodeContext]` doesn't implement [`SpanDecoder`]
pub(super) struct BlobDecodeContext<'a> {
opaque: MemDecoder<'a>,
blob: &'a MetadataBlob,
lazy_state: LazyState,
}
/// trait for anything containing `LazyState` and is a decoder.
/// This trait abstracts over decoders that can decode lazy values using [`LazyState`]:
///
/// - [`LazyValue`]
/// - [`LazyArray`]
/// - [`LazyTable`]
pub(super) trait LazyDecoder: BlobDecoder {
fn set_lazy_state(&mut self, state: LazyState);
fn get_lazy_state(&self) -> LazyState;
@@ -210,6 +215,7 @@ fn get_lazy_state(&self) -> LazyState {
/// This is the decode context used when crate metadata was already read.
/// Decoding of some types, like `Span` require some information to already been read.
/// Can be constructed from a [`TyCtxt`] and [`CrateMetadataRef`] (see the [`Metadata`] trait)
pub(super) struct MetadataDecodeContext<'a, 'tcx> {
blob_decoder: BlobDecodeContext<'a>,
cdata: CrateMetadataRef<'a>,
+6 -7
View File
@@ -19,8 +19,7 @@
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
use rustc_macros::{
BlobDecodable, Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable,
TyEncodable,
BlobDecodable, Decodable, Encodable, LazyDecodable, MetadataEncodable, TyDecodable, TyEncodable,
};
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
@@ -188,7 +187,7 @@ enum LazyState {
type ExpnDataTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnData>>>;
type ExpnHashTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnHash>>>;
#[derive(MetadataEncodable, MetadataDecodable)]
#[derive(MetadataEncodable, LazyDecodable)]
pub(crate) struct ProcMacroData {
proc_macro_decls_static: DefIndex,
stability: Option<hir::Stability>,
@@ -237,7 +236,7 @@ pub(crate) struct CrateHeader {
/// compilation session. If we were to serialize a proc-macro crate like
/// a normal crate, much of what we serialized would be unusable in addition
/// to being unused.
#[derive(MetadataEncodable, MetadataDecodable)]
#[derive(MetadataEncodable, LazyDecodable)]
pub(crate) struct CrateRoot {
/// A header used to detect if this is the right crate to load.
header: CrateHeader,
@@ -334,13 +333,13 @@ pub(crate) struct CrateDep {
pub is_private: bool,
}
#[derive(MetadataEncodable, MetadataDecodable)]
#[derive(MetadataEncodable, LazyDecodable)]
pub(crate) struct TraitImpls {
trait_id: (u32, DefIndex),
impls: LazyArray<(DefIndex, Option<SimplifiedType>)>,
}
#[derive(MetadataEncodable, MetadataDecodable)]
#[derive(MetadataEncodable, LazyDecodable)]
pub(crate) struct IncoherentImpls {
self_ty: LazyValue<SimplifiedType>,
impls: LazyArray<DefIndex>,
@@ -352,7 +351,7 @@ macro_rules! define_tables {
- defaulted: $($name1:ident: Table<$IDX1:ty, $T1:ty>,)+
- optional: $($name2:ident: Table<$IDX2:ty, $T2:ty>,)+
) => {
#[derive(MetadataEncodable, MetadataDecodable)]
#[derive(MetadataEncodable, LazyDecodable)]
pub(crate) struct LazyTables {
$($name1: LazyTable<$IDX1, $T1>,)+
$($name2: LazyTable<$IDX2, Option<$T2>>,)+
+14
View File
@@ -1304,6 +1304,20 @@ pub trait BlobDecoder: Decoder {
/// This trait is used to allow decoder specific encodings of certain types.
/// It is similar to rustc_type_ir's TyDecoder.
///
/// Specifically for metadata, an important note is that spans can only be decoded once
/// some other metadata is already read.
/// Spans have to be properly mapped into the decoding crate's sourcemap,
/// and crate numbers have to be converted sometimes.
/// This can only be done once the `CrateRoot` is available.
///
/// As such, some methods that used to be in the `SpanDecoder` trait
/// are now in the `BlobDecoder` trait. This hierarchy is not mirrored for `Encoder`s.
/// `BlobDecoder` has methods for deserializing types that are more complex than just those
/// that can be decoded with `Decoder`, but which can be decoded on their own, *before* any other metadata is.
/// Importantly, that means that types that can be decoded with `BlobDecoder` can show up in the crate root.
/// The place where this distinction is relevant is in `rustc_metadata` where metadata is decoded using either the
/// `MetadataDecodeContext` or the `BlobDecodeContext`.
pub trait SpanDecoder: BlobDecoder {
fn decode_span(&mut self) -> Span;
fn decode_expn_id(&mut self) -> ExpnId;