Use generic NonZero
.
This commit is contained in:
parent
7531eafa7e
commit
bd8e565e16
22 changed files with 83 additions and 82 deletions
|
@ -2,6 +2,7 @@ use std::borrow::{Borrow, Cow};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use std::iter;
|
use std::iter;
|
||||||
|
use std::num::NonZero;
|
||||||
use std::ops::Bound;
|
use std::ops::Bound;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
|
@ -10,8 +11,8 @@ use tracing::debug;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Abi, AbiAndPrefAlign, Align, FieldsShape, IndexSlice, IndexVec, Integer, LayoutS, Niche,
|
Abi, AbiAndPrefAlign, Align, FieldsShape, IndexSlice, IndexVec, Integer, LayoutS, Niche,
|
||||||
NonZeroUsize, Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout,
|
Primitive, ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, Variants,
|
||||||
Variants, WrappingRange,
|
WrappingRange,
|
||||||
};
|
};
|
||||||
|
|
||||||
// A variant is absent if it's uninhabited and only has ZST fields.
|
// A variant is absent if it's uninhabited and only has ZST fields.
|
||||||
|
@ -327,7 +328,7 @@ pub trait LayoutCalculator {
|
||||||
|
|
||||||
Some(LayoutS {
|
Some(LayoutS {
|
||||||
variants: Variants::Single { index: VariantIdx::new(0) },
|
variants: Variants::Single { index: VariantIdx::new(0) },
|
||||||
fields: FieldsShape::Union(NonZeroUsize::new(only_variant.len())?),
|
fields: FieldsShape::Union(NonZero::new(only_variant.len())?),
|
||||||
abi,
|
abi,
|
||||||
largest_niche: None,
|
largest_niche: None,
|
||||||
align,
|
align,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
|
#![cfg_attr(feature = "nightly", feature(rustdoc_internals))]
|
||||||
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::num::{NonZeroUsize, ParseIntError};
|
use std::num::{NonZero, ParseIntError};
|
||||||
use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
|
use std::ops::{Add, AddAssign, Mul, RangeInclusive, Sub};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
@ -1149,7 +1149,7 @@ pub enum FieldsShape<FieldIdx: Idx> {
|
||||||
Primitive,
|
Primitive,
|
||||||
|
|
||||||
/// All fields start at no offset. The `usize` is the field count.
|
/// All fields start at no offset. The `usize` is the field count.
|
||||||
Union(NonZeroUsize),
|
Union(NonZero<usize>),
|
||||||
|
|
||||||
/// Array/vector-like placement, with all fields of identical types.
|
/// Array/vector-like placement, with all fields of identical types.
|
||||||
Array { stride: Size, count: u64 },
|
Array { stride: Size, count: u64 },
|
||||||
|
|
|
@ -2164,7 +2164,7 @@ pub enum TyKind {
|
||||||
MacCall(P<MacCall>),
|
MacCall(P<MacCall>),
|
||||||
/// Placeholder for a `va_list`.
|
/// Placeholder for a `va_list`.
|
||||||
CVarArgs,
|
CVarArgs,
|
||||||
/// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZeroU32`,
|
/// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`,
|
||||||
/// just as part of the type system.
|
/// just as part of the type system.
|
||||||
Pat(P<Ty>, P<Pat>),
|
Pat(P<Ty>, P<Pat>),
|
||||||
/// Sometimes we need a dummy value when no error has occurred.
|
/// Sometimes we need a dummy value when no error has occurred.
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::ty::{Align, IndexedVal, Ty, VariantIdx};
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
use crate::Opaque;
|
use crate::Opaque;
|
||||||
use std::fmt::{self, Debug};
|
use std::fmt::{self, Debug};
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZero;
|
||||||
use std::ops::RangeInclusive;
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
/// A function ABI definition.
|
/// A function ABI definition.
|
||||||
|
@ -133,7 +133,7 @@ pub enum FieldsShape {
|
||||||
Primitive,
|
Primitive,
|
||||||
|
|
||||||
/// All fields start at no offset. The `usize` is the field count.
|
/// All fields start at no offset. The `usize` is the field count.
|
||||||
Union(NonZeroUsize),
|
Union(NonZero<usize>),
|
||||||
|
|
||||||
/// Array/vector-like placement, with all fields of identical types.
|
/// Array/vector-like placement, with all fields of identical types.
|
||||||
Array { stride: Size, count: u64 },
|
Array { stride: Size, count: u64 },
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
intrinsics,
|
intrinsics,
|
||||||
iter::{from_fn, TrustedLen, TrustedRandomAccess},
|
iter::{from_fn, TrustedLen, TrustedRandomAccess},
|
||||||
num::NonZeroUsize,
|
num::NonZero,
|
||||||
ops::{Range, Try},
|
ops::{Range, Try},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -42,10 +42,10 @@ impl<I> StepBy<I> {
|
||||||
/// The `step` that was originally passed to `Iterator::step_by(step)`,
|
/// The `step` that was originally passed to `Iterator::step_by(step)`,
|
||||||
/// aka `self.step_minus_one + 1`.
|
/// aka `self.step_minus_one + 1`.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn original_step(&self) -> NonZeroUsize {
|
fn original_step(&self) -> NonZero<usize> {
|
||||||
// SAFETY: By type invariant, `step_minus_one` cannot be `MAX`, which
|
// SAFETY: By type invariant, `step_minus_one` cannot be `MAX`, which
|
||||||
// means the addition cannot overflow and the result cannot be zero.
|
// means the addition cannot overflow and the result cannot be zero.
|
||||||
unsafe { NonZeroUsize::new_unchecked(intrinsics::unchecked_add(self.step_minus_one, 1)) }
|
unsafe { NonZero::new_unchecked(intrinsics::unchecked_add(self.step_minus_one, 1)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,12 +231,12 @@ unsafe impl<I: Iterator> StepByImpl<I> for StepBy<I> {
|
||||||
#[inline]
|
#[inline]
|
||||||
default fn spec_size_hint(&self) -> (usize, Option<usize>) {
|
default fn spec_size_hint(&self) -> (usize, Option<usize>) {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn first_size(step: NonZeroUsize) -> impl Fn(usize) -> usize {
|
fn first_size(step: NonZero<usize>) -> impl Fn(usize) -> usize {
|
||||||
move |n| if n == 0 { 0 } else { 1 + (n - 1) / step }
|
move |n| if n == 0 { 0 } else { 1 + (n - 1) / step }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn other_size(step: NonZeroUsize) -> impl Fn(usize) -> usize {
|
fn other_size(step: NonZero<usize>) -> impl Fn(usize) -> usize {
|
||||||
move |n| n / step
|
move |n| n / step
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,7 @@ fn main() {
|
||||||
let num_threads = if let Some(num) = env::var_os("BUILD_MANIFEST_NUM_THREADS") {
|
let num_threads = if let Some(num) = env::var_os("BUILD_MANIFEST_NUM_THREADS") {
|
||||||
num.to_str().unwrap().parse().expect("invalid number for BUILD_MANIFEST_NUM_THREADS")
|
num.to_str().unwrap().parse().expect("invalid number for BUILD_MANIFEST_NUM_THREADS")
|
||||||
} else {
|
} else {
|
||||||
std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get)
|
std::thread::available_parallelism().map_or(1, std::num::NonZero::get)
|
||||||
};
|
};
|
||||||
rayon::ThreadPoolBuilder::new()
|
rayon::ThreadPoolBuilder::new()
|
||||||
.num_threads(num_threads)
|
.num_threads(num_threads)
|
||||||
|
|
|
@ -87,7 +87,7 @@ pub(super) fn check<'tcx>(
|
||||||
&& is_normalizable(cx, cx.param_env, from_ty)
|
&& is_normalizable(cx, cx.param_env, from_ty)
|
||||||
&& is_normalizable(cx, cx.param_env, to_ty)
|
&& is_normalizable(cx, cx.param_env, to_ty)
|
||||||
// we only want to lint if the target type has a niche that is larger than the one of the source type
|
// we only want to lint if the target type has a niche that is larger than the one of the source type
|
||||||
// e.g. `u8` to `NonZeroU8` should lint, but `NonZeroU8` to `u8` should not
|
// e.g. `u8` to `NonZero<u8>` should lint, but `NonZero<u8>` to `u8` should not
|
||||||
&& let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from_ty))
|
&& let Ok(from_layout) = cx.tcx.layout_of(cx.param_env.and(from_ty))
|
||||||
&& let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to_ty))
|
&& let Ok(to_layout) = cx.tcx.layout_of(cx.param_env.and(to_ty))
|
||||||
&& match (from_layout.largest_niche, to_layout.largest_niche) {
|
&& match (from_layout.largest_niche, to_layout.largest_niche) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZero;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Parser)]
|
#[derive(Clone, Debug, Parser)]
|
||||||
|
@ -61,7 +61,7 @@ impl LintcheckConfig {
|
||||||
config.max_jobs = if config.fix || config.recursive {
|
config.max_jobs = if config.fix || config.recursive {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
std::thread::available_parallelism().map_or(1, NonZeroUsize::get)
|
std::thread::available_parallelism().map_or(1, NonZero::get)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
extern crate proc_macro_derive;
|
extern crate proc_macro_derive;
|
||||||
|
|
||||||
use core::num::{NonZeroUsize, Saturating, Wrapping};
|
use core::num::{NonZero, Saturating, Wrapping};
|
||||||
|
|
||||||
const ONE: i32 = 1;
|
const ONE: i32 = 1;
|
||||||
const ZERO: i32 = 0;
|
const ZERO: i32 = 0;
|
||||||
|
@ -494,15 +494,15 @@ pub fn issue_11262() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn issue_11392() {
|
pub fn issue_11392() {
|
||||||
fn example_div(unsigned: usize, nonzero_unsigned: NonZeroUsize) -> usize {
|
fn example_div(unsigned: usize, nonzero_unsigned: NonZero<usize>) -> usize {
|
||||||
unsigned / nonzero_unsigned
|
unsigned / nonzero_unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
fn example_rem(unsigned: usize, nonzero_unsigned: NonZeroUsize) -> usize {
|
fn example_rem(unsigned: usize, nonzero_unsigned: NonZero<usize>) -> usize {
|
||||||
unsigned % nonzero_unsigned
|
unsigned % nonzero_unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
let (unsigned, nonzero_unsigned) = (0, NonZeroUsize::new(1).unwrap());
|
let (unsigned, nonzero_unsigned) = (0, NonZero::new(1).unwrap());
|
||||||
example_div(unsigned, nonzero_unsigned);
|
example_div(unsigned, nonzero_unsigned);
|
||||||
example_rem(unsigned, nonzero_unsigned);
|
example_rem(unsigned, nonzero_unsigned);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#![warn(clippy::eager_transmute)]
|
#![warn(clippy::eager_transmute)]
|
||||||
#![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)]
|
#![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)]
|
||||||
|
|
||||||
use std::num::NonZeroU8;
|
use std::num::NonZero;
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum Opcode {
|
enum Opcode {
|
||||||
|
@ -85,21 +85,21 @@ macro_rules! impls {
|
||||||
}
|
}
|
||||||
impls!(NonMaxU8, NonZeroNonMaxU8);
|
impls!(NonMaxU8, NonZeroNonMaxU8);
|
||||||
|
|
||||||
fn niche_tests(v1: u8, v2: NonZeroU8, v3: NonZeroNonMaxU8) {
|
fn niche_tests(v1: u8, v2: NonZero<u8>, v3: NonZeroNonMaxU8) {
|
||||||
// u8 -> NonZeroU8, do lint
|
// u8 -> NonZero<u8>, do lint
|
||||||
let _: Option<NonZeroU8> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) });
|
let _: Option<NonZero<u8>> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) });
|
||||||
|
|
||||||
// NonZeroU8 -> u8, don't lint, target type has no niche and therefore a higher validity range
|
// NonZero<u8> -> u8, don't lint, target type has no niche and therefore a higher validity range
|
||||||
let _: Option<u8> = (v2 > NonZeroU8::new(1).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
let _: Option<u8> = (v2 > NonZero::new(1u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
||||||
|
|
||||||
// NonZeroU8 -> NonMaxU8, do lint, different niche
|
// NonZero<u8> -> NonMaxU8, do lint, different niche
|
||||||
let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
|
let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
|
||||||
|
|
||||||
// NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity
|
// NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity
|
||||||
let _: Option<NonMaxU8> = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) });
|
let _: Option<NonMaxU8> = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) });
|
||||||
|
|
||||||
// NonZeroU8 -> NonZeroNonMaxU8, do lint, target type has less validity
|
// NonZero<u8> -> NonZeroNonMaxU8, do lint, target type has less validity
|
||||||
let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
|
let _: Option<NonZeroNonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#![warn(clippy::eager_transmute)]
|
#![warn(clippy::eager_transmute)]
|
||||||
#![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)]
|
#![allow(clippy::transmute_int_to_non_zero, clippy::missing_transmute_annotations)]
|
||||||
|
|
||||||
use std::num::NonZeroU8;
|
use std::num::NonZero;
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
enum Opcode {
|
enum Opcode {
|
||||||
|
@ -85,21 +85,21 @@ macro_rules! impls {
|
||||||
}
|
}
|
||||||
impls!(NonMaxU8, NonZeroNonMaxU8);
|
impls!(NonMaxU8, NonZeroNonMaxU8);
|
||||||
|
|
||||||
fn niche_tests(v1: u8, v2: NonZeroU8, v3: NonZeroNonMaxU8) {
|
fn niche_tests(v1: u8, v2: NonZero<u8>, v3: NonZeroNonMaxU8) {
|
||||||
// u8 -> NonZeroU8, do lint
|
// u8 -> NonZero<u8>, do lint
|
||||||
let _: Option<NonZeroU8> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
|
let _: Option<NonZero<u8>> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
|
||||||
|
|
||||||
// NonZeroU8 -> u8, don't lint, target type has no niche and therefore a higher validity range
|
// NonZero<u8> -> u8, don't lint, target type has no niche and therefore a higher validity range
|
||||||
let _: Option<u8> = (v2 > NonZeroU8::new(1).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
let _: Option<u8> = (v2 > NonZero::new(1u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
||||||
|
|
||||||
// NonZeroU8 -> NonMaxU8, do lint, different niche
|
// NonZero<u8> -> NonMaxU8, do lint, different niche
|
||||||
let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
||||||
|
|
||||||
// NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity
|
// NonZeroNonMaxU8 -> NonMaxU8, don't lint, target type has more validity
|
||||||
let _: Option<NonMaxU8> = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) });
|
let _: Option<NonMaxU8> = (v3 < 255).then_some(unsafe { std::mem::transmute(v2) });
|
||||||
|
|
||||||
// NonZeroU8 -> NonZeroNonMaxU8, do lint, target type has less validity
|
// NonZero<u8> -> NonZeroNonMaxU8, do lint, target type has less validity
|
||||||
let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
let _: Option<NonZeroNonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
|
|
@ -155,36 +155,36 @@ LL | (op < 4).then(|| std::mem::transmute::<_, Opcode>(op));
|
||||||
| ~~~~ ++
|
| ~~~~ ++
|
||||||
|
|
||||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||||
--> tests/ui/eager_transmute.rs:90:60
|
--> tests/ui/eager_transmute.rs:90:62
|
||||||
|
|
|
|
||||||
LL | let _: Option<NonZeroU8> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
|
LL | let _: Option<NonZero<u8>> = (v1 > 0).then_some(unsafe { std::mem::transmute(v1) });
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider using `bool::then` to only transmute if the condition holds
|
help: consider using `bool::then` to only transmute if the condition holds
|
||||||
|
|
|
|
||||||
LL | let _: Option<NonZeroU8> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) });
|
LL | let _: Option<NonZero<u8>> = (v1 > 0).then(|| unsafe { std::mem::transmute(v1) });
|
||||||
| ~~~~ ++
|
| ~~~~ ++
|
||||||
|
|
||||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||||
--> tests/ui/eager_transmute.rs:96:86
|
--> tests/ui/eager_transmute.rs:96:86
|
||||||
|
|
|
|
||||||
LL | let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
LL | let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider using `bool::then` to only transmute if the condition holds
|
help: consider using `bool::then` to only transmute if the condition holds
|
||||||
|
|
|
|
||||||
LL | let _: Option<NonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
|
LL | let _: Option<NonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
|
||||||
| ~~~~ ++
|
| ~~~~ ++
|
||||||
|
|
||||||
error: this transmute is always evaluated eagerly, even if the condition is false
|
error: this transmute is always evaluated eagerly, even if the condition is false
|
||||||
--> tests/ui/eager_transmute.rs:102:93
|
--> tests/ui/eager_transmute.rs:102:93
|
||||||
|
|
|
|
||||||
LL | let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
LL | let _: Option<NonZeroNonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then_some(unsafe { std::mem::transmute(v2) });
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
|
||||||
help: consider using `bool::then` to only transmute if the condition holds
|
help: consider using `bool::then` to only transmute if the condition holds
|
||||||
|
|
|
|
||||||
LL | let _: Option<NonZeroNonMaxU8> = (v2 < NonZeroU8::new(255).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
|
LL | let _: Option<NonZeroNonMaxU8> = (v2 < NonZero::new(255u8).unwrap()).then(|| unsafe { std::mem::transmute(v2) });
|
||||||
| ~~~~ ++
|
| ~~~~ ++
|
||||||
|
|
||||||
error: aborting due to 17 previous errors
|
error: aborting due to 17 previous errors
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#![feature(custom_mir)]
|
#![feature(custom_mir)]
|
||||||
|
|
||||||
use std::intrinsics::mir::*;
|
use std::intrinsics::mir::*;
|
||||||
use std::num::NonZeroI32;
|
use std::num::NonZero;
|
||||||
|
|
||||||
// We define our own option type so that we can control the variant indices.
|
// We define our own option type so that we can control the variant indices.
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -13,7 +13,7 @@ enum Option<T> {
|
||||||
use Option::*;
|
use Option::*;
|
||||||
|
|
||||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||||
fn set_discriminant(ptr: &mut Option<NonZeroI32>) {
|
fn set_discriminant(ptr: &mut Option<NonZero<i32>>) {
|
||||||
mir! {
|
mir! {
|
||||||
{
|
{
|
||||||
// We set the discriminant to `Some`, which is a NOP since this is the niched variant.
|
// We set the discriminant to `Some`, which is a NOP since this is the niched variant.
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::num::*;
|
use std::num::NonZero;
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct S1(NonZeroI32);
|
struct S1(NonZero<i32>);
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
struct S2(i32);
|
struct S2(i32);
|
||||||
|
@ -11,6 +11,6 @@ fn callee(_s: S2) {}
|
||||||
fn main() {
|
fn main() {
|
||||||
let fnptr: fn(S2) = callee;
|
let fnptr: fn(S2) = callee;
|
||||||
let fnptr: fn(S1) = unsafe { std::mem::transmute(fnptr) };
|
let fnptr: fn(S1) = unsafe { std::mem::transmute(fnptr) };
|
||||||
fnptr(S1(NonZeroI32::new(1).unwrap()));
|
fnptr(S1(NonZero::new(1).unwrap()));
|
||||||
//~^ ERROR: calling a function with argument of type S2 passing data of type S1
|
//~^ ERROR: calling a function with argument of type S2 passing data of type S1
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
error: Undefined Behavior: calling a function with argument of type S2 passing data of type S1
|
error: Undefined Behavior: calling a function with argument of type S2 passing data of type S1
|
||||||
--> $DIR/abi_mismatch_repr_C.rs:LL:CC
|
--> $DIR/abi_mismatch_repr_C.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | fnptr(S1(NonZeroI32::new(1).unwrap()));
|
LL | fnptr(S1(NonZero::new(1).unwrap()));
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type S2 passing data of type S1
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ calling a function with argument of type S2 passing data of type S1
|
||||||
|
|
|
|
||||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||||
|
|
|
@ -2,15 +2,15 @@
|
||||||
#![feature(core_intrinsics, custom_mir)]
|
#![feature(core_intrinsics, custom_mir)]
|
||||||
|
|
||||||
use std::intrinsics::mir::*;
|
use std::intrinsics::mir::*;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZero;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
// This function supposedly returns a NonZeroU32, but actually returns something invalid in a way that
|
// This function supposedly returns a `NonZero<u32>`, but actually returns something invalid in a way that
|
||||||
// never materializes a bad NonZeroU32 value: we take a pointer to the return place and cast the pointer
|
// never materializes a bad `NonZero<u32>` value: we take a pointer to the return place and cast the pointer
|
||||||
// type. That way we never get an "invalid value constructed" error inside the function, it can
|
// type. That way we never get an "invalid value constructed" error inside the function, it can
|
||||||
// only possibly be detected when the return value is passed to the caller.
|
// only possibly be detected when the return value is passed to the caller.
|
||||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||||
fn f() -> NonZeroU32 {
|
fn f() -> NonZero<u32> {
|
||||||
mir! {
|
mir! {
|
||||||
{
|
{
|
||||||
let tmp = ptr::addr_of_mut!(RET);
|
let tmp = ptr::addr_of_mut!(RET);
|
||||||
|
@ -22,7 +22,7 @@ fn f() -> NonZeroU32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let f: fn() -> u32 = unsafe { std::mem::transmute(f as fn() -> NonZeroU32) };
|
let f: fn() -> u32 = unsafe { std::mem::transmute(f as fn() -> NonZero<u32>) };
|
||||||
// There's a NonZeroU32-to-u32 transmute happening here
|
// There's a `NonZero<u32>` to `u32` transmute happening here.
|
||||||
f(); //~ERROR: expected something greater or equal to 1
|
f(); //~ERROR: expected something greater or equal to 1
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,24 +2,24 @@
|
||||||
#![feature(core_intrinsics, custom_mir)]
|
#![feature(core_intrinsics, custom_mir)]
|
||||||
|
|
||||||
use std::intrinsics::mir::*;
|
use std::intrinsics::mir::*;
|
||||||
use std::num::NonZeroU32;
|
use std::num::NonZero;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
fn f(c: u32) {
|
fn f(c: u32) {
|
||||||
println!("{c}");
|
println!("{c}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Call that function in a bad way, with an invalid NonZeroU32, but without
|
// Call that function in a bad way, with an invalid `NonZero<u32>`, but without
|
||||||
// ever materializing this as a NonZeroU32 value outside the call itself.
|
// ever materializing this as a `NonZero<u32>` value outside the call itself.
|
||||||
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
#[custom_mir(dialect = "runtime", phase = "optimized")]
|
||||||
fn call(f: fn(NonZeroU32)) {
|
fn call(f: fn(NonZero<u32>)) {
|
||||||
mir! {
|
mir! {
|
||||||
let _res: ();
|
let _res: ();
|
||||||
{
|
{
|
||||||
let c = 0;
|
let c = 0;
|
||||||
let tmp = ptr::addr_of!(c);
|
let tmp = ptr::addr_of!(c);
|
||||||
let ptr = tmp as *const NonZeroU32;
|
let ptr = tmp as *const NonZero<u32>;
|
||||||
// The call site now is a NonZeroU32-to-u32 transmute.
|
// The call site now is a `NonZero<u32>` to `u32` transmute.
|
||||||
Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) //~ERROR: expected something greater or equal to 1
|
Call(_res = f(*ptr), ReturnTo(retblock), UnwindContinue()) //~ERROR: expected something greater or equal to 1
|
||||||
}
|
}
|
||||||
retblock = {
|
retblock = {
|
||||||
|
@ -29,6 +29,6 @@ fn call(f: fn(NonZeroU32)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let f: fn(NonZeroU32) = unsafe { std::mem::transmute(f as fn(u32)) };
|
let f: fn(NonZero<u32>) = unsafe { std::mem::transmute(f as fn(u32)) };
|
||||||
call(f);
|
call(f);
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ fn main() {
|
||||||
test_abi_compat(0usize, 0u64);
|
test_abi_compat(0usize, 0u64);
|
||||||
test_abi_compat(0isize, 0i64);
|
test_abi_compat(0isize, 0i64);
|
||||||
}
|
}
|
||||||
test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap());
|
test_abi_compat(42u32, num::NonZero::new(1u32).unwrap());
|
||||||
// - `char` and `u32`.
|
// - `char` and `u32`.
|
||||||
test_abi_compat(42u32, 'x');
|
test_abi_compat(42u32, 'x');
|
||||||
// - Reference/pointer types with the same pointee.
|
// - Reference/pointer types with the same pointee.
|
||||||
|
@ -86,9 +86,9 @@ fn main() {
|
||||||
// - Guaranteed null-pointer-optimizations (RFC 3391).
|
// - Guaranteed null-pointer-optimizations (RFC 3391).
|
||||||
test_abi_compat(&0u32 as *const u32, Some(&0u32));
|
test_abi_compat(&0u32 as *const u32, Some(&0u32));
|
||||||
test_abi_compat(main as fn(), Some(main as fn()));
|
test_abi_compat(main as fn(), Some(main as fn()));
|
||||||
test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap()));
|
test_abi_compat(0u32, Some(num::NonZero::new(1u32).unwrap()));
|
||||||
test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32)));
|
test_abi_compat(&0u32 as *const u32, Some(Wrapper(&0u32)));
|
||||||
test_abi_compat(0u32, Some(Wrapper(num::NonZeroU32::new(1).unwrap())));
|
test_abi_compat(0u32, Some(Wrapper(num::NonZero::new(1u32).unwrap())));
|
||||||
|
|
||||||
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
|
// These must work for *any* type, since we guarantee that `repr(transparent)` is ABI-compatible
|
||||||
// with the wrapped field.
|
// with the wrapped field.
|
||||||
|
@ -102,7 +102,7 @@ fn main() {
|
||||||
test_abi_newtype::<[u32; 2]>();
|
test_abi_newtype::<[u32; 2]>();
|
||||||
test_abi_newtype::<[u32; 32]>();
|
test_abi_newtype::<[u32; 32]>();
|
||||||
test_abi_newtype::<Option<i32>>();
|
test_abi_newtype::<Option<i32>>();
|
||||||
test_abi_newtype::<Option<num::NonZeroU32>>();
|
test_abi_newtype::<Option<num::NonZero<u32>>>();
|
||||||
|
|
||||||
// Extra test for assumptions made by arbitrary-self-dyn-receivers.
|
// Extra test for assumptions made by arbitrary-self-dyn-receivers.
|
||||||
// This is interesting since these types are not `repr(transparent)`. So this is not part of our
|
// This is interesting since these types are not `repr(transparent)`. So this is not part of our
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
//@compile-flags: -Zmiri-num-cpus=1024
|
//@compile-flags: -Zmiri-num-cpus=1024
|
||||||
|
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZero;
|
||||||
use std::thread::available_parallelism;
|
use std::thread::available_parallelism;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
assert_eq!(available_parallelism().unwrap(), NonZeroUsize::new(1024).unwrap());
|
assert_eq!(available_parallelism().unwrap(), NonZero::new(1024).unwrap());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use std::ffi::OsString;
|
use std::ffi::OsString;
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZero;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::sync::OnceLock;
|
use std::sync::OnceLock;
|
||||||
use std::{env, process::Command};
|
use std::{env, process::Command};
|
||||||
|
@ -76,7 +76,7 @@ fn miri_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
|
||||||
edition: Some("2021".into()), // keep in sync with `./miri run`
|
edition: Some("2021".into()), // keep in sync with `./miri run`
|
||||||
threads: std::env::var("MIRI_TEST_THREADS")
|
threads: std::env::var("MIRI_TEST_THREADS")
|
||||||
.ok()
|
.ok()
|
||||||
.map(|threads| NonZeroUsize::new(threads.parse().unwrap()).unwrap()),
|
.map(|threads| NonZero::new(threads.parse().unwrap()).unwrap()),
|
||||||
..Config::rustc(path)
|
..Config::rustc(path)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ fn check_result(abi: &ArgAbi) {
|
||||||
assert_matches!(layout.variants, VariantsShape::Multiple { .. })
|
assert_matches!(layout.variants, VariantsShape::Multiple { .. })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check the niche information about: `NonZeroU8`
|
/// Checks the niche information about `NonZero<u8>`.
|
||||||
fn check_niche(abi: &ArgAbi) {
|
fn check_niche(abi: &ArgAbi) {
|
||||||
assert!(abi.ty.kind().is_struct());
|
assert!(abi.ty.kind().is_struct());
|
||||||
assert_matches!(abi.mode, PassMode::Direct { .. });
|
assert_matches!(abi.mode, PassMode::Direct { .. });
|
||||||
|
@ -150,12 +150,12 @@ fn generate_input(path: &str) -> std::io::Result<()> {
|
||||||
#![feature(c_variadic)]
|
#![feature(c_variadic)]
|
||||||
#![allow(unused_variables)]
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
use std::num::NonZeroU8;
|
use std::num::NonZero;
|
||||||
|
|
||||||
pub fn fn_abi(
|
pub fn fn_abi(
|
||||||
ignore: [u8; 0],
|
ignore: [u8; 0],
|
||||||
primitive: char,
|
primitive: char,
|
||||||
niche: NonZeroU8,
|
niche: NonZero<u8>,
|
||||||
) -> Result<usize, &'static str> {{
|
) -> Result<usize, &'static str> {{
|
||||||
// We only care about the signature.
|
// We only care about the signature.
|
||||||
todo!()
|
todo!()
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
use std::pat::pattern_type;
|
use std::pat::pattern_type;
|
||||||
|
|
||||||
type X = std::num::NonZeroU32;
|
type X = std::num::NonZero<u32>;
|
||||||
type Y = pattern_type!(u32 is 1..);
|
type Y = pattern_type!(u32 is 1..);
|
||||||
type Z = Option<pattern_type!(u32 is 1..)>;
|
type Z = Option<pattern_type!(u32 is 1..)>;
|
||||||
struct NonZeroU32New(pattern_type!(u32 is 1..));
|
struct NonZeroU32New(pattern_type!(u32 is 1..));
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue