1
0
mirror of https://github.com/google/comprehensive-rust.git synced 2025-02-06 02:53:28 +02:00

Simplify imports by importing fewer items directly (#2404)

When reading the code without an IDE, I find it useful to use explicit
module names, especially when items come from the standard library.

So `io::Error` instead of just `Error`, especially when people have
just been told about `std::error::Error` as well.

I also omitted most single-use items: I find it has less cognitive
overhead to say “we import `fmt`” and then later use `fmt::Display`
and `fmt::Formatter` in the code. It’s clear from the name that these
two things have something to do with formatting.

Finally, I made a few usages more consistent so that we refer to each
item in the same way within a single codeblock.
This commit is contained in:
Martin Geisler 2024-10-29 06:19:58 -04:00 committed by GitHub
parent 7a462efb57
commit 1d7c9163f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 16 additions and 18 deletions

View File

@ -7,9 +7,9 @@ minutes: 8
Several crates have support for asynchronous channels. For instance `tokio`:
```rust,editable,compile_fail
use tokio::sync::mpsc::{self, Receiver};
use tokio::sync::mpsc;
async fn ping_handler(mut input: Receiver<()>) {
async fn ping_handler(mut input: mpsc::Receiver<()>) {
let mut count: usize = 0;
while let Some(_) = input.recv().await {

View File

@ -15,8 +15,7 @@
// ANCHOR: solution
// ANCHOR: Philosopher
use std::sync::Arc;
use tokio::sync::mpsc::{self, Sender};
use tokio::sync::Mutex;
use tokio::sync::{mpsc, Mutex};
use tokio::time;
struct Fork;
@ -26,7 +25,7 @@ struct Philosopher {
// ANCHOR_END: Philosopher
left_fork: Arc<Mutex<Fork>>,
right_fork: Arc<Mutex<Fork>>,
thoughts: Sender<String>,
thoughts: mpsc::Sender<String>,
}
// ANCHOR: Philosopher-think

View File

@ -10,7 +10,7 @@ the system works correctly even when futures are cancelled. For example, it
shouldn't deadlock or lose data.
```rust,editable,compile_fail
use std::io::{self, ErrorKind};
use std::io;
use std::time::Duration;
use tokio::io::{AsyncReadExt, AsyncWriteExt, DuplexStream};
@ -36,12 +36,12 @@ impl LinesReader {
return Ok(None);
}
let s = String::from_utf8(bytes)
.map_err(|_| io::Error::new(ErrorKind::InvalidData, "not UTF-8"))?;
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "not UTF-8"))?;
Ok(Some(s))
}
}
async fn slow_copy(source: String, mut dest: DuplexStream) -> std::io::Result<()> {
async fn slow_copy(source: String, mut dest: DuplexStream) -> io::Result<()> {
for b in source.bytes() {
dest.write_u8(b).await?;
tokio::time::sleep(Duration::from_millis(10)).await
@ -50,7 +50,7 @@ async fn slow_copy(source: String, mut dest: DuplexStream) -> std::io::Result<()
}
#[tokio::main]
async fn main() -> std::io::Result<()> {
async fn main() -> io::Result<()> {
let (client, server) = tokio::io::duplex(5);
let handle = tokio::spawn(slow_copy("hi\nthere\n".to_owned(), client));
@ -102,7 +102,7 @@ async fn main() -> std::io::Result<()> {
// ...
let raw = std::mem::take(&mut self.bytes);
let s = String::from_utf8(raw)
.map_err(|_| io::Error::new(ErrorKind::InvalidData, "not UTF-8"))?;
.map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "not UTF-8"))?;
// ...
}
}

View File

@ -9,8 +9,8 @@ avoid boilerplate when defining error types. It provides derive macros that
assist in implementing `From<T>`, `Display`, and the `Error` trait.
```rust,editable,compile_fail
use std::fs;
use std::io::{self, Read};
use std::io::Read;
use std::{fs, io};
use thiserror::Error;
#[derive(Debug, Error)]

View File

@ -28,9 +28,8 @@ higher-level errors.
```rust,editable
use std::error::Error;
use std::fmt::{self, Display, Formatter};
use std::fs::File;
use std::io::{self, Read};
use std::io::Read;
use std::{fmt, fs, io};
#[derive(Debug)]
enum ReadUsernameError {
@ -40,8 +39,8 @@ enum ReadUsernameError {
impl Error for ReadUsernameError {}
impl Display for ReadUsernameError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
impl fmt::Display for ReadUsernameError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::IoError(e) => write!(f, "I/O error: {e}"),
Self::EmptyUsername(path) => write!(f, "Found no username in {path}"),
@ -57,7 +56,7 @@ impl From<io::Error> for ReadUsernameError {
fn read_username(path: &str) -> Result<String, ReadUsernameError> {
let mut username = String::with_capacity(100);
File::open(path)?.read_to_string(&mut username)?;
fs::File::open(path)?.read_to_string(&mut username)?;
if username.is_empty() {
return Err(ReadUsernameError::EmptyUsername(String::from(path)));
}