Skip to content

Commit bf1f2ee

Browse files
committed
Auto merge of #70865 - Dylan-DPC:rollup-jje2cuv, r=Dylan-DPC
Rollup of 5 pull requests Successful merges: - #70612 (Add io::Write::write_all_vectored) - #70690 (Clean up E0501 explanation) - #70821 (expose suggestions::InferCtxtExt for clippy) - #70839 (clean up E0506 explanation) - #70859 (Move sanitize-inline-always test to sanitize directory) Failed merges: r? @ghost
2 parents 6dee5f1 + b9fe46d commit bf1f2ee

File tree

6 files changed

+210
-47
lines changed

6 files changed

+210
-47
lines changed

src/librustc_error_codes/error_codes/E0501.md

+11-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
1-
This error indicates that a mutable variable is being used while it is still
2-
captured by a closure. Because the closure has borrowed the variable, it is not
3-
available for use until the closure goes out of scope.
4-
5-
Note that a capture will either move or borrow a variable, but in this
6-
situation, the closure is borrowing the variable. Take a look at the chapter
7-
on [Capturing][capturing] in Rust By Example for more information.
8-
9-
[capturing]: https://doc.rust-lang.org/stable/rust-by-example/fn/closures/capture.html
1+
A mutable variable is used but it is already captured by a closure.
102

113
Erroneous code example:
124

@@ -29,6 +21,16 @@ fn foo(a: &mut i32) {
2921
}
3022
```
3123

24+
This error indicates that a mutable variable is used while it is still captured
25+
by a closure. Because the closure has borrowed the variable, it is not available
26+
until the closure goes out of scope.
27+
28+
Note that a capture will either move or borrow a variable, but in this
29+
situation, the closure is borrowing the variable. Take a look at the chapter
30+
on [Capturing][capturing] in Rust By Example for more information.
31+
32+
[capturing]: https://doc.rust-lang.org/stable/rust-by-example/fn/closures/capture.html
33+
3234
To fix this error, you can finish using the closure before using the captured
3335
variable:
3436

+26-34
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
This error occurs when an attempt is made to assign to a borrowed value.
1+
An attempt was made to assign to a borrowed value.
22

33
Erroneous code example:
44

@@ -7,14 +7,12 @@ struct FancyNum {
77
num: u8,
88
}
99
10-
fn main() {
11-
let mut fancy_num = FancyNum { num: 5 };
12-
let fancy_ref = &fancy_num;
13-
fancy_num = FancyNum { num: 6 };
14-
// error: cannot assign to `fancy_num` because it is borrowed
10+
let mut fancy_num = FancyNum { num: 5 };
11+
let fancy_ref = &fancy_num;
12+
fancy_num = FancyNum { num: 6 };
13+
// error: cannot assign to `fancy_num` because it is borrowed
1514
16-
println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
17-
}
15+
println!("Num: {}, Ref: {}", fancy_num.num, fancy_ref.num);
1816
```
1917

2018
Because `fancy_ref` still holds a reference to `fancy_num`, `fancy_num` can't
@@ -27,13 +25,11 @@ struct FancyNum {
2725
num: u8,
2826
}
2927
30-
fn main() {
31-
let mut fancy_num = FancyNum { num: 5 };
32-
let moved_num = fancy_num;
33-
fancy_num = FancyNum { num: 6 };
28+
let mut fancy_num = FancyNum { num: 5 };
29+
let moved_num = fancy_num;
30+
fancy_num = FancyNum { num: 6 };
3431
35-
println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num);
36-
}
32+
println!("Num: {}, Moved num: {}", fancy_num.num, moved_num.num);
3733
```
3834

3935
If the value has to be borrowed, try limiting the lifetime of the borrow using
@@ -44,18 +40,16 @@ struct FancyNum {
4440
num: u8,
4541
}
4642
47-
fn main() {
48-
let mut fancy_num = FancyNum { num: 5 };
49-
50-
{
51-
let fancy_ref = &fancy_num;
52-
println!("Ref: {}", fancy_ref.num);
53-
}
43+
let mut fancy_num = FancyNum { num: 5 };
5444
55-
// Works because `fancy_ref` is no longer in scope
56-
fancy_num = FancyNum { num: 6 };
57-
println!("Num: {}", fancy_num.num);
45+
{
46+
let fancy_ref = &fancy_num;
47+
println!("Ref: {}", fancy_ref.num);
5848
}
49+
50+
// Works because `fancy_ref` is no longer in scope
51+
fancy_num = FancyNum { num: 6 };
52+
println!("Num: {}", fancy_num.num);
5953
```
6054

