core/ops/
index.rs

1/// Used for indexing operations (`container[index]`) in immutable contexts.
2///
3/// `container[index]` is actually syntactic sugar for `*container.index(index)`,
4/// but only when used as an immutable value. If a mutable value is requested,
5/// [`IndexMut`] is used instead. This allows nice things such as
6/// `let value = v[index]` if the type of `value` implements [`Copy`].
7///
8/// # Examples
9///
10/// The following example implements `Index` on a read-only `NucleotideCount`
11/// container, enabling individual counts to be retrieved with index syntax.
12///
13/// ```
14/// use std::ops::Index;
15///
16/// enum Nucleotide {
17///     A,
18///     C,
19///     G,
20///     T,
21/// }
22///
23/// struct NucleotideCount {
24///     a: usize,
25///     c: usize,
26///     g: usize,
27///     t: usize,
28/// }
29///
30/// impl Index<Nucleotide> for NucleotideCount {
31///     type Output = usize;
32///
33///     fn index(&self, nucleotide: Nucleotide) -> &Self::Output {
34///         match nucleotide {
35///             Nucleotide::A => &self.a,
36///             Nucleotide::C => &self.c,
37///             Nucleotide::G => &self.g,
38///             Nucleotide::T => &self.t,
39///         }
40///     }
41/// }
42///
43/// let nucleotide_count = NucleotideCount {a: 14, c: 9, g: 10, t: 12};
44/// assert_eq!(nucleotide_count[Nucleotide::A], 14);
45/// assert_eq!(nucleotide_count[Nucleotide::C], 9);
46/// assert_eq!(nucleotide_count[Nucleotide::G], 10);
47/// assert_eq!(nucleotide_count[Nucleotide::T], 12);
48/// ```
49#[lang = "index"]
50#[diagnostic::on_unimplemented(
51    message = "the type `{Self}` cannot be indexed by `{Idx}`",
52    label = "`{Self}` cannot be indexed by `{Idx}`"
53)]
54#[stable(feature = "rust1", since = "1.0.0")]
55#[doc(alias = "]")]
56#[doc(alias = "[")]
57#[doc(alias = "[]")]
58#[rustc_const_unstable(feature = "const_index", issue = "143775")]
59pub const trait Index<Idx: ?Sized> {
60    /// The returned type after indexing.
61    #[stable(feature = "rust1", since = "1.0.0")]
62    #[rustc_diagnostic_item = "IndexOutput"]
63    type Output: ?Sized;
64
65    /// Performs the indexing (`container[index]`) operation.
66    ///
67    /// # Panics
68    ///
69    /// May panic if the index is out of bounds.
70    #[stable(feature = "rust1", since = "1.0.0")]
71    #[rustc_no_implicit_autorefs]
72    #[track_caller]
73    #[ferrocene::annotation(
74        "This method declaration has no code to be covered, the fact that this shows up as uncovered is a bug in our coverage tooling."
75    )]
76    fn index(&self, index: Idx) -> &Self::Output;
77}
78
79/// Used for indexing operations (`container[index]`) in mutable contexts.
80///
81/// `container[index]` is actually syntactic sugar for
82/// `*container.index_mut(index)`, but only when used as a mutable value. If
83/// an immutable value is requested, the [`Index`] trait is used instead. This
84/// allows nice things such as `v[index] = value`.
85///
86/// # Examples
87///
88/// A very simple implementation of a `Balance` struct that has two sides, where
89/// each can be indexed mutably and immutably.
90///
91/// ```
92/// use std::ops::{Index, IndexMut};
93///
94/// #[derive(Debug)]
95/// enum Side {
96///     Left,
97///     Right,
98/// }
99///
100/// #[derive(Debug, PartialEq)]
101/// enum Weight {
102///     Kilogram(f32),
103///     Pound(f32),
104/// }
105///
106/// struct Balance {
107///     pub left: Weight,
108///     pub right: Weight,
109/// }
110///
111/// impl Index<Side> for Balance {
112///     type Output = Weight;
113///
114///     fn index(&self, index: Side) -> &Self::Output {
115///         println!("Accessing {index:?}-side of balance immutably");
116///         match index {
117///             Side::Left => &self.left,
118///             Side::Right => &self.right,
119///         }
120///     }
121/// }
122///
123/// impl IndexMut<Side> for Balance {
124///     fn index_mut(&mut self, index: Side) -> &mut Self::Output {
125///         println!("Accessing {index:?}-side of balance mutably");
126///         match index {
127///             Side::Left => &mut self.left,
128///             Side::Right => &mut self.right,
129///         }
130///     }
131/// }
132///
133/// let mut balance = Balance {
134///     right: Weight::Kilogram(2.5),
135///     left: Weight::Pound(1.5),
136/// };
137///
138/// // In this case, `balance[Side::Right]` is sugar for
139/// // `*balance.index(Side::Right)`, since we are only *reading*
140/// // `balance[Side::Right]`, not writing it.
141/// assert_eq!(balance[Side::Right], Weight::Kilogram(2.5));
142///
143/// // However, in this case `balance[Side::Left]` is sugar for
144/// // `*balance.index_mut(Side::Left)`, since we are writing
145/// // `balance[Side::Left]`.
146/// balance[Side::Left] = Weight::Kilogram(3.0);
147/// ```
148#[lang = "index_mut"]
149#[rustc_on_unimplemented(
150    on(
151        Self = "&str",
152        note = "you can use `.chars().nth()` or `.bytes().nth()`
153see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
154    ),
155    on(
156        Self = "str",
157        note = "you can use `.chars().nth()` or `.bytes().nth()`
158see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
159    ),
160    on(
161        Self = "alloc::string::String",
162        note = "you can use `.chars().nth()` or `.bytes().nth()`
163see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
164    ),
165    message = "the type `{Self}` cannot be mutably indexed by `{Idx}`",
166    label = "`{Self}` cannot be mutably indexed by `{Idx}`"
167)]
168#[stable(feature = "rust1", since = "1.0.0")]
169#[doc(alias = "[")]
170#[doc(alias = "]")]
171#[doc(alias = "[]")]
172#[rustc_const_unstable(feature = "const_index", issue = "143775")]
173pub const trait IndexMut<Idx: ?Sized>: [const] Index<Idx> {
174    /// Performs the mutable indexing (`container[index]`) operation.
175    ///
176    /// # Panics
177    ///
178    /// May panic if the index is out of bounds.
179    #[stable(feature = "rust1", since = "1.0.0")]
180    #[rustc_no_implicit_autorefs]
181    #[track_caller]
182    #[ferrocene::annotation(
183        "This method declaration has no code to be covered, the fact that this shows up as uncovered is a bug in our coverage tooling."
184    )]
185    fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
186}