From 413446b67a2bbe84da8562f35cc44dfa25313c31 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 6 Sep 2026 12:21:18 +0200 Subject: [PATCH] define metadata in terms of unsized tail to reduce redundancy --- src/dynamically-sized-types.md | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/dynamically-sized-types.md b/src/dynamically-sized-types.md index 52c7ac3f43..00efc51c65 100644 --- a/src/dynamically-sized-types.md +++ b/src/dynamically-sized-types.md @@ -8,10 +8,10 @@ r[dynamic-sized.restriction] Such types can only be used in certain cases: r[dynamic-sized.pointer-types] -* [Pointer types] to DSTs are sized but have twice the size of pointers to sized types, since they also store *metadata*: - * Pointers to slices store the number of elements; pointers to `str` store the length in bytes. - * Pointers to trait objects store a pointer to a vtable. - * Pointers to a struct or tuple with an [unsized tail] store the same metadata as a pointer to that tail. +* [Pointer types] to DSTs are sized but have twice the size of pointers to sized types, since they also store *metadata*. The type of the metadata depends on the type of the [unsized tail]: + * If the unsized tail is a slice, metadata stores the number of elements. + * If the unsized tail is a `str`, metadata stores the length in bytes. + * if the unsized tail is a trait object, metadata stores a pointer to a vtable. r[dynamic-sized.question-sized] * DSTs can be provided as type arguments to generic type parameters having the special `?Sized` bound. They can also be used for associated type definitions when the corresponding associated type declaration has a `?Sized` bound. By default, any type parameter or associated type has a `Sized` bound, unless it is relaxed using `?Sized`. @@ -27,7 +27,10 @@ r[dynamic-sized.struct-field] > [Variables], function parameters, [const] items, and [static] items must be `Sized`. r[dynamic-sized.tail] -The *unsized tail* of a type is the dynamically sized component that the [metadata] of a pointer to the type describes. A [slice] (`[T]`) and a [`str`] are each their own unsized tail, described by a length; a [trait object] (`dyn Trait`) is its own unsized tail, described by a pointer to a vtable. When a struct (per [dynamic-sized.struct-field]) or a tuple has an unsized last field, its unsized tail is the unsized tail of that field. A sized type has no unsized tail. +The *unsized tail* of a type is the dynamically sized component at the "end" of the type, after recursively descending through compound types: + - A [slice] (`[T]`), [`str`], and [trait object] (`dyn Trait`) are each their own unsized tail. + - When a struct (per [dynamic-sized.struct-field]) or a tuple has an unsized last field, its unsized tail is the unsized tail of that field. + - A sized type has no unsized tail. [metadata]: dynamic-sized.pointer-types [sized]: special-types-and-traits.md#sized