Skip to content

Commit 11d2046

Browse files
committed
Auto merge of #148022 - Zalathar:rollup-3m6ty9u, r=Zalathar
Rollup of 2 pull requests Successful merges: - #140463 (Document MaybeUninit bit validity) - #148017 (Add TidyFlags and merge DiagCtx) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 469357e + 5ff30d3 commit 11d2046

38 files changed

+254
-137
lines changed

library/core/src/mem/maybe_uninit.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,89 @@ use crate::{fmt, intrinsics, ptr, slice};
253253
/// std::process::exit(*code); // UB! Accessing uninitialized memory.
254254
/// }
255255
/// ```
256+
///
257+
/// # Validity
258+
///
259+
/// `MaybeUninit<T>` has no validity requirements –- any sequence of [bytes] of
260+
/// the appropriate length, initialized or uninitialized, are a valid
261+
/// representation.
262+
///
263+
/// Moving or copying a value of type `MaybeUninit<T>` (i.e., performing a
264+
/// "typed copy") will exactly preserve the contents, including the
265+
/// [provenance], of all non-padding bytes of type `T` in the value's
266+
/// representation.
267+
///
268+
/// Therefore `MaybeUninit` can be used to perform a round trip of a value from
269+
/// type `T` to type `MaybeUninit<U>` then back to type `T`, while preserving
270+
/// the original value, if two conditions are met. One, type `U` must have the
271+
/// same size as type `T`. Two, for all byte offsets where type `U` has padding,
272+
/// the corresponding bytes in the representation of the value must be
273+
/// uninitialized.
274+
///
275+
/// For example, due to the fact that the type `[u8; size_of::<T>]` has no
276+
/// padding, the following is sound for any type `T` and will return the
277+
/// original value:
278+
///
279+
/// ```rust,no_run
280+
/// # use core::mem::{MaybeUninit, transmute};
281+
/// # struct T;
282+
/// fn identity(t: T) -> T {
283+
/// unsafe {
284+
/// let u: MaybeUninit<[u8; size_of::<T>()]> = transmute(t);
285+
/// transmute(u) // OK.
286+
/// }
287+
/// }
288+
/// ```
289+
///
290+
/// Note: Copying a value that contains references may implicitly reborrow them
291+
/// causing the provenance of the returned value to differ from that of the
292+
/// original. This applies equally to the trivial identity function:
293+
///
294+
/// ```rust,no_run
295+
/// fn trivial_identity<T>(t: T) -> T { t }
296+
/// ```
297+
///
298+
/// Note: Moving or copying a value whose representation has initialized bytes
299+
/// at byte offsets where the type has padding may lose the value of those
300+
/// bytes, so while the original value will be preserved, the original
301+
/// *representation* of that value as bytes may not be. Again, this applies
302+
/// equally to `trivial_identity`.
303+
///
304+
/// Note: Performing this round trip when type `U` has padding at byte offsets
305+
/// where the representation of the original value has initialized bytes may
306+
/// produce undefined behavior or a different value. For example, the following
307+
/// is unsound since `T` requires all bytes to be initialized:
308+
///
309+
/// ```rust,no_run
310+
/// # use core::mem::{MaybeUninit, transmute};
311+
/// #[repr(C)] struct T([u8; 4]);
312+
/// #[repr(C)] struct U(u8, u16);
313+
/// fn unsound_identity(t: T) -> T {
314+
/// unsafe {
315+
/// let u: MaybeUninit<U> = transmute(t);
316+
/// transmute(u) // UB.
317+
/// }
318+
/// }
319+
/// ```
320+
///
321+
/// Conversely, the following is sound since `T` allows uninitialized bytes in
322+
/// the representation of a value, but the round trip may alter the value:
323+
///
324+
/// ```rust,no_run
325+
/// # use core::mem::{MaybeUninit, transmute};
326+
/// #[repr(C)] struct T(MaybeUninit<[u8; 4]>);
327+
/// #[repr(C)] struct U(u8, u16);
328+
/// fn non_identity(t: T) -> T {
329+
/// unsafe {
330+
/// // May lose an initialized byte.
331+
/// let u: MaybeUninit<U> = transmute(t);
332+
/// transmute(u)
333+
/// }
334+
/// }
335+
/// ```
336+
///
337+
/// [bytes]: ../../reference/memory-model.html#bytes
338+
/// [provenance]: crate::ptr#provenance
256339
#[stable(feature = "maybe_uninit", since = "1.36.0")]
257340
// Lang item so we can wrap other types in it. This is useful for coroutines.
258341
#[lang = "maybe_uninit"]

