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

Mark -1 as an available niche for file descriptors #74699

Merged
merged 4 commits into from
Dec 20, 2020
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
9 changes: 8 additions & 1 deletion library/std/src/sys/unix/fd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ use crate::sys_common::AsInner;
use libc::{c_int, c_void};

#[derive(Debug)]
#[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.
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
pub struct FileDesc {
fd: c_int,
}
Expand Down Expand Up @@ -63,7 +68,9 @@ const fn max_iov() -> usize {

impl FileDesc {
pub fn new(fd: c_int) -> FileDesc {
FileDesc { fd }
assert_ne!(fd, -1i32);
Copy link
Contributor

@vi vi Dec 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will there be unsafe fn new_unchecked, to avoid including panicking code in a program that otherwise avoid it?

If this is a private type, not directly available in public API, will panicking and string formatting code suddenly appear in places where it was absent before, breaking things like no-panic?

// SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
unsafe { FileDesc { fd } }
notriddle marked this conversation as resolved.
Show resolved Hide resolved
}

pub fn raw(&self) -> c_int {
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/unix/fd/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::mem::ManuallyDrop;

#[test]
fn limit_vector_count() {
let stdout = ManuallyDrop::new(FileDesc { fd: 1 });
let stdout = ManuallyDrop::new(unsafe { FileDesc { fd: 1 } });
let bufs = (0..1500).map(|_| IoSlice::new(&[])).collect::<Vec<_>>();
assert!(stdout.write_vectored(&bufs).is_ok());
}
16 changes: 12 additions & 4 deletions src/test/ui/print_type_sizes/niche-filling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,19 @@
// padding and overall computed sizes can be quite different.

#![feature(start)]
#![feature(rustc_attrs)]
#![allow(dead_code)]

use std::num::NonZeroU32;

pub enum MyOption<T> { None, Some(T) }

#[rustc_layout_scalar_valid_range_start(0)]
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
pub struct MyNotNegativeOne {
_i: i32,
}

impl<T> Default for MyOption<T> {
fn default() -> Self { MyOption::None }
}
Expand Down Expand Up @@ -77,17 +84,18 @@ fn start(_: isize, _: *const *const u8) -> isize {
let _a: MyOption<bool> = Default::default();
let _b: MyOption<char> = Default::default();
let _c: MyOption<std::cmp::Ordering> = Default::default();
let _b: MyOption<MyOption<u8>> = Default::default();
let _d: MyOption<MyOption<u8>> = Default::default();
let _e: Enum4<(), char, (), ()> = Enum4::One(());
let _f: Enum4<(), (), bool, ()> = Enum4::One(());
let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
let _h: MyOption<MyNotNegativeOne> = Default::default();

// Unions do not currently participate in niche filling.
let _h: MyOption<Union2<NonZeroU32, u32>> = Default::default();
let _i: MyOption<Union2<NonZeroU32, u32>> = Default::default();

// ...even when theoretically possible.
let _i: MyOption<Union1<NonZeroU32>> = Default::default();
let _j: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
let _j: MyOption<Union1<NonZeroU32>> = Default::default();
let _k: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();

0
}
6 changes: 6 additions & 0 deletions src/test/ui/print_type_sizes/niche-filling.stdout
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,12 @@ print-type-size variant `Three`: 0 bytes
print-type-size field `.0`: 0 bytes
print-type-size variant `Four`: 0 bytes
print-type-size field `.0`: 0 bytes
print-type-size type: `MyNotNegativeOne`: 4 bytes, alignment: 4 bytes
print-type-size field `._i`: 4 bytes
print-type-size type: `MyOption<MyNotNegativeOne>`: 4 bytes, alignment: 4 bytes
print-type-size variant `Some`: 4 bytes
print-type-size field `.0`: 4 bytes
print-type-size variant `None`: 0 bytes
print-type-size type: `MyOption<char>`: 4 bytes, alignment: 4 bytes
print-type-size variant `Some`: 4 bytes
print-type-size field `.0`: 4 bytes
Expand Down