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#[const_trait]
59#[rustc_const_unstable(feature = "const_index", issue = "143775")]
60pub trait Index<Idx: ?Sized> {
61 /// The returned type after indexing.
62 #[stable(feature = "rust1", since = "1.0.0")]
63 #[rustc_diagnostic_item = "IndexOutput"]
64 type Output: ?Sized;
65
66 /// Performs the indexing (`container[index]`) operation.
67 ///
68 /// # Panics
69 ///
70 /// May panic if the index is out of bounds.
71 #[stable(feature = "rust1", since = "1.0.0")]
72 #[rustc_no_implicit_autorefs]
73 #[track_caller]
74 fn index(&self, index: Idx) -> &Self::Output;
75}
76
77/// Used for indexing operations (`container[index]`) in mutable contexts.
78///
79/// `container[index]` is actually syntactic sugar for
80/// `*container.index_mut(index)`, but only when used as a mutable value. If
81/// an immutable value is requested, the [`Index`] trait is used instead. This
82/// allows nice things such as `v[index] = value`.
83///
84/// # Examples
85///
86/// A very simple implementation of a `Balance` struct that has two sides, where
87/// each can be indexed mutably and immutably.
88///
89/// ```
90/// use std::ops::{Index, IndexMut};
91///
92/// #[derive(Debug)]
93/// enum Side {
94/// Left,
95/// Right,
96/// }
97///
98/// #[derive(Debug, PartialEq)]
99/// enum Weight {
100/// Kilogram(f32),
101/// Pound(f32),
102/// }
103///
104/// struct Balance {
105/// pub left: Weight,
106/// pub right: Weight,
107/// }
108///
109/// impl Index<Side> for Balance {
110/// type Output = Weight;
111///
112/// fn index(&self, index: Side) -> &Self::Output {
113/// println!("Accessing {index:?}-side of balance immutably");
114/// match index {
115/// Side::Left => &self.left,
116/// Side::Right => &self.right,
117/// }
118/// }
119/// }
120///
121/// impl IndexMut<Side> for Balance {
122/// fn index_mut(&mut self, index: Side) -> &mut Self::Output {
123/// println!("Accessing {index:?}-side of balance mutably");
124/// match index {
125/// Side::Left => &mut self.left,
126/// Side::Right => &mut self.right,
127/// }
128/// }
129/// }
130///
131/// let mut balance = Balance {
132/// right: Weight::Kilogram(2.5),
133/// left: Weight::Pound(1.5),
134/// };
135///
136/// // In this case, `balance[Side::Right]` is sugar for
137/// // `*balance.index(Side::Right)`, since we are only *reading*
138/// // `balance[Side::Right]`, not writing it.
139/// assert_eq!(balance[Side::Right], Weight::Kilogram(2.5));
140///
141/// // However, in this case `balance[Side::Left]` is sugar for
142/// // `*balance.index_mut(Side::Left)`, since we are writing
143/// // `balance[Side::Left]`.
144/// balance[Side::Left] = Weight::Kilogram(3.0);
145/// ```
146#[lang = "index_mut"]
147#[rustc_on_unimplemented(
148 on(
149 Self = "&str",
150 note = "you can use `.chars().nth()` or `.bytes().nth()`
151see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
152 ),
153 on(
154 Self = "str",
155 note = "you can use `.chars().nth()` or `.bytes().nth()`
156see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
157 ),
158 on(
159 Self = "alloc::string::String",
160 note = "you can use `.chars().nth()` or `.bytes().nth()`
161see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
162 ),
163 message = "the type `{Self}` cannot be mutably indexed by `{Idx}`",
164 label = "`{Self}` cannot be mutably indexed by `{Idx}`"
165)]
166#[stable(feature = "rust1", since = "1.0.0")]
167#[doc(alias = "[")]
168#[doc(alias = "]")]
169#[doc(alias = "[]")]
170#[rustc_const_unstable(feature = "const_index", issue = "143775")]
171#[const_trait]
172pub trait IndexMut<Idx: ?Sized>: ~const Index<Idx> {
173 /// Performs the mutable indexing (`container[index]`) operation.
174 ///
175 /// # Panics
176 ///
177 /// May panic if the index is out of bounds.
178 #[stable(feature = "rust1", since = "1.0.0")]
179 #[rustc_no_implicit_autorefs]
180 #[track_caller]
181 fn index_mut(&mut self, index: Idx) -> &mut Self::Output;
182}