mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-27 18:57:42 +03:00
document various traits
This commit is contained in:
@@ -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).
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>,
|
||||
|
||||
@@ -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>>,)+
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user