Skip to content

Commit bb690c6

Browse files
committed
Rollup merge of rust-lang#49988 - clarcharr:never_docs, r=steveklabnik
Mention Result<!, E> in never docs. Fixes rust-lang#48096.
2 parents 8e7f6db + fc6d6c9 commit bb690c6

File tree

1 file changed

+53
-0
lines changed

1 file changed

+53
-0
lines changed

src/libstd/primitive_docs.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ mod prim_bool { }
116116
///
117117
/// # `!` and generics
118118
///
119+
/// ## Infallible errors
120+
///
119121
/// The main place you'll see `!` used explicitly is in generic code. Consider the [`FromStr`]
120122
/// trait:
121123
///
@@ -144,9 +146,60 @@ mod prim_bool { }
144146
/// [`Ok`] variant. This illustrates another behaviour of `!` - it can be used to "delete" certain
145147
/// enum variants from generic types like `Result`.
146148
///
149+
/// ## Infinite loops
150+
///
151+
/// While [`Result<T, !>`] is very useful for removing errors, `!` can also be used to remove
152+
/// successes as well. If we think of [`Result<T, !>`] as "if this function returns, it has not
153+
/// errored," we get a very intuitive idea of [`Result<!, E>`] as well: if the function returns, it
154+
/// *has* errored.
155+
///
156+
/// For example, consider the case of a simple web server, which can be simplified to:
157+
///
158+
/// ```ignore (hypothetical-example)
159+
/// loop {
160+
/// let (client, request) = get_request().expect("disconnected");
161+
/// let response = request.process();
162+
/// response.send(client);
163+
/// }
164+
/// ```
165+
///
166+
/// Currently, this isn't ideal, because we simply panic whenever we fail to get a new connection.
167+
/// Instead, we'd like to keep track of this error, like this:
168+
///
169+
/// ```ignore (hypothetical-example)
170+
/// loop {
171+
/// match get_request() {
172+
/// Err(err) => break err,
173+
/// Ok((client, request)) => {
174+
/// let response = request.process();
175+
/// response.send(client);
176+
/// },
177+
/// }
178+
/// }
179+
/// ```
180+
///
181+
/// Now, when the server disconnects, we exit the loop with an error instead of panicking. While it
182+
/// might be intuitive to simply return the error, we might want to wrap it in a [`Result<!, E>`]
183+
/// instead:
184+
///
185+
/// ```ignore (hypothetical-example)
186+
/// fn server_loop() -> Result<!, ConnectionError> {
187+
/// loop {
188+
/// let (client, request) = get_request()?;
189+
/// let response = request.process();
190+
/// response.send(client);
191+
/// }
192+
/// }
193+
/// ```
194+
///
195+
/// Now, we can use `?` instead of `match`, and the return type makes a lot more sense: if the loop
196+
/// ever stops, it means that an error occurred. We don't even have to wrap the loop in an `Ok`
197+
/// because `!` coerces to `Result<!, ConnectionError>` automatically.
198+
///
147199
/// [`String::from_str`]: str/trait.FromStr.html#tymethod.from_str
148200
/// [`Result<String, !>`]: result/enum.Result.html
149201
/// [`Result<T, !>`]: result/enum.Result.html
202+
/// [`Result<!, E>`]: result/enum.Result.html
150203
/// [`Ok`]: result/enum.Result.html#variant.Ok
151204
/// [`String`]: string/struct.String.html
152205
/// [`Err`]: result/enum.Result.html#variant.Err

0 commit comments

Comments
 (0)