Skip to content

Commit

Permalink
Auto merge of rust-lang#134677 - tgross35:rollup-ozoeyop, r=tgross35
Browse files Browse the repository at this point in the history
Rollup of 4 pull requests

Successful merges:

 - rust-lang#129220 (Add platform docs for FreeBSD.)
 - rust-lang#134659 (test-infra: improve compiletest and run-make-support symlink handling)
 - rust-lang#134668 (Make sure we don't lose default struct value when formatting struct)
 - rust-lang#134672 (Revert stabilization of the `#[coverage(..)]` attribute)

r? `@ghost`
`@rustbot` modify labels: rollup
  • Loading branch information
bors committed Dec 23, 2024
2 parents 66bb586 + 8fc4ba2 commit 85c3989
Show file tree
Hide file tree
Showing 142 changed files with 969 additions and 433 deletions.
3 changes: 0 additions & 3 deletions compiler/rustc_feature/src/accepted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,6 @@ declare_features! (
(accepted, const_refs_to_static, "1.83.0", Some(119618)),
/// Allows implementing `Copy` for closures where possible (RFC 2132).
(accepted, copy_closures, "1.26.0", Some(44490)),
/// Allows function attribute `#[coverage(on/off)]`, to control coverage
/// instrumentation of that function.
(accepted, coverage_attribute, "CURRENT_RUSTC_VERSION", Some(84605)),
/// Allows `crate` in paths.
(accepted, crate_in_paths, "1.30.0", Some(45477)),
/// Allows users to provide classes for fenced code block using `class:classname`.
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -480,9 +480,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
template!(List: "address, kcfi, memory, thread"), DuplicatesOk,
EncodeCrossCrate::No, experimental!(no_sanitize)
),
ungated!(
gated!(
coverage, Normal, template!(OneOf: &[sym::off, sym::on]),
ErrorPreceding, EncodeCrossCrate::No,
coverage_attribute, experimental!(coverage)
),

ungated!(
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,9 @@ declare_features! (
(unstable, coroutine_clone, "1.65.0", Some(95360)),
/// Allows defining coroutines.
(unstable, coroutines, "1.21.0", Some(43122)),
/// Allows function attribute `#[coverage(on/off)]`, to control coverage
/// instrumentation of that function.
(unstable, coverage_attribute, "1.74.0", Some(84605)),
/// Allows non-builtin attributes in inner attribute position.
(unstable, custom_inner_attributes, "1.30.0", Some(54726)),
/// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/cmp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ pub trait Eq: PartialEq<Self> {
#[rustc_builtin_macro]
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
#[allow_internal_unstable(core_intrinsics, derive_eq, structural_match)]
#[cfg_attr(bootstrap, allow_internal_unstable(coverage_attribute))]
#[allow_internal_unstable(coverage_attribute)]
pub macro Eq($item:item) {
/* compiler built-in */
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@
//
// Library features:
// tidy-alphabetical-start
#![cfg_attr(bootstrap, feature(coverage_attribute))]
#![cfg_attr(bootstrap, feature(do_not_recommend))]
#![feature(array_ptr_get)]
#![feature(asm_experimental_arch)]
#![feature(const_eval_select)]
#![feature(const_typed_swap)]
#![feature(core_intrinsics)]
#![feature(coverage_attribute)]
#![feature(internal_impls_macro)]
#![feature(ip)]
#![feature(is_ascii_octdigit)]
Expand Down
6 changes: 2 additions & 4 deletions library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1673,8 +1673,7 @@ pub(crate) mod builtin {
///
/// [the reference]: ../../../reference/attributes/testing.html#the-test-attribute
#[stable(feature = "rust1", since = "1.0.0")]
#[allow_internal_unstable(test, rustc_attrs)]
#[cfg_attr(bootstrap, allow_internal_unstable(coverage_attribute))]
#[allow_internal_unstable(test, rustc_attrs, coverage_attribute)]
#[rustc_builtin_macro]
pub macro test($item:item) {
/* compiler built-in */
Expand All @@ -1687,8 +1686,7 @@ pub(crate) mod builtin {
soft,
reason = "`bench` is a part of custom test frameworks which are unstable"
)]
#[allow_internal_unstable(test, rustc_attrs)]
#[cfg_attr(bootstrap, allow_internal_unstable(coverage_attribute))]
#[allow_internal_unstable(test, rustc_attrs, coverage_attribute)]
#[rustc_builtin_macro]
pub macro bench($item:item) {
/* compiler built-in */
Expand Down
69 changes: 69 additions & 0 deletions src/build_helper/src/fs/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
//! Misc filesystem related helpers for use by bootstrap and tools.
use std::fs::Metadata;
use std::path::Path;
use std::{fs, io};

#[cfg(test)]
mod tests;

/// Helper to ignore [`std::io::ErrorKind::NotFound`], but still propagate other
/// [`std::io::ErrorKind`]s.
pub fn ignore_not_found<Op>(mut op: Op) -> io::Result<()>
where
Op: FnMut() -> io::Result<()>,
{
match op() {
Ok(()) => Ok(()),
Err(e) if e.kind() == io::ErrorKind::NotFound => Ok(()),
Err(e) => Err(e),
}
}

/// A wrapper around [`std::fs::remove_dir_all`] that can also be used on *non-directory entries*,
/// including files and symbolic links.
///
/// - This will produce an error if the target path is not found.
/// - Like [`std::fs::remove_dir_all`], this helper does not traverse symbolic links, will remove
/// symbolic link itself.
/// - This helper is **not** robust against races on the underlying filesystem, behavior is
/// unspecified if this helper is called concurrently.
/// - This helper is not robust against TOCTOU problems.
///
/// FIXME: this implementation is insufficiently robust to replace bootstrap's clean `rm_rf`
/// implementation:
///
/// - This implementation currently does not perform retries.
#[track_caller]
pub fn recursive_remove<P: AsRef<Path>>(path: P) -> io::Result<()> {
let path = path.as_ref();
let metadata = fs::symlink_metadata(path)?;
#[cfg(windows)]
let is_dir_like = |meta: &fs::Metadata| {
use std::os::windows::fs::FileTypeExt;
meta.is_dir() || meta.file_type().is_symlink_dir()
};
#[cfg(not(windows))]
let is_dir_like = fs::Metadata::is_dir;

if is_dir_like(&metadata) {
fs::remove_dir_all(path)
} else {
try_remove_op_set_perms(fs::remove_file, path, metadata)
}
}

fn try_remove_op_set_perms<'p, Op>(mut op: Op, path: &'p Path, metadata: Metadata) -> io::Result<()>
where
Op: FnMut(&'p Path) -> io::Result<()>,
{
match op(path) {
Ok(()) => Ok(()),
Err(e) if e.kind() == io::ErrorKind::PermissionDenied => {
let mut perms = metadata.permissions();
perms.set_readonly(false);
fs::set_permissions(path, perms)?;
op(path)
}
Err(e) => Err(e),
}
}
214 changes: 214 additions & 0 deletions src/build_helper/src/fs/tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
#![deny(unused_must_use)]

use std::{env, fs, io};

use super::recursive_remove;

mod recursive_remove_tests {
use super::*;

// Basic cases

#[test]
fn nonexistent_path() {
let tmpdir = env::temp_dir();
let path = tmpdir.join("__INTERNAL_BOOTSTRAP_nonexistent_path");
assert!(fs::symlink_metadata(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound));
assert!(recursive_remove(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound));
}

#[test]
fn file() {
let tmpdir = env::temp_dir();
let path = tmpdir.join("__INTERNAL_BOOTSTRAP_file");
fs::write(&path, b"").unwrap();
assert!(fs::symlink_metadata(&path).is_ok());
assert!(recursive_remove(&path).is_ok());
assert!(fs::symlink_metadata(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound));
}

mod dir_tests {
use super::*;

#[test]
fn dir_empty() {
let tmpdir = env::temp_dir();
let path = tmpdir.join("__INTERNAL_BOOTSTRAP_dir_tests_dir_empty");
fs::create_dir_all(&path).unwrap();
assert!(fs::symlink_metadata(&path).is_ok());
assert!(recursive_remove(&path).is_ok());
assert!(
fs::symlink_metadata(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);
}

#[test]
fn dir_recursive() {
let tmpdir = env::temp_dir();
let path = tmpdir.join("__INTERNAL_BOOTSTRAP_dir_tests_dir_recursive");
fs::create_dir_all(&path).unwrap();
assert!(fs::symlink_metadata(&path).is_ok());

let file_a = path.join("a.txt");
fs::write(&file_a, b"").unwrap();
assert!(fs::symlink_metadata(&file_a).is_ok());

let dir_b = path.join("b");
fs::create_dir_all(&dir_b).unwrap();
assert!(fs::symlink_metadata(&dir_b).is_ok());

let file_c = dir_b.join("c.rs");
fs::write(&file_c, b"").unwrap();
assert!(fs::symlink_metadata(&file_c).is_ok());

assert!(recursive_remove(&path).is_ok());

assert!(
fs::symlink_metadata(&file_a).is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);
assert!(
fs::symlink_metadata(&dir_b).is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);
assert!(
fs::symlink_metadata(&file_c).is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);
}
}

/// Check that [`recursive_remove`] does not traverse symlinks and only removes symlinks
/// themselves.
///
/// Symlink-to-file versus symlink-to-dir is a distinction that's important on Windows, but not
/// on Unix.
mod symlink_tests {
use super::*;

#[cfg(unix)]
#[test]
fn unix_symlink() {
let tmpdir = env::temp_dir();
let path = tmpdir.join("__INTERNAL_BOOTSTRAP_symlink_tests_unix_symlink");
let symlink_path =
tmpdir.join("__INTERNAL_BOOTSTRAP__symlink_tests_unix_symlink_symlink");
fs::write(&path, b"").unwrap();

assert!(fs::symlink_metadata(&path).is_ok());
assert!(
fs::symlink_metadata(&symlink_path)
.is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);

std::os::unix::fs::symlink(&path, &symlink_path).unwrap();

assert!(recursive_remove(&symlink_path).is_ok());

// Check that the symlink got removed...
assert!(
fs::symlink_metadata(&symlink_path)
.is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);
// ... but pointed-to file still exists.
assert!(fs::symlink_metadata(&path).is_ok());

fs::remove_file(&path).unwrap();
}

#[cfg(windows)]
#[test]
fn windows_symlink_to_file() {
let tmpdir = env::temp_dir();
let path = tmpdir.join("__INTERNAL_BOOTSTRAP_symlink_tests_windows_symlink_to_file");
let symlink_path = tmpdir
.join("__INTERNAL_BOOTSTRAP_SYMLINK_symlink_tests_windows_symlink_to_file_symlink");
fs::write(&path, b"").unwrap();

assert!(fs::symlink_metadata(&path).is_ok());
assert!(
fs::symlink_metadata(&symlink_path)
.is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);

std::os::windows::fs::symlink_file(&path, &symlink_path).unwrap();

assert!(recursive_remove(&symlink_path).is_ok());

// Check that the symlink-to-file got removed...
assert!(
fs::symlink_metadata(&symlink_path)
.is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);
// ... but pointed-to file still exists.
assert!(fs::symlink_metadata(&path).is_ok());

fs::remove_file(&path).unwrap();
}

#[cfg(windows)]
#[test]
fn windows_symlink_to_dir() {
let tmpdir = env::temp_dir();
let path = tmpdir.join("__INTERNAL_BOOTSTRAP_symlink_tests_windows_symlink_to_dir");
let symlink_path =
tmpdir.join("__INTERNAL_BOOTSTRAP_symlink_tests_windows_symlink_to_dir_symlink");
fs::create_dir_all(&path).unwrap();

assert!(fs::symlink_metadata(&path).is_ok());
assert!(
fs::symlink_metadata(&symlink_path)
.is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);

std::os::windows::fs::symlink_dir(&path, &symlink_path).unwrap();

assert!(recursive_remove(&symlink_path).is_ok());

// Check that the symlink-to-dir got removed...
assert!(
fs::symlink_metadata(&symlink_path)
.is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);
// ... but pointed-to dir still exists.
assert!(fs::symlink_metadata(&path).is_ok());

fs::remove_dir_all(&path).unwrap();
}
}

/// Read-only file and directories only need special handling on Windows.
#[cfg(windows)]
mod readonly_tests {
use super::*;

#[test]
fn overrides_readonly() {
let tmpdir = env::temp_dir();
let path = tmpdir.join("__INTERNAL_BOOTSTRAP_readonly_tests_overrides_readonly");

// In case of a previous failed test:
if let Ok(mut perms) = fs::symlink_metadata(&path).map(|m| m.permissions()) {
perms.set_readonly(false);
fs::set_permissions(&path, perms).unwrap();
fs::remove_file(&path).unwrap();
}

fs::write(&path, b"").unwrap();

let mut perms = fs::symlink_metadata(&path).unwrap().permissions();
perms.set_readonly(true);
fs::set_permissions(&path, perms).unwrap();

// Check that file exists but is read-only, and that normal `std::fs::remove_file` fails
// to delete the file.
assert!(fs::symlink_metadata(&path).is_ok_and(|m| m.permissions().readonly()));
assert!(
fs::remove_file(&path).is_err_and(|e| e.kind() == io::ErrorKind::PermissionDenied)
);

assert!(recursive_remove(&path).is_ok());

assert!(
fs::symlink_metadata(&path).is_err_and(|e| e.kind() == io::ErrorKind::NotFound)
);
}
}
}
1 change: 1 addition & 0 deletions src/build_helper/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pub mod ci;
pub mod drop_bomb;
pub mod fs;
pub mod git;
pub mod metrics;
pub mod stage0_parser;
Expand Down
1 change: 1 addition & 0 deletions src/doc/rustc/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@
- [\*-nto-qnx-\*](platform-support/nto-qnx.md)
- [*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md)
- [*-unknown-hermit](platform-support/hermit.md)
- [*-unknown-freebsd](platform-support/freebsd.md)
- [\*-unknown-netbsd\*](platform-support/netbsd.md)
- [*-unknown-openbsd](platform-support/openbsd.md)
- [*-unknown-redox](platform-support/redox.md)
Expand Down
Loading

0 comments on commit 85c3989

Please sign in to comment.