6155
Or by moving the reference into a function:
@@ -65,17 +59,15 @@ struct FancyNum {
6559
num: u8,
6660
}
6761
68-
fn main() {
69-
let mut fancy_num = FancyNum { num: 5 };
70-
71-
print_fancy_ref(&fancy_num);
72-
73-
// Works because function borrow has ended
74-
fancy_num = FancyNum { num: 6 };
75-
println!("Num: {}", fancy_num.num);
76-
}
77-
7862
fn print_fancy_ref(fancy_ref: &FancyNum){
7963
println!("Ref: {}", fancy_ref.num);
8064
}
65+
66+
let mut fancy_num = FancyNum { num: 5 };
67+
68+
print_fancy_ref(&fancy_num);
69+
70+
// Works because function borrow has ended
71+
fancy_num = FancyNum { num: 6 };
72+
println!("Num: {}", fancy_num.num);
8173
```

src/librustc_trait_selection/traits/error_reporting/suggestions.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ use std::fmt;
2222
use super::InferCtxtPrivExt;
2323
use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
2424

25-
crate trait InferCtxtExt<'tcx> {
25+
// This trait is public to expose the diagnostics methods to clippy.
26+
pub trait InferCtxtExt<'tcx> {
2627
fn suggest_restricting_param_bound(
2728
&self,
2829
err: &mut DiagnosticBuilder<'_>,

src/libstd/io/mod.rs

+169-1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@
261261

262262
use crate::cmp;
263263
use crate::fmt;
264+
use crate::mem;
264265
use crate::memchr;
265266
use crate::ops::{Deref, DerefMut};
266267
use crate::ptr;
@@ -1376,6 +1377,70 @@ pub trait Write {
13761377
Ok(())
13771378
}
13781379

1380+
/// Attempts to write multiple buffers into this writer.
1381+
///
1382+
/// This method will continuously call [`write_vectored`] until there is no
1383+
/// more data to be written or an error of non-[`ErrorKind::Interrupted`]
1384+
/// kind is returned. This method will not return until all buffers have
1385+
/// been successfully written or such an error occurs. The first error that
1386+
/// is not of [`ErrorKind::Interrupted`] kind generated from this method
1387+
/// will be returned.
1388+
///
1389+
/// If the buffer contains no data, this will never call [`write_vectored`].
1390+
///
1391+
/// [`write_vectored`]: #method.write_vectored
1392+
/// [`ErrorKind::Interrupted`]: ../../std/io/enum.ErrorKind.html#variant.Interrupted
1393+
///
1394+
/// # Notes
1395+
///
1396+
///
1397+
/// Unlike `io::Write::write_vectored`, this takes a *mutable* reference to
1398+
/// a slice of `IoSlice`s, not an immutable one. That's because we need to
1399+
/// modify the slice to keep track of the bytes already written.
1400+
///
1401+
/// Once this function returns, the contents of `bufs` are unspecified, as
1402+
/// this depends on how many calls to `write_vectored` were necessary. It is
1403+
/// best to understand this function as taking ownership of `bufs` and to
1404+
/// not use `bufs` afterwards. The underlying buffers, to which the
1405+
/// `IoSlice`s point (but not the `IoSlice`s themselves), are unchanged and
1406+
/// can be reused.
1407+
///
1408+
/// # Examples
1409+
///
1410+
/// ```
1411+
/// #![feature(write_all_vectored)]
1412+
/// # fn main() -> std::io::Result<()> {
1413+
///
1414+
/// use std::io::{Write, IoSlice};
1415+
///
1416+
/// let mut writer = Vec::new();
1417+
/// let bufs = &mut [
1418+
/// IoSlice::new(&[1]),
1419+
/// IoSlice::new(&[2, 3]),
1420+
/// IoSlice::new(&[4, 5, 6]),
1421+
/// ];
1422+
///
1423+
/// writer.write_all_vectored(bufs)?;
1424+
/// // Note: the contents of `bufs` is now undefined, see the Notes section.
1425+
///
1426+
/// assert_eq!(writer, &[1, 2, 3, 4, 5, 6]);
1427+
/// # Ok(()) }
1428+
/// ```
1429+
#[unstable(feature = "write_all_vectored", issue = "70436")]
1430+
fn write_all_vectored(&mut self, mut bufs: &mut [IoSlice<'_>]) -> Result<()> {
1431+
while !bufs.is_empty() {
1432+
match self.write_vectored(bufs) {
1433+
Ok(0) => {
1434+
return Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer"));
1435+
}
1436+
Ok(n) => bufs = IoSlice::advance(mem::take(&mut bufs), n),
1437+
Err(ref e) if e.kind() == ErrorKind::Interrupted => {}
1438+
Err(e) => return Err(e),
1439+
}
1440+
}
1441+
Ok(())
1442+
}
1443+
13791444
/// Writes a formatted string into this writer, returning any error
13801445
/// encountered.
13811446
///
@@ -2423,7 +2488,7 @@ impl<B: BufRead> Iterator for Lines<B> {
24232488
#[cfg(test)]
24242489
mod tests {
24252490
use super::{repeat, Cursor, SeekFrom};
2426-
use crate::cmp;
2491+
use crate::cmp::{self, min};
24272492
use crate::io::prelude::*;
24282493
use crate::io::{self, IoSlice, IoSliceMut};
24292494
use crate::ops::Deref;
@@ -2812,4 +2877,107 @@ mod tests {
28122877
bufs = IoSlice::advance(bufs, 9);
28132878
assert!(bufs.is_empty());
28142879
}
2880+
2881+
/// Create a new writer that reads from at most `n_bufs` and reads
2882+
/// `per_call` bytes (in total) per call to write.
2883+
fn test_writer(n_bufs: usize, per_call: usize) -> TestWriter {
2884+
TestWriter { n_bufs, per_call, written: Vec::new() }
2885+
}
2886+
2887+
struct TestWriter {
2888+
n_bufs: usize,
2889+
per_call: usize,
2890+
written: Vec<u8>,
2891+
}
2892+
2893+
impl Write for TestWriter {
2894+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
2895+
self.write_vectored(&[IoSlice::new(buf)])
2896+
}
2897+
2898+
fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
2899+
let mut left = self.per_call;
2900+
let mut written = 0;
2901+
for buf in bufs.iter().take(self.n_bufs) {
2902+
let n = min(left, buf.len());
2903+
self.written.extend_from_slice(&buf[0..n]);
2904+
left -= n;
2905+
written += n;
2906+
}
2907+
Ok(written)
2908+
}
2909+
2910+
fn flush(&mut self) -> io::Result<()> {
2911+
Ok(())
2912+
}
2913+
}
2914+
2915+
#[test]
2916+
fn test_writer_read_from_one_buf() {
2917+
let mut writer = test_writer(1, 2);
2918+
2919+
assert_eq!(writer.write(&[]).unwrap(), 0);
2920+
assert_eq!(writer.write_vectored(&[]).unwrap(), 0);
2921+
2922+
// Read at most 2 bytes.
2923+
assert_eq!(writer.write(&[1, 1, 1]).unwrap(), 2);
2924+
let bufs = &[IoSlice::new(&[2, 2, 2])];
2925+
assert_eq!(writer.write_vectored(bufs).unwrap(), 2);
2926+
2927+
// Only read from first buf.
2928+
let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4, 4])];
2929+
assert_eq!(writer.write_vectored(bufs).unwrap(), 1);
2930+
2931+
assert_eq!(writer.written, &[1, 1, 2, 2, 3]);
2932+
}
2933+
2934+
#[test]
2935+
fn test_writer_read_from_multiple_bufs() {
2936+
let mut writer = test_writer(3, 3);
2937+
2938+
// Read at most 3 bytes from two buffers.
2939+
let bufs = &[IoSlice::new(&[1]), IoSlice::new(&[2, 2, 2])];
2940+
assert_eq!(writer.write_vectored(bufs).unwrap(), 3);
2941+
2942+
// Read at most 3 bytes from three buffers.
2943+
let bufs = &[IoSlice::new(&[3]), IoSlice::new(&[4]), IoSlice::new(&[5, 5])];
2944+
assert_eq!(writer.write_vectored(bufs).unwrap(), 3);
2945+
2946+
assert_eq!(writer.written, &[1, 2, 2, 3, 4, 5]);
2947+
}
2948+
2949+
#[test]
2950+
fn test_write_all_vectored() {
2951+
#[rustfmt::skip] // Becomes unreadable otherwise.
2952+
let tests: Vec<(_, &'static [u8])> = vec![
2953+
(vec![], &[]),
2954+
(vec![IoSlice::new(&[1])], &[1]),
2955+
(vec![IoSlice::new(&[1, 2])], &[1, 2]),
2956+
(vec![IoSlice::new(&[1, 2, 3])], &[1, 2, 3]),
2957+
(vec![IoSlice::new(&[1, 2, 3, 4])], &[1, 2, 3, 4]),
2958+
(vec![IoSlice::new(&[1, 2, 3, 4, 5])], &[1, 2, 3, 4, 5]),
2959+
(vec![IoSlice::new(&[1]), IoSlice::new(&[2])], &[1, 2]),
2960+
(vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2])], &[1, 2, 2]),
2961+
(vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2])], &[1, 1, 2, 2]),
2962+
(vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]),
2963+
(vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 2, 2, 2]),
2964+
(vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2])], &[1, 1, 1, 2, 2, 2]),
2965+
(vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 2, 2, 2, 2]),
2966+
(vec![IoSlice::new(&[1, 1, 1, 1]), IoSlice::new(&[2, 2, 2, 2])], &[1, 1, 1, 1, 2, 2, 2, 2]),
2967+
(vec![IoSlice::new(&[1]), IoSlice::new(&[2]), IoSlice::new(&[3])], &[1, 2, 3]),
2968+
(vec![IoSlice::new(&[1, 1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3])], &[1, 1, 2, 2, 3, 3]),
2969+
(vec![IoSlice::new(&[1]), IoSlice::new(&[2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 2, 2, 3, 3, 3]),
2970+
(vec![IoSlice::new(&[1, 1, 1]), IoSlice::new(&[2, 2, 2]), IoSlice::new(&[3, 3, 3])], &[1, 1, 1, 2, 2, 2, 3, 3, 3]),
2971+
];
2972+
2973+
let writer_configs = &[(1, 1), (1, 2), (1, 3), (2, 2), (2, 3), (3, 3)];
2974+
2975+
for (n_bufs, per_call) in writer_configs.iter().copied() {
2976+
for (mut input, wanted) in tests.clone().into_iter() {
2977+
let mut writer = test_writer(n_bufs, per_call);
2978+
assert!(writer.write_all_vectored(&mut *input).is_ok());
2979+
assert_eq!(&*writer.written, &*wanted);
2980+
}
2981+
}
2982+
}
28152983
}
File renamed without changes.

src/test/ui/sanitize-inline-always.stderr src/test/ui/sanitize/inline-always.stderr

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
warning: `no_sanitize` will have no effect after inlining
2-
--> $DIR/sanitize-inline-always.rs:7:1
2+
--> $DIR/inline-always.rs:7:1
33
|
44
LL | #[no_sanitize(address)]
55
| ^^^^^^^^^^^^^^^^^^^^^^^
66
|
77
= note: `#[warn(inline_no_sanitize)]` on by default
88
note: inlining requested here
9-
--> $DIR/sanitize-inline-always.rs:5:1
9+
--> $DIR/inline-always.rs:5:1
1010
|
1111
LL | #[inline(always)]
1212
| ^^^^^^^^^^^^^^^^^

0 commit comments

Comments
 (0)