@@ -113,6 +113,7 @@ mod suspicious_map;
113
113
mod suspicious_splitn;
114
114
mod suspicious_to_owned;
115
115
mod type_id_on_box;
116
+ mod unbuffered_bytes;
116
117
mod uninit_assumed_init;
117
118
mod unit_hash;
118
119
mod unnecessary_fallible_conversions;
@@ -4406,6 +4407,33 @@ declare_clippy_lint! {
4406
4407
"using `Option::and_then` or `Result::and_then` to chain a computation that returns an `Option` or a `Result`"
4407
4408
}
4408
4409
4410
+ declare_clippy_lint ! {
4411
+ /// ### What it does
4412
+ /// Checks for calls to `Read::bytes` on types which don't implement `BufRead`.
4413
+ ///
4414
+ /// ### Why is this bad?
4415
+ /// The default implementation calls `read` for each byte, which can be very inefficient for data that’s not in memory, such as `File`.
4416
+ ///
4417
+ /// ### Example
4418
+ /// ```no_run
4419
+ /// use std::io::Read;
4420
+ /// use std::fs::File;
4421
+ /// let file = File::open("./bytes.txt").unwrap();
4422
+ /// file.bytes();
4423
+ /// ```
4424
+ /// Use instead:
4425
+ /// ```no_run
4426
+ /// use std::io::{BufReader, Read};
4427
+ /// use std::fs::File;
4428
+ /// let file = BufReader::new(std::fs::File::open("./bytes.txt").unwrap());
4429
+ /// file.bytes();
4430
+ /// ```
4431
+ #[ clippy:: version = "1.86.0" ]
4432
+ pub UNBUFFERED_BYTES ,
4433
+ perf,
4434
+ "calling .bytes() is very inefficient when data is not in memory"
4435
+ }
4436
+
4409
4437
#[ expect( clippy:: struct_excessive_bools) ]
4410
4438
pub struct Methods {
4411
4439
avoid_breaking_exported_api : bool ,
@@ -4580,6 +4608,7 @@ impl_lint_pass!(Methods => [
4580
4608
MANUAL_REPEAT_N ,
4581
4609
SLICED_STRING_AS_BYTES ,
4582
4610
RETURN_AND_THEN ,
4611
+ UNBUFFERED_BYTES ,
4583
4612
] ) ;
4584
4613
4585
4614
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4856,6 +4885,7 @@ impl Methods {
4856
4885
( "as_ptr" , [ ] ) => manual_c_str_literals:: check_as_ptr ( cx, expr, recv, & self . msrv ) ,
4857
4886
( "as_ref" , [ ] ) => useless_asref:: check ( cx, expr, "as_ref" , recv) ,
4858
4887
( "assume_init" , [ ] ) => uninit_assumed_init:: check ( cx, expr, recv) ,
4888
+ ( "bytes" , [ ] ) => unbuffered_bytes:: check ( cx, expr, recv) ,
4859
4889
( "cloned" , [ ] ) => {
4860
4890
cloned_instead_of_copied:: check ( cx, expr, recv, span, & self . msrv ) ;
4861
4891
option_as_ref_cloned:: check ( cx, recv, span) ;
0 commit comments