Skip to content

Commit f3b3162

Browse files
committed
Add a dedicated chapter for generic types
This is only a bare-bones skeleton. The intent is that this should get filled out with more rules specific to generic types.
1 parent 6fbd064 commit f3b3162

3 files changed

Lines changed: 64 additions & 1 deletion

File tree

src/SUMMARY.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
- [Inferred type](types/inferred.md)
9595
- [Generics](types/generics/index.md)
9696
- [Generic lifetimes](types/generics/lifetimes.md)
97+
- [Generic types](types/generics/types.md)
9798
- [Generic constants](types/generics/constants.md)
9899
- [Dynamically sized types](dynamically-sized-types.md)
99100
- [Type layout](type-layout.md)

src/types/generics/index.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ r[generics]
22
# Generics
33

44
r[generics.intro]
5-
Generics allow items to be parameterized by types, [lifetimes], and [constants]. This allows definitions to be written in a flexible way that can be reused with different concrete types and values.
5+
Generics allow items to be parameterized by [types], [lifetimes], and [constants]. This allows definitions to be written in a flexible way that can be reused with different concrete types and values.
66

77
r[generics.parameters]
88
## Generic parameters
@@ -368,4 +368,5 @@ The [built-in attributes] that have meaning on a generic parameter are [`cfg`] a
368368
[tuples]: type.tuple
369369
[turbofish]: paths.expr.turbofish
370370
[type aliases]: items.type
371+
[types]: generics.types
371372
[unions]: items.union

src/types/generics/types.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
r[generics.types]
2+
# Generic types
3+
4+
r[generics.types.intro]
5+
A *type parameter* is a generic parameter for a type.
6+
7+
r[generics.types.at-least-once]
8+
[Structs], [enumerations], and [unions] must use each of their type parameters at least once in their fields or variants.
9+
10+
> [!EXAMPLE]
11+
> ```rust,compile_fail
12+
> // ERROR: type parameter `T` is never used
13+
> struct Unused<T>;
14+
>
15+
> // ERROR: type parameter `T` is never used
16+
> enum Empty<T> { A }
17+
> ```
18+
>
19+
> ```rust
20+
> // OK: `T` appears in a field.
21+
> struct Wrapper<T>(T);
22+
>
23+
> // A type parameter that does not appear directly in any field may be used
24+
> // via `std::marker::PhantomData`.
25+
> struct Key<T> {
26+
> id: u64,
27+
> _phantom: std::marker::PhantomData<T>,
28+
> }
29+
> ```
30+
31+
r[generics.types.sized]
32+
Unless the `?Sized` [opt-out bound][`Sized`] is present, a type parameter has an implicit [`Sized`] bound. This means the concrete type supplied for the parameter must have a size known at compile time.
33+
34+
> [!EXAMPLE]
35+
> ```rust
36+
> // `T` implicitly requires `T: Sized`.
37+
> fn takes_sized<T>(x: T) {}
38+
>
39+
> // `T` may be a dynamically sized type.
40+
> fn takes_unsized<T: ?Sized>(x: &T) {}
41+
> ```
42+
43+
r[generics.types.default-constraint]
44+
The default type of a type parameter must satisfy all of the type parameter's [trait bounds].
45+
46+
> [!EXAMPLE]
47+
> ```rust,compile_fail
48+
> // ERROR: the default type `String` does not implement `Copy`
49+
> struct Foo<T: Copy = String>(T);
50+
> ```
51+
>
52+
> ```rust
53+
> // OK: `i32` satisfies the `Copy` bound
54+
> struct Bar<T: Copy = i32>(T);
55+
> ```
56+
57+
[enumerations]: items.enum
58+
[structs]: items.struct
59+
[trait]: items.traits
60+
[trait bounds]: bound
61+
[unions]: items.union

0 commit comments

Comments
 (0)