src/tools/tidy/src/alphabetical.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use std::fmt::Display;
2424
use std::iter::Peekable;
2525
use std::path::Path;
2626

27-
use crate::diagnostics::{CheckId, DiagCtx, RunningCheck};
27+
use crate::diagnostics::{CheckId, RunningCheck, TidyCtx};
2828
use crate::walk::{filter_dirs, walk};
2929

3030
#[cfg(test)]
@@ -130,8 +130,8 @@ fn check_lines<'a>(
130130
}
131131
}
132132

133-
pub fn check(path: &Path, diag_ctx: DiagCtx) {
134-
let mut check = diag_ctx.start_check(CheckId::new("alphabetical").path(path));
133+
pub fn check(path: &Path, tidy_ctx: TidyCtx) {
134+
let mut check = tidy_ctx.start_check(CheckId::new("alphabetical").path(path));
135135

136136
let skip =
137137
|path: &_, _is_dir| filter_dirs(path) || path.ends_with("tidy/src/alphabetical/tests.rs");

src/tools/tidy/src/alphabetical/tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
use std::path::Path;
22

33
use crate::alphabetical::check_lines;
4-
use crate::diagnostics::DiagCtx;
4+
use crate::diagnostics::{TidyCtx, TidyFlags};
55

66
#[track_caller]
77
fn test(lines: &str, name: &str, expected_msg: &str, expected_bad: bool) {
8-
let diag_ctx = DiagCtx::new(Path::new("/"), false);
9-
let mut check = diag_ctx.start_check("alphabetical-test");
8+
let tidy_ctx = TidyCtx::new(Path::new("/"), false, TidyFlags::default());
9+
let mut check = tidy_ctx.start_check("alphabetical-test");
1010
check_lines(&name, lines.lines().enumerate(), &mut check);
1111

1212
assert_eq!(expected_bad, check.is_bad());

src/tools/tidy/src/bins.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ pub use os_impl::*;
1212
mod os_impl {
1313
use std::path::Path;
1414

15-
use crate::diagnostics::DiagCtx;
15+
use crate::diagnostics::TidyCtx;
1616

1717
pub fn check_filesystem_support(_sources: &[&Path], _output: &Path) -> bool {
1818
return false;
1919
}
2020

21-
pub fn check(_path: &Path, _diag_ctx: DiagCtx) {}
21+
pub fn check(_path: &Path, _tidy_ctx: TidyCtx) {}
2222
}
2323

2424
#[cfg(unix)]
@@ -38,7 +38,7 @@ mod os_impl {
3838

3939
use FilesystemSupport::*;
4040

41-
use crate::diagnostics::DiagCtx;
41+
use crate::diagnostics::TidyCtx;
4242

4343
fn is_executable(path: &Path) -> std::io::Result<bool> {
4444
Ok(path.metadata()?.mode() & 0o111 != 0)
@@ -110,8 +110,8 @@ mod os_impl {
110110
}
111111

112112
#[cfg(unix)]
113-
pub fn check(path: &Path, diag_ctx: DiagCtx) {
114-
let mut check = diag_ctx.start_check("bins");
113+
pub fn check(path: &Path, tidy_ctx: TidyCtx) {
114+
let mut check = tidy_ctx.start_check("bins");
115115

116116
use std::ffi::OsStr;
117117

src/tools/tidy/src/debug_artifacts.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
33
use std::path::Path;
44

5-
use crate::diagnostics::{CheckId, DiagCtx};
5+
use crate::diagnostics::{CheckId, TidyCtx};
66
use crate::walk::{filter_dirs, filter_not_rust, walk};
77

88
const GRAPHVIZ_POSTFLOW_MSG: &str = "`borrowck_graphviz_postflow` attribute in test";
99

10-
pub fn check(test_dir: &Path, diag_ctx: DiagCtx) {
11-
let mut check = diag_ctx.start_check(CheckId::new("debug_artifacts").path(test_dir));
10+
pub fn check(test_dir: &Path, tidy_ctx: TidyCtx) {
11+
let mut check = tidy_ctx.start_check(CheckId::new("debug_artifacts").path(test_dir));
1212

1313
walk(
1414
test_dir,

src/tools/tidy/src/deps.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use build_helper::ci::CiEnv;
99
use cargo_metadata::semver::Version;
1010
use cargo_metadata::{Metadata, Package, PackageId};
1111

12-
use crate::diagnostics::{DiagCtx, RunningCheck};
12+
use crate::diagnostics::{RunningCheck, TidyCtx};
1313

1414
#[path = "../../../bootstrap/src/utils/proc_macro_deps.rs"]
1515
mod proc_macro_deps;
@@ -615,8 +615,9 @@ const PERMITTED_CRANELIFT_DEPENDENCIES: &[&str] = &[
615615
///
616616
/// `root` is path to the directory with the root `Cargo.toml` (for the workspace). `cargo` is path
617617
/// to the cargo executable.
618-
pub fn check(root: &Path, cargo: &Path, bless: bool, diag_ctx: DiagCtx) {
619-
let mut check = diag_ctx.start_check("deps");
618+
pub fn check(root: &Path, cargo: &Path, tidy_ctx: TidyCtx) {
619+
let mut check = tidy_ctx.start_check("deps");
620+
let bless = tidy_ctx.is_bless_enabled();
620621

621622
let mut checked_runtime_licenses = false;
622623

src/tools/tidy/src/diagnostics.rs

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,59 @@ use std::sync::{Arc, Mutex};
55

66
use termcolor::{Color, WriteColor};
77

8+
#[derive(Clone, Default)]
9+
///CLI flags used by tidy.
10+
pub struct TidyFlags {
11+
///Applies style and formatting changes during a tidy run.
12+
bless: bool,
13+
}
14+
15+
impl TidyFlags {
16+
pub fn new(cfg_args: &[String]) -> Self {
17+
let mut flags = Self::default();
18+
19+
for arg in cfg_args {
20+
match arg.as_str() {
21+
"--bless" => flags.bless = true,
22+
_ => continue,
23+
}
24+
}
25+
flags
26+
}
27+
}
28+
829
/// Collects diagnostics from all tidy steps, and contains shared information
930
/// that determines how should message and logs be presented.
1031
///
1132
/// Since checks are executed in parallel, the context is internally synchronized, to avoid
1233
/// all checks to lock it explicitly.
1334
#[derive(Clone)]
14-
pub struct DiagCtx(Arc<Mutex<DiagCtxInner>>);
35+
pub struct TidyCtx {
36+
tidy_flags: TidyFlags,
37+
diag_ctx: Arc<Mutex<DiagCtxInner>>,
38+
}
39+
40+
impl TidyCtx {
41+
pub fn new(root_path: &Path, verbose: bool, tidy_flags: TidyFlags) -> Self {
42+
Self {
43+
diag_ctx: Arc::new(Mutex::new(DiagCtxInner {
44+
running_checks: Default::default(),
45+
finished_checks: Default::default(),
46+
root_path: root_path.to_path_buf(),
47+
verbose,
48+
})),
49+
tidy_flags,
50+
}
51+
}
1552

16-
impl DiagCtx {
17-
pub fn new(root_path: &Path, verbose: bool) -> Self {
18-
Self(Arc::new(Mutex::new(DiagCtxInner {
19-
running_checks: Default::default(),
20-
finished_checks: Default::default(),
21-
root_path: root_path.to_path_buf(),
22-
verbose,
23-
})))
53+
pub fn is_bless_enabled(&self) -> bool {
54+
self.tidy_flags.bless
2455
}
2556

2657
pub fn start_check<Id: Into<CheckId>>(&self, id: Id) -> RunningCheck {
2758
let mut id = id.into();
2859

29-
let mut ctx = self.0.lock().unwrap();
60+
let mut ctx = self.diag_ctx.lock().unwrap();
3061

3162
// Shorten path for shorter diagnostics
3263
id.path = match id.path {
@@ -38,14 +69,14 @@ impl DiagCtx {
3869
RunningCheck {
3970
id,
4071
bad: false,
41-
ctx: self.0.clone(),
72+
ctx: self.diag_ctx.clone(),
4273
#[cfg(test)]
4374
errors: vec![],
4475
}
4576
}
4677

4778
pub fn into_failed_checks(self) -> Vec<FinishedCheck> {
48-
let ctx = Arc::into_inner(self.0).unwrap().into_inner().unwrap();
79+
let ctx = Arc::into_inner(self.diag_ctx).unwrap().into_inner().unwrap();
4980
assert!(ctx.running_checks.is_empty(), "Some checks are still running");
5081
ctx.finished_checks.into_iter().filter(|c| c.bad).collect()
5182
}
@@ -151,7 +182,7 @@ impl RunningCheck {
151182
/// Useful if you want to run some functions from tidy without configuring
152183
/// diagnostics.
153184
pub fn new_noop() -> Self {
154-
let ctx = DiagCtx::new(Path::new(""), false);
185+
let ctx = TidyCtx::new(Path::new(""), false, TidyFlags::default());
155186
ctx.start_check("noop")
156187
}
157188

src/tools/tidy/src/edition.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
33
use std::path::Path;
44

5-
use crate::diagnostics::{CheckId, DiagCtx};
5+
use crate::diagnostics::{CheckId, TidyCtx};
66
use crate::walk::{filter_dirs, walk};
77

8-
pub fn check(path: &Path, diag_ctx: DiagCtx) {
9-
let mut check = diag_ctx.start_check(CheckId::new("edition").path(path));
8+
pub fn check(path: &Path, tidy_ctx: TidyCtx) {
9+
let mut check = tidy_ctx.start_check(CheckId::new("edition").path(path));
1010
walk(path, |path, _is_dir| filter_dirs(path), &mut |entry, contents| {
1111
let file = entry.path();
1212
let filename = file.file_name().unwrap();

src/tools/tidy/src/error_codes.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use std::path::Path;
2222

2323
use regex::Regex;
2424

25-
use crate::diagnostics::{DiagCtx, RunningCheck};
25+
use crate::diagnostics::{RunningCheck, TidyCtx};
2626
use crate::walk::{filter_dirs, walk, walk_many};
2727

2828
const ERROR_CODES_PATH: &str = "compiler/rustc_error_codes/src/lib.rs";
@@ -36,8 +36,8 @@ const IGNORE_DOCTEST_CHECK: &[&str] = &["E0464", "E0570", "E0601", "E0602", "E07
3636
const IGNORE_UI_TEST_CHECK: &[&str] =
3737
&["E0461", "E0465", "E0514", "E0554", "E0640", "E0717", "E0729"];
3838

39-
pub fn check(root_path: &Path, search_paths: &[&Path], ci_info: &crate::CiInfo, diag_ctx: DiagCtx) {
40-
let mut check = diag_ctx.start_check("error_codes");
39+
pub fn check(root_path: &Path, search_paths: &[&Path], ci_info: &crate::CiInfo, tidy_ctx: TidyCtx) {
40+
let mut check = tidy_ctx.start_check("error_codes");
4141

4242
// Check that no error code explanation was removed.
4343
check_removed_error_code_explanation(ci_info, &mut check);

src/tools/tidy/src/extdeps.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::fs;
44
use std::path::Path;
55

66
use crate::deps::WorkspaceInfo;
7-
use crate::diagnostics::DiagCtx;
7+
use crate::diagnostics::TidyCtx;
88

99
/// List of allowed sources for packages.
1010
const ALLOWED_SOURCES: &[&str] = &[
@@ -15,8 +15,8 @@ const ALLOWED_SOURCES: &[&str] = &[
1515

1616
/// Checks for external package sources. `root` is the path to the directory that contains the
1717
/// workspace `Cargo.toml`.
18-
pub fn check(root: &Path, diag_ctx: DiagCtx) {
19-
let mut check = diag_ctx.start_check("extdeps");
18+
pub fn check(root: &Path, tidy_ctx: TidyCtx) {
19+
let mut check = tidy_ctx.start_check("extdeps");
2020

2121
for &WorkspaceInfo { path, submodules, .. } in crate::deps::WORKSPACES {
2222
if crate::deps::has_missing_submodule(root, submodules) {

0 commit comments

Comments
 (0)