Skip to content

Commit 285c9b1

Browse files
committed
document various traits
1 parent 292f156 commit 285c9b1

File tree

5 files changed

+94
-23
lines changed

5 files changed

+94
-23
lines changed

compiler/rustc_macros/src/lib.rs

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,25 +72,77 @@ decl_derive!(
7272
hash_stable::hash_stable_no_context_derive
7373
);
7474

75-
decl_derive!([Decodable_NoContext] => serialize::decodable_nocontext_derive);
75+
// Encoding and Decoding derives
76+
decl_derive!([Decodable_NoContext] =>
77+
/// See docs on derive [`Decodable`].
78+
///
79+
/// Derives `Decodable<D> for T where D: Decoder`.
80+
serialize::decodable_nocontext_derive
81+
);
7682
decl_derive!([Encodable_NoContext] => serialize::encodable_nocontext_derive);
77-
decl_derive!([Decodable] => serialize::decodable_derive);
83+
decl_derive!([Decodable] =>
84+
/// Derives `Decodable<D> for T where D: SpanDecoder`
85+
///
86+
/// # Deriving decoding traits
87+
///
88+
/// > Some shared docs about decoding traits, since this is likely the first trait you find
89+
///
90+
/// The difference between theses derives can be subtle!
91+
/// At a high level, there's the `T: Decodable<D>` trait that says some type `T`
92+
/// can be decoded using a decoder `D`. There are various decoders!
93+
/// The different derives place different *trait* bounds on this type `D`.
94+
///
95+
/// Even though this derive, based on its name, seems like the most vanilla one,
96+
/// it actually places a pretty strict bound on `D`: `SpanDecoder`.
97+
/// It means that types that derive this can contain spans, among other things,
98+
/// and still be decoded. The reason this is hard is that at least in metadata,
99+
/// spoans can only be decoded later, once some information from the header
100+
/// is already decoded to properly deal with spans.
101+
///
102+
/// The hierarchy is roughly:
103+
///
104+
/// - derive [`Decodable_NoContext`] is the most relaxed bounds that could be placed on `D`,
105+
/// and is only really suited for structs and enums containing primitive types.
106+
/// - derive [`BlobDecodable`] may be a better default, than deriving `Decodable`:
107+
/// it places fewer requirements on `D`, while still allowing some complex types to be decoded.
108+
/// - derive [`LazyDecodable`]: Only for types containing `Lazy{Array,Table,Value}`.
109+
/// - derive [`Decodable`] for structures containing spans. Requires `D: SpanDecoder`
110+
/// - derive [`TyDecodable`] for types that require access to the `TyCtxt` while decoding.
111+
/// For example: arena allocated types.
112+
serialize::decodable_derive
113+
);
78114
decl_derive!([Encodable] => serialize::encodable_derive);
79-
decl_derive!([TyDecodable] => serialize::type_decodable_derive);
115+
decl_derive!([TyDecodable] =>
116+
/// See docs on derive [`Decodable`].
117+
///
118+
/// Derives `Decodable<D> for T where D: TyDecoder`.
119+
serialize::type_decodable_derive
120+
);
80121
decl_derive!([TyEncodable] => serialize::type_encodable_derive);
81-
decl_derive!([MetadataDecodable] =>
82-
/// This constrains the decoder to be specifically the decoder that can decode LazyArrays in metadata.
83-
/// Therefore, we only use this on things containing LazyArray really.
84-
/// Anything else should either be `NoContext`, if possible `BlobDecodable`, or otherwise just `Decodable`.
85-
serialize::meta_decodable_derive
122+
decl_derive!([LazyDecodable] =>
123+
/// See docs on derive [`Decodable`].
124+
///
125+
/// Derives `Decodable<D> for T where D: LazyDecoder`.
126+
/// This constrains the decoder to be specifically the decoder that can decode
127+
/// `LazyArray`s, `LazyValue`s amd `LazyTable`s in metadata.
128+
/// Therefore, we only need this on things containing LazyArray really.
129+
///
130+
/// Most decodable derives mirror an encodable derive.
131+
/// [`LazyDecodable`] and [`BlobDecodable`] together roughly mirror [`MetadataEncodable`]
132+
serialize::lazy_decodable_derive
86133
);
87134
decl_derive!([BlobDecodable] =>
88-
/// For anything that is "simple" to decode, without needing anything but the original data,
89-
/// but for which the Decoder can customize some things
90-
/// (unlike Decodable_NoContext which individual decoders can't customize).
135+
/// See docs on derive [`Decodable`].
136+
///
137+
/// Derives `Decodable<D> for T where D: BlobDecoder`.
91138
serialize::blob_decodable_derive
92139
);
93-
decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive);
140+
decl_derive!([MetadataEncodable] =>
141+
/// Most encodable derives mirror a decodable derive.
142+
/// [`MetadataEncodable`] is roughly mirrored by the combination of [`LazyDecodable`] and [`BlobDecodable`]
143+
serialize::meta_encodable_derive
144+
);
145+
94146
decl_derive!(
95147
[TypeFoldable, attributes(type_foldable)] =>
96148
/// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported).

compiler/rustc_macros/src/serialize.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub(super) fn blob_decodable_derive(
2626
decodable_body(s, decoder_ty)
2727
}
2828

29-
pub(super) fn meta_decodable_derive(
29+
pub(super) fn lazy_decodable_derive(
3030
mut s: synstructure::Structure<'_>,
3131
) -> proc_macro2::TokenStream {
3232
let decoder_ty = quote! { __D };

compiler/rustc_metadata/src/rmeta/decoder.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,20 @@ struct ImportedSourceFile {
155155
translated_source_file: Arc<rustc_span::SourceFile>,
156156
}
157157

158-
/// Decode context used when we just have a blob,
159-
/// and we still have to read the header etc.
158+
/// Decode context used when we just have a blob of metadata from which we have to decode a header
159+
/// and [`CrateRoot`]. After that, [`MetadataDecodeContext`] can be used.
160+
/// Most notably, [`BlobDecodeContext]` doesn't implement [`SpanDecoder`]
160161
pub(super) struct BlobDecodeContext<'a> {
161162
opaque: MemDecoder<'a>,
162163
blob: &'a MetadataBlob,
163164
lazy_state: LazyState,
164165
}
165166

166-
/// trait for anything containing `LazyState` and is a decoder.
167+
/// This trait abstracts over decoders that can decode lazy values using [`LazyState`]:
168+
///
169+
/// - [`LazyValue`]
170+
/// - [`LazyArray`]
171+
/// - [`LazyTable`]
167172
pub(super) trait LazyDecoder: BlobDecoder {
168173
fn set_lazy_state(&mut self, state: LazyState);
169174
fn get_lazy_state(&self) -> LazyState;
@@ -210,6 +215,7 @@ impl<'a> LazyDecoder for BlobDecodeContext<'a> {
210215

211216
/// This is the decode context used when crate metadata was already read.
212217
/// Decoding of some types, like `Span` require some information to already been read.
218+
/// Can be constructed from a [`TyCtxt`] and [`CrateMetadataRef`] (see the [`Metadata`] trait)
213219
pub(super) struct MetadataDecodeContext<'a, 'tcx> {
214220
blob_decoder: BlobDecodeContext<'a>,
215221
cdata: CrateMetadataRef<'a>,

compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ use rustc_hir::{PreciseCapturingArgKind, attrs};
1919
use rustc_index::IndexVec;
2020
use rustc_index::bit_set::DenseBitSet;
2121
use rustc_macros::{
22-
BlobDecodable, Decodable, Encodable, MetadataDecodable, MetadataEncodable, TyDecodable,
23-
TyEncodable,
22+
BlobDecodable, Decodable, Encodable, LazyDecodable, MetadataEncodable, TyDecodable, TyEncodable,
2423
};
2524
use rustc_middle::metadata::ModChild;
2625
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
@@ -188,7 +187,7 @@ type SyntaxContextTable = LazyTable<u32, Option<LazyValue<SyntaxContextKey>>>;
188187
type ExpnDataTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnData>>>;
189188
type ExpnHashTable = LazyTable<ExpnIndex, Option<LazyValue<ExpnHash>>>;
190189

191-
#[derive(MetadataEncodable, MetadataDecodable)]
190+
#[derive(MetadataEncodable, LazyDecodable)]
192191
pub(crate) struct ProcMacroData {
193192
proc_macro_decls_static: DefIndex,
194193
stability: Option<hir::Stability>,
@@ -237,7 +236,7 @@ pub(crate) struct CrateHeader {
237236
/// compilation session. If we were to serialize a proc-macro crate like
238237
/// a normal crate, much of what we serialized would be unusable in addition
239238
/// to being unused.
240-
#[derive(MetadataEncodable, MetadataDecodable)]
239+
#[derive(MetadataEncodable, LazyDecodable)]
241240
pub(crate) struct CrateRoot {
242241
/// A header used to detect if this is the right crate to load.
243242
header: CrateHeader,
@@ -334,13 +333,13 @@ pub(crate) struct CrateDep {
334333
pub is_private: bool,
335334
}
336335

337-
#[derive(MetadataEncodable, MetadataDecodable)]
336+
#[derive(MetadataEncodable, LazyDecodable)]
338337
pub(crate) struct TraitImpls {
339338
trait_id: (u32, DefIndex),
340339
impls: LazyArray<(DefIndex, Option<SimplifiedType>)>,
341340
}
342341

343-
#[derive(MetadataEncodable, MetadataDecodable)]
342+
#[derive(MetadataEncodable, LazyDecodable)]
344343
pub(crate) struct IncoherentImpls {
345344
self_ty: LazyValue<SimplifiedType>,
346345
impls: LazyArray<DefIndex>,
@@ -352,7 +351,7 @@ macro_rules! define_tables {
352351
- defaulted: $($name1:ident: Table<$IDX1:ty, $T1:ty>,)+
353352
- optional: $($name2:ident: Table<$IDX2:ty, $T2:ty>,)+
354353
) => {
355-
#[derive(MetadataEncodable, MetadataDecodable)]
354+
#[derive(MetadataEncodable, LazyDecodable)]
356355
pub(crate) struct LazyTables {
357356
$($name1: LazyTable<$IDX1, $T1>,)+
358357
$($name2: LazyTable<$IDX2, Option<$T2>>,)+

compiler/rustc_span/src/lib.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1304,6 +1304,20 @@ pub trait BlobDecoder: Decoder {
13041304

13051305
/// This trait is used to allow decoder specific encodings of certain types.
13061306
/// It is similar to rustc_type_ir's TyDecoder.
1307+
///
1308+
/// Specifically for metadata, an important note is that spans can only be decoded once
1309+
/// some other metadata is already read.
1310+
/// Spans have to be properly mapped into the decoding crate's sourcemap,
1311+
/// and crate numbers have to be converted sometimes.
1312+
/// This can only be done once the `CrateRoot` is available.
1313+
///
1314+
/// As such, some methods that used to be in the `SpanDecoder` trait
1315+
/// are now in the `BlobDecoder` trait. This hierarchy is not mirrored for `Encoder`s.
1316+
/// `BlobDecoder` has methods for deserializing types that are more complex than just those
1317+
/// that can be decoded with `Decoder`, but which can be decoded on their own, *before* any other metadata is.
1318+
/// Importantly, that means that types that can be decoded with `BlobDecoder` can show up in the crate root.
1319+
/// The place where this distinction is relevant is in `rustc_metadata` where metadata is decoded using either the
1320+
/// `MetadataDecodeContext` or the `BlobDecodeContext`.
13071321
pub trait SpanDecoder: BlobDecoder {
13081322
fn decode_span(&mut self) -> Span;
13091323
fn decode_expn_id(&mut self) -> ExpnId;

0 commit comments

Comments
 (0)