Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 5 pull requests #134631

Merged
merged 14 commits into from
Dec 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_index/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ edition = "2021"

[dependencies]
# tidy-alphabetical-start
rustc_index_macros = { path = "../rustc_index_macros", default-features = false }
rustc_index_macros = { path = "../rustc_index_macros" }
rustc_macros = { path = "../rustc_macros", optional = true }
rustc_serialize = { path = "../rustc_serialize", optional = true }
smallvec = "1.8.1"
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_index_macros/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ proc-macro2 = "1"
quote = "1"

[features]
default = ["nightly"]
nightly = []
38 changes: 31 additions & 7 deletions library/core/src/ptr/const_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ impl<T: ?Sized> *const T {
/// Therefore, two pointers that are null may still not compare equal to
/// each other.
///
/// ## Behavior during const evaluation
/// # Panics during const evaluation
///
/// When this function is used during const evaluation, it may return `false` for pointers
/// that turn out to be null at runtime. Specifically, when a pointer to some memory
/// is offset beyond its bounds in such a way that the resulting pointer is null,
/// the function will still return `false`. There is no way for CTFE to know
/// the absolute position of that memory, so we cannot tell if the pointer is
/// null or not.
/// If this method is used during const evaluation, and `self` is a pointer
/// that is offset beyond the bounds of the memory it initially pointed to,
/// then there might not be enough information to determine whether the
/// pointer is null. This is because the absolute address in memory is not
/// known at compile time. If the nullness of the pointer cannot be
/// determined, this method will panic.
///
/// In-bounds pointers are never null, so the method will never panic for
/// such pointers.
///
/// # Examples
///
Expand Down Expand Up @@ -254,6 +257,13 @@ impl<T: ?Sized> *const T {
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: #method.is_null
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -331,6 +341,13 @@ impl<T: ?Sized> *const T {
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: #method.is_null
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -1607,6 +1624,13 @@ impl<T> *const [T] {
///
/// [valid]: crate::ptr#safety
/// [allocated object]: crate::ptr#allocated-object
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: #method.is_null
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
Expand Down
58 changes: 51 additions & 7 deletions library/core/src/ptr/mut_ptr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,17 @@ impl<T: ?Sized> *mut T {
/// Therefore, two pointers that are null may still not compare equal to
/// each other.
///
/// ## Behavior during const evaluation
/// # Panics during const evaluation
///
/// When this function is used during const evaluation, it may return `false` for pointers
/// that turn out to be null at runtime. Specifically, when a pointer to some memory
/// is offset beyond its bounds in such a way that the resulting pointer is null,
/// the function will still return `false`. There is no way for CTFE to know
/// the absolute position of that memory, so we cannot tell if the pointer is
/// null or not.
/// If this method is used during const evaluation, and `self` is a pointer
/// that is offset beyond the bounds of the memory it initially pointed to,
/// then there might not be enough information to determine whether the
/// pointer is null. This is because the absolute address in memory is not
/// known at compile time. If the nullness of the pointer cannot be
/// determined, this method will panic.
///
/// In-bounds pointers are never null, so the method will never panic for
/// such pointers.
///
/// # Examples
///
Expand Down Expand Up @@ -243,6 +246,13 @@ impl<T: ?Sized> *mut T {
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: #method.is_null-1
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -327,6 +337,13 @@ impl<T: ?Sized> *mut T {
/// Note that because the created reference is to `MaybeUninit<T>`, the
/// source pointer can point to uninitialized memory.
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: #method.is_null-1
///
/// # Examples
///
/// ```
Expand Down Expand Up @@ -590,6 +607,12 @@ impl<T: ?Sized> *mut T {
/// the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: #method.is_null-1
///
/// # Examples
///
Expand Down Expand Up @@ -673,6 +696,13 @@ impl<T: ?Sized> *mut T {
///
/// When calling this method, you have to ensure that *either* the pointer is null *or*
/// the pointer is [convertible to a reference](crate::ptr#pointer-to-reference-conversion).
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: #method.is_null-1
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_mut<'a>(self) -> Option<&'a mut MaybeUninit<T>>
Expand Down Expand Up @@ -1949,6 +1979,13 @@ impl<T> *mut [T] {
///
/// [valid]: crate::ptr#safety
/// [allocated object]: crate::ptr#allocated-object
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: #method.is_null-1
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice<'a>(self) -> Option<&'a [MaybeUninit<T>]> {
Expand Down Expand Up @@ -2000,6 +2037,13 @@ impl<T> *mut [T] {
///
/// [valid]: crate::ptr#safety
/// [allocated object]: crate::ptr#allocated-object
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: #method.is_null-1
#[inline]
#[unstable(feature = "ptr_as_uninit", issue = "75402")]
pub const unsafe fn as_uninit_slice_mut<'a>(self) -> Option<&'a mut [MaybeUninit<T>]> {
Expand Down
7 changes: 7 additions & 0 deletions library/core/src/ptr/non_null.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ impl<T: ?Sized> NonNull<T> {

/// Creates a new `NonNull` if `ptr` is non-null.
///
/// # Panics during const evaluation
///
/// This method will panic during const evaluation if the pointer cannot be
/// determined to be null or not. See [`is_null`] for more information.
///
/// [`is_null`]: ../primitive.pointer.html#method.is_null-1
///
/// # Examples
///
/// ```
Expand Down
8 changes: 5 additions & 3 deletions library/std/src/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2397,12 +2397,14 @@ pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
/// # Platform-specific behavior
///
/// This function currently corresponds to the `rename` function on Unix
/// and the `MoveFileEx` function with the `MOVEFILE_REPLACE_EXISTING` flag on Windows.
/// and the `SetFileInformationByHandle` function on Windows.
///
/// Because of this, the behavior when both `from` and `to` exist differs. On
/// Unix, if `from` is a directory, `to` must also be an (empty) directory. If
/// `from` is not a directory, `to` must also be not a directory. In contrast,
/// on Windows, `from` can be anything, but `to` must *not* be a directory.
/// `from` is not a directory, `to` must also be not a directory. The behavior
/// on Windows is the same on Windows 10 1607 and higher if `FileRenameInfoEx`
/// is supported by the filesystem; otherwise, `from` can be anything, but
/// `to` must *not* be a directory.
///
/// Note that, this [may change in the future][changes].
///
Expand Down
41 changes: 41 additions & 0 deletions library/std/src/fs/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1912,3 +1912,44 @@ fn test_hidden_file_truncation() {
let metadata = file.metadata().unwrap();
assert_eq!(metadata.len(), 0);
}

#[cfg(windows)]
#[test]
fn test_rename_file_over_open_file() {
// Make sure that std::fs::rename works if the target file is already opened with FILE_SHARE_DELETE. See #123985.
let tmpdir = tmpdir();

// Create source with test data to read.
let source_path = tmpdir.join("source_file.txt");
fs::write(&source_path, b"source hello world").unwrap();

// Create target file with test data to read;
let target_path = tmpdir.join("target_file.txt");
fs::write(&target_path, b"target hello world").unwrap();

// Open target file
let target_file = fs::File::open(&target_path).unwrap();

// Rename source
fs::rename(source_path, &target_path).unwrap();

core::mem::drop(target_file);
assert_eq!(fs::read(target_path).unwrap(), b"source hello world");
}

#[test]
#[cfg(windows)]
fn test_rename_directory_to_non_empty_directory() {
// Renaming a directory over a non-empty existing directory should fail on Windows.
let tmpdir: TempDir = tmpdir();

let source_path = tmpdir.join("source_directory");
let target_path = tmpdir.join("target_directory");

fs::create_dir(&source_path).unwrap();
fs::create_dir(&target_path).unwrap();

fs::write(target_path.join("target_file.txt"), b"target hello world").unwrap();

error!(fs::rename(source_path, target_path), 145); // ERROR_DIR_NOT_EMPTY
}
3 changes: 3 additions & 0 deletions library/std/src/sys/pal/windows/c/bindings.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2295,6 +2295,7 @@ Windows.Win32.Storage.FileSystem.FILE_NAME_OPENED
Windows.Win32.Storage.FileSystem.FILE_READ_ATTRIBUTES
Windows.Win32.Storage.FileSystem.FILE_READ_DATA
Windows.Win32.Storage.FileSystem.FILE_READ_EA
Windows.Win32.Storage.FileSystem.FILE_RENAME_INFO
Windows.Win32.Storage.FileSystem.FILE_SHARE_DELETE
Windows.Win32.Storage.FileSystem.FILE_SHARE_MODE
Windows.Win32.Storage.FileSystem.FILE_SHARE_NONE
Expand Down Expand Up @@ -2603,5 +2604,7 @@ Windows.Win32.System.Threading.WaitForMultipleObjects
Windows.Win32.System.Threading.WaitForSingleObject
Windows.Win32.System.Threading.WakeAllConditionVariable
Windows.Win32.System.Threading.WakeConditionVariable
Windows.Win32.System.WindowsProgramming.FILE_RENAME_FLAG_POSIX_SEMANTICS
Windows.Win32.System.WindowsProgramming.FILE_RENAME_FLAG_REPLACE_IF_EXISTS
Windows.Win32.System.WindowsProgramming.PROGRESS_CONTINUE
Windows.Win32.UI.Shell.GetUserProfileDirectoryW
16 changes: 16 additions & 0 deletions library/std/src/sys/pal/windows/c/windows_sys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2472,6 +2472,22 @@ pub const FILE_RANDOM_ACCESS: NTCREATEFILE_CREATE_OPTIONS = 2048u32;
pub const FILE_READ_ATTRIBUTES: FILE_ACCESS_RIGHTS = 128u32;
pub const FILE_READ_DATA: FILE_ACCESS_RIGHTS = 1u32;
pub const FILE_READ_EA: FILE_ACCESS_RIGHTS = 8u32;
pub const FILE_RENAME_FLAG_POSIX_SEMANTICS: u32 = 2u32;
pub const FILE_RENAME_FLAG_REPLACE_IF_EXISTS: u32 = 1u32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct FILE_RENAME_INFO {
pub Anonymous: FILE_RENAME_INFO_0,
pub RootDirectory: HANDLE,
pub FileNameLength: u32,
pub FileName: [u16; 1],
}
#[repr(C)]
#[derive(Clone, Copy)]
pub union FILE_RENAME_INFO_0 {
pub ReplaceIfExists: BOOLEAN,
pub Flags: u32,
}
pub const FILE_RESERVE_OPFILTER: NTCREATEFILE_CREATE_OPTIONS = 1048576u32;
pub const FILE_SEQUENTIAL_ONLY: NTCREATEFILE_CREATE_OPTIONS = 4u32;
pub const FILE_SESSION_AWARE: NTCREATEFILE_CREATE_OPTIONS = 262144u32;
Expand Down
Loading
Loading