Mark -1
as an available niche for file descriptors
Based on discussion from https://internals.rust-lang.org/t/can-the-standard-library-shrink-option-file/12768, the file descriptor -1 is chosen based on the POSIX API designs that use it as a sentinel to report errors. A bigger niche could've been chosen, particularly on Linux, but would not necessarily be portable. This PR also adds a test case to ensure that the -1 niche (which is kind of hacky and has no obvious test case) works correctly. It requires the "upper" bound, which is actually -1, to be expressed in two's complement.
This commit is contained in:
parent
d32c320d7e
commit
59abdb6a7e
3 changed files with 25 additions and 5 deletions
|
@ -12,6 +12,11 @@ use crate::sys_common::AsInner;
|
||||||
use libc::{c_int, c_void};
|
use libc::{c_int, c_void};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[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 {
|
pub struct FileDesc {
|
||||||
fd: c_int,
|
fd: c_int,
|
||||||
}
|
}
|
||||||
|
@ -63,7 +68,8 @@ const fn max_iov() -> usize {
|
||||||
|
|
||||||
impl FileDesc {
|
impl FileDesc {
|
||||||
pub fn new(fd: c_int) -> FileDesc {
|
pub fn new(fd: c_int) -> FileDesc {
|
||||||
FileDesc { fd }
|
assert_ne!(fd, -1);
|
||||||
|
unsafe { FileDesc { fd } }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw(&self) -> c_int {
|
pub fn raw(&self) -> c_int {
|
||||||
|
|
|
@ -15,12 +15,19 @@
|
||||||
// padding and overall computed sizes can be quite different.
|
// padding and overall computed sizes can be quite different.
|
||||||
|
|
||||||
#![feature(start)]
|
#![feature(start)]
|
||||||
|
#![feature(rustc_attrs)]
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZeroU32;
|
||||||
|
|
||||||
pub enum MyOption<T> { None, Some(T) }
|
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> {
|
impl<T> Default for MyOption<T> {
|
||||||
fn default() -> Self { MyOption::None }
|
fn default() -> Self { MyOption::None }
|
||||||
}
|
}
|
||||||
|
@ -77,17 +84,18 @@ fn start(_: isize, _: *const *const u8) -> isize {
|
||||||
let _a: MyOption<bool> = Default::default();
|
let _a: MyOption<bool> = Default::default();
|
||||||
let _b: MyOption<char> = Default::default();
|
let _b: MyOption<char> = Default::default();
|
||||||
let _c: MyOption<std::cmp::Ordering> = 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 _e: Enum4<(), char, (), ()> = Enum4::One(());
|
||||||
let _f: Enum4<(), (), bool, ()> = Enum4::One(());
|
let _f: Enum4<(), (), bool, ()> = Enum4::One(());
|
||||||
let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
|
let _g: Enum4<(), (), (), MyOption<u8>> = Enum4::One(());
|
||||||
|
let _h: MyOption<MyNotNegativeOne> = Default::default();
|
||||||
|
|
||||||
// Unions do not currently participate in niche filling.
|
// 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.
|
// ...even when theoretically possible.
|
||||||
let _i: MyOption<Union1<NonZeroU32>> = Default::default();
|
let _j: MyOption<Union1<NonZeroU32>> = Default::default();
|
||||||
let _j: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
|
let _k: MyOption<Union2<NonZeroU32, NonZeroU32>> = Default::default();
|
||||||
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,12 @@ print-type-size variant `Three`: 0 bytes
|
||||||
print-type-size field `.0`: 0 bytes
|
print-type-size field `.0`: 0 bytes
|
||||||
print-type-size variant `Four`: 0 bytes
|
print-type-size variant `Four`: 0 bytes
|
||||||
print-type-size field `.0`: 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 type: `MyOption<char>`: 4 bytes, alignment: 4 bytes
|
||||||
print-type-size variant `Some`: 4 bytes
|
print-type-size variant `Some`: 4 bytes
|
||||||
print-type-size field `.0`: 4 bytes
|
print-type-size field `.0`: 4 bytes
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue