Remove use of rustc_attrs, which is no longer needed. (#53)

* Remove use of `rustc_attrs`, which is no longer needed.

This io-lifetimes crate no longer needs this rustc_attrs code. On Rust
versions where io_safety is stabilized, we use the version in std (which
uses rustc_attrs internally). On Rust versions where it's not, rustc_attrs
isn't available to user code anyway, since it's not a stable language
feature.

This might fix #51.

* Rename `io_lifetimes_use_std` to `io_safety_is_in_std`.

This may also help fix #51.
This commit is contained in:
Dan Gohman
2022-11-25 10:01:14 -08:00
committed by GitHub
parent bacb6a6f58
commit e296b6236d
11 changed files with 57 additions and 99 deletions
+1 -1
View File
@@ -25,7 +25,7 @@ fs-err = { version = "2.6.0", optional = true }
os_pipe = { version = "1.0.0", features = ["io_safety"], optional = true }
# The following dependencies allow io-lifetimes to define impls for various
# third-party traits. This is only done in not(io_lifetimes_use_std) mode,
# third-party traits. This is only done in not(io_safety_is_in_std) mode,
# because when we're using the std types and traits, we can't define impls
# on third-party traits, due to the orphan rule. Work is ongoing to add
# the needs impls upstream.
-3
View File
@@ -20,9 +20,6 @@ This is associated with [RFC 3128], the I/O Safety RFC, which is now merged.
Work is now underway to move the `OwnedFd` and `BorrowedFd` types and `AsFd`
trait developed here into `std`.
Some features currently require nightly Rust, as they depend on `rustc_attrs`
to perform niche optimizations needed for FFI use cases.
For a quick taste, check out the code examples:
- [hello], a basic demo of this API, doing low-level I/O manually, using the
+1 -5
View File
@@ -4,13 +4,9 @@ use std::io::Write;
fn main() {
// I/O safety is stabilized in Rust 1.63.
if has_io_safety() {
use_feature("io_lifetimes_use_std")
use_feature("io_safety_is_in_std")
}
// Niche optimizations for `Borrowed*` and `Owned*` depend on `rustc_attrs`
// which, outside of `std`, are only available on nightly.
use_feature_or_nothing("rustc_attrs");
// Work around
// https://github.com/rust-lang/rust/issues/103306.
use_feature_or_nothing("wasi_ext");
+7 -7
View File
@@ -1,7 +1,7 @@
//! A simple testcase that prints a few messages to the console, demonstrating
//! the io-lifetimes API.
#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
#![cfg_attr(not(io_safety_is_in_std), allow(unused_imports))]
#[cfg(feature = "close")]
use io_lifetimes::example_ffi::*;
@@ -14,12 +14,12 @@ use std::{
#[cfg(all(unix, feature = "close"))]
use io_lifetimes::{AsFd, OwnedFd};
#[cfg(windows)]
use io_lifetimes::{AsHandle, FromHandle, OwnedHandle};
#[cfg(windows)]
#[cfg(all(windows, feature = "close"))]
use io_lifetimes::{AsHandle, OwnedHandle};
#[cfg(all(windows, feature = "close"))]
use std::{convert::TryInto, os::windows::io::RawHandle, ptr::null_mut};
#[cfg(all(rustc_attrs, unix, feature = "close"))]
#[cfg(all(io_safety_is_in_std, unix, feature = "close"))]
fn main() -> io::Result<()> {
let fd = unsafe {
// Open a file, which returns an `Option<OwnedFd>`, which we can
@@ -120,9 +120,9 @@ fn main() -> io::Result<()> {
}
#[cfg(all(
not(all(rustc_attrs, unix, feature = "close")),
not(all(io_safety_is_in_std, unix, feature = "close")),
not(all(windows, feature = "close"))
))]
fn main() {
println!("On Unix, this example requires Rust nightly (for `rustc_attrs`) and the \"close\" feature.");
println!("On Unix, this example requires Rust nightly (for `io_safety_is_in_std`) and the \"close\" feature.");
}
+8 -8
View File
@@ -1,16 +1,16 @@
//! A simple example implementing the main traits for a type.
#[cfg(not(windows))]
#[cfg(any(feature = "close", not(io_lifetimes_use_std)))]
#[cfg(any(feature = "close", not(io_safety_is_in_std)))]
use io_lifetimes::FromFd;
#[cfg(windows)]
#[cfg(any(feature = "close", not(io_lifetimes_use_std)))]
#[cfg(any(feature = "close", not(io_safety_is_in_std)))]
use io_lifetimes::FromHandle;
#[cfg(not(windows))]
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
use io_lifetimes::IntoFd;
#[cfg(windows)]
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
use io_lifetimes::IntoHandle;
use io_lifetimes::OwnedFilelike;
#[cfg(not(windows))]
@@ -43,7 +43,7 @@ impl AsFd for Thing {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(not(windows))]
impl IntoFd for Thing {
#[inline]
@@ -60,7 +60,7 @@ impl From<Thing> for OwnedFd {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(not(windows))]
impl FromFd for Thing {
#[inline]
@@ -85,7 +85,7 @@ impl AsHandle for Thing {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
impl IntoHandle for Thing {
#[inline]
@@ -102,7 +102,7 @@ impl From<Thing> for OwnedHandle {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
impl FromHandle for Thing {
#[inline]
+2 -2
View File
@@ -1,6 +1,6 @@
//! This is just a sample of what FFI using this crate can look like.
#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
#![cfg_attr(not(io_safety_is_in_std), allow(unused_imports))]
#![allow(missing_docs)]
#[cfg(any(unix, target_os = "wasi"))]
@@ -23,7 +23,7 @@ use {
};
// Declare a few FFI functions ourselves, to show off the FFI ergonomics.
#[cfg(all(rustc_attrs, any(unix, target_os = "wasi")))]
#[cfg(all(io_safety_is_in_std, any(unix, target_os = "wasi")))]
extern "C" {
pub fn open(pathname: *const c_char, flags: c_int, ...) -> Option<OwnedFd>;
}
+21 -22
View File
@@ -28,22 +28,21 @@
//! [from+into conversions]: FromFilelike::from_into_filelike
#![deny(missing_docs)]
#![cfg_attr(rustc_attrs, feature(rustc_attrs))]
// Work around https://github.com/rust-lang/rust/issues/103306.
#![cfg_attr(all(wasi_ext, target_os = "wasi"), feature(wasi_ext))]
mod portability;
mod traits;
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
mod types;
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
mod impls_std;
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(any(unix, target_os = "wasi"))]
pub use traits::AsFd;
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
pub use traits::{AsHandle, AsSocket};
#[cfg(any(unix, target_os = "wasi"))]
@@ -53,23 +52,23 @@ pub use traits::{FromFd, IntoFd};
#[allow(deprecated)]
pub use traits::{FromHandle, FromSocket, IntoHandle, IntoSocket};
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(any(unix, target_os = "wasi"))]
pub use types::{BorrowedFd, OwnedFd};
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
pub use types::{
BorrowedHandle, BorrowedSocket, HandleOrInvalid, InvalidHandleError, NullHandleError,
OwnedHandle, OwnedSocket,
};
#[cfg(io_lifetimes_use_std)]
#[cfg(io_safety_is_in_std)]
#[cfg(unix)]
pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd};
#[cfg(io_lifetimes_use_std)]
#[cfg(io_safety_is_in_std)]
#[cfg(target_os = "wasi")]
pub use std::os::wasi::io::{AsFd, BorrowedFd, OwnedFd};
#[cfg(io_lifetimes_use_std)]
#[cfg(io_safety_is_in_std)]
#[cfg(windows)]
pub use std::os::windows::io::{
AsHandle, AsSocket, BorrowedHandle, BorrowedSocket, HandleOrInvalid, InvalidHandleError,
@@ -87,7 +86,7 @@ pub use std::os::windows::io::{
//
// So we define `FromFd`/`IntoFd` traits, and implement them in terms of
// `From`/`Into`,
#[cfg(io_lifetimes_use_std)]
#[cfg(io_safety_is_in_std)]
#[cfg(any(unix, target_os = "wasi"))]
#[allow(deprecated)]
impl<T: From<OwnedFd>> FromFd for T {
@@ -96,7 +95,7 @@ impl<T: From<OwnedFd>> FromFd for T {
owned_fd.into()
}
}
#[cfg(io_lifetimes_use_std)]
#[cfg(io_safety_is_in_std)]
#[cfg(any(unix, target_os = "wasi"))]
#[allow(deprecated)]
impl<T> IntoFd for T
@@ -109,7 +108,7 @@ where
}
}
#[cfg(io_lifetimes_use_std)]
#[cfg(io_safety_is_in_std)]
#[cfg(windows)]
#[allow(deprecated)]
impl<T: From<OwnedHandle>> FromHandle for T {
@@ -118,7 +117,7 @@ impl<T: From<OwnedHandle>> FromHandle for T {
owned_handle.into()
}
}
#[cfg(io_lifetimes_use_std)]
#[cfg(io_safety_is_in_std)]
#[cfg(windows)]
#[allow(deprecated)]
impl<T> IntoHandle for T
@@ -131,7 +130,7 @@ where
}
}
#[cfg(io_lifetimes_use_std)]
#[cfg(io_safety_is_in_std)]
#[cfg(windows)]
#[allow(deprecated)]
impl<T: From<OwnedSocket>> FromSocket for T {
@@ -140,7 +139,7 @@ impl<T: From<OwnedSocket>> FromSocket for T {
owned_socket.into()
}
}
#[cfg(io_lifetimes_use_std)]
#[cfg(io_safety_is_in_std)]
#[cfg(windows)]
#[allow(deprecated)]
impl<T> IntoSocket for T
@@ -165,22 +164,22 @@ pub mod views;
// Ideally, we'd want crates to implement our traits themselves. But for now,
// while we're prototyping, we provide a few impls on foreign types.
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(feature = "async-std")]
mod impls_async_std;
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(feature = "fs-err")]
mod impls_fs_err;
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(feature = "mio")]
mod impls_mio;
#[cfg(not(target_os = "wasi"))]
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(feature = "os_pipe")]
mod impls_os_pipe;
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(feature = "socket2")]
mod impls_socket2;
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(feature = "tokio")]
mod impls_tokio;
+11 -11
View File
@@ -1,9 +1,9 @@
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(any(unix, target_os = "wasi"))]
use crate::BorrowedFd;
#[cfg(any(unix, target_os = "wasi"))]
use crate::OwnedFd;
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
use crate::{BorrowedHandle, BorrowedSocket};
#[cfg(windows)]
@@ -14,7 +14,7 @@ use crate::{OwnedHandle, OwnedSocket};
/// This is only available on unix platforms and must be imported in order to
/// call the method. Windows platforms have a corresponding `AsHandle` and
/// `AsSocket` set of traits.
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(any(unix, target_os = "wasi"))]
pub trait AsFd {
/// Borrows the file descriptor.
@@ -34,7 +34,7 @@ pub trait AsFd {
}
/// A trait to borrow the handle from an underlying object.
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
pub trait AsHandle {
/// Borrows the handle.
@@ -54,7 +54,7 @@ pub trait AsHandle {
}
/// A trait to borrow the socket from an underlying object.
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
pub trait AsSocket {
/// Borrows the socket.
@@ -235,7 +235,7 @@ pub trait FromSocket {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(any(unix, target_os = "wasi"))]
impl<T: AsFd> AsFd for &T {
#[inline]
@@ -244,7 +244,7 @@ impl<T: AsFd> AsFd for &T {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(any(unix, target_os = "wasi"))]
impl<T: AsFd> AsFd for &mut T {
#[inline]
@@ -253,7 +253,7 @@ impl<T: AsFd> AsFd for &mut T {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
impl<T: AsHandle> AsHandle for &T {
#[inline]
@@ -262,7 +262,7 @@ impl<T: AsHandle> AsHandle for &T {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
impl<T: AsHandle> AsHandle for &mut T {
#[inline]
@@ -271,7 +271,7 @@ impl<T: AsHandle> AsHandle for &mut T {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
impl<T: AsSocket> AsSocket for &T {
#[inline]
@@ -280,7 +280,7 @@ impl<T: AsSocket> AsSocket for &T {
}
}
#[cfg(not(io_lifetimes_use_std))]
#[cfg(not(io_safety_is_in_std))]
#[cfg(windows)]
impl<T: AsSocket> AsSocket for &mut T {
#[inline]
-34
View File
@@ -50,12 +50,6 @@ const INVALID_SOCKET: usize = !0 as _;
#[cfg(any(unix, target_os = "wasi"))]
#[derive(Copy, Clone)]
#[repr(transparent)]
#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)]
#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))]
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
// 32-bit c_int. Below is -2, in two's complement, but that only works out
// because c_int is 32 bits.
#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
pub struct BorrowedFd<'fd> {
fd: RawFd,
_phantom: PhantomData<&'fd OwnedFd>,
@@ -105,17 +99,6 @@ pub struct BorrowedHandle<'handle> {
#[cfg(windows)]
#[derive(Copy, Clone)]
#[repr(transparent)]
#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)]
#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))]
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
#[cfg_attr(
all(rustc_attrs, target_pointer_width = "32"),
rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)
)]
#[cfg_attr(
all(rustc_attrs, target_pointer_width = "64"),
rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
)]
pub struct BorrowedSocket<'socket> {
socket: RawSocket,
_phantom: PhantomData<&'socket OwnedSocket>,
@@ -131,12 +114,6 @@ pub struct BorrowedSocket<'socket> {
/// has the value `-1`.
#[cfg(any(unix, target_os = "wasi"))]
#[repr(transparent)]
#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)]
#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))]
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
// 32-bit c_int. Below is -2, in two's complement, but that only works out
// because c_int is 32 bits.
#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
pub struct OwnedFd {
fd: RawFd,
}
@@ -286,17 +263,6 @@ impl BorrowedHandle<'_> {
/// [`INVALID_SOCKET`].
#[cfg(windows)]
#[repr(transparent)]
#[cfg_attr(rustc_attrs, rustc_nonnull_optimization_guaranteed)]
#[cfg_attr(rustc_attrs, rustc_layout_scalar_valid_range_start(0))]
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
#[cfg_attr(
all(rustc_attrs, target_pointer_width = "32"),
rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)
)]
#[cfg_attr(
all(rustc_attrs, target_pointer_width = "64"),
rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
)]
pub struct OwnedSocket {
socket: RawSocket,
}
+3 -3
View File
@@ -1,4 +1,4 @@
#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
#![cfg_attr(not(io_safety_is_in_std), allow(unused_imports))]
#![cfg(feature = "close")]
#[cfg(any(unix, windows))]
@@ -12,7 +12,7 @@ use windows_sys::Win32::Storage::FileSystem::{
FILE_ATTRIBUTE_NORMAL, FILE_GENERIC_READ, OPEN_EXISTING,
};
#[cfg(all(rustc_attrs, unix))]
#[cfg(all(io_safety_is_in_std, unix))]
#[test]
fn test_file_not_found() {
assert!(unsafe {
@@ -50,7 +50,7 @@ fn test_file_not_found() {
);
}
#[cfg(all(rustc_attrs, unix))]
#[cfg(all(io_safety_is_in_std, unix))]
#[test]
fn test_file_found() {
assert!(unsafe { open("Cargo.toml\0".as_ptr() as *const _, O_RDONLY | O_CLOEXEC) }.is_some());
+3 -3
View File
@@ -1,4 +1,4 @@
#![cfg_attr(not(rustc_attrs), allow(unused_imports))]
#![cfg_attr(not(io_safety_is_in_std), allow(unused_imports))]
#![cfg_attr(target_os = "wasi", feature(wasi_ext))]
use std::mem::size_of;
@@ -15,7 +15,7 @@ use std::os::wasi::io::{FromRawFd, IntoRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{FromRawSocket, IntoRawSocket, RawSocket};
#[cfg(all(rustc_attrs, any(unix, target_os = "wasi")))]
#[cfg(all(io_safety_is_in_std, any(unix, target_os = "wasi")))]
#[test]
fn test_niche_optimizations() {
assert_eq!(size_of::<Option<OwnedFd>>(), size_of::<RawFd>());
@@ -38,7 +38,7 @@ fn test_niche_optimizations() {
}
}
#[cfg(all(rustc_attrs, windows))]
#[cfg(all(io_safety_is_in_std, windows))]
#[test]
fn test_niche_optimizations_socket() {
assert_eq!(size_of::<Option<OwnedSocket>>(), size_of::<RawSocket>());