Skip to content

Commit bf19196

Browse files
committed
Auto merge of rust-lang#120165 - reitermarkus:nonzero-switch-alias-direction, r=dtolnay
Switch `NonZero` alias direction. Step 4 mentioned in rust-lang#100428 (review). Depends on rust-lang#120160. r? `@dtolnay`
2 parents 6351247 + 021739c commit bf19196

22 files changed

+208
-190
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+29-25
Original file line numberDiff line numberDiff line change
@@ -2140,46 +2140,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21402140
expr_ty: Ty<'tcx>,
21412141
) -> bool {
21422142
let tcx = self.tcx;
2143-
let (adt, unwrap) = match expected.kind() {
2143+
let (adt, substs, unwrap) = match expected.kind() {
21442144
// In case Option<NonZero*> is wanted, but * is provided, suggest calling new
2145-
ty::Adt(adt, args) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
2146-
// Unwrap option
2147-
let ty::Adt(adt, _) = args.type_at(0).kind() else {
2145+
ty::Adt(adt, substs) if tcx.is_diagnostic_item(sym::Option, adt.did()) => {
2146+
let nonzero_type = substs.type_at(0); // Unwrap option type.
2147+
let ty::Adt(adt, substs) = nonzero_type.kind() else {
21482148
return false;
21492149
};
2150-
2151-
(adt, "")
2150+
(adt, substs, "")
21522151
}
2153-
// In case NonZero* is wanted, but * is provided also add `.unwrap()` to satisfy types
2154-
ty::Adt(adt, _) => (adt, ".unwrap()"),
2152+
// In case `NonZero<*>` is wanted but `*` is provided, also add `.unwrap()` to satisfy types.
2153+
ty::Adt(adt, substs) => (adt, substs, ".unwrap()"),
21552154
_ => return false,
21562155
};
21572156

2158-
let map = [
2159-
(sym::NonZeroU8, tcx.types.u8),
2160-
(sym::NonZeroU16, tcx.types.u16),
2161-
(sym::NonZeroU32, tcx.types.u32),
2162-
(sym::NonZeroU64, tcx.types.u64),
2163-
(sym::NonZeroU128, tcx.types.u128),
2164-
(sym::NonZeroI8, tcx.types.i8),
2165-
(sym::NonZeroI16, tcx.types.i16),
2166-
(sym::NonZeroI32, tcx.types.i32),
2167-
(sym::NonZeroI64, tcx.types.i64),
2168-
(sym::NonZeroI128, tcx.types.i128),
2157+
if !self.tcx.is_diagnostic_item(sym::NonZero, adt.did()) {
2158+
return false;
2159+
}
2160+
2161+
// FIXME: This can be simplified once `NonZero<T>` is stable.
2162+
let coercable_types = [
2163+
("NonZeroU8", tcx.types.u8),
2164+
("NonZeroU16", tcx.types.u16),
2165+
("NonZeroU32", tcx.types.u32),
2166+
("NonZeroU64", tcx.types.u64),
2167+
("NonZeroU128", tcx.types.u128),
2168+
("NonZeroI8", tcx.types.i8),
2169+
("NonZeroI16", tcx.types.i16),
2170+
("NonZeroI32", tcx.types.i32),
2171+
("NonZeroI64", tcx.types.i64),
2172+
("NonZeroI128", tcx.types.i128),
21692173
];
21702174

2171-
let Some((s, _)) = map.iter().find(|&&(s, t)| {
2172-
self.tcx.is_diagnostic_item(s, adt.did()) && self.can_coerce(expr_ty, t)
2175+
let int_type = substs.type_at(0);
2176+
2177+
let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| {
2178+
if *t == int_type && self.can_coerce(expr_ty, *t) { Some(nonzero_alias) } else { None }
21732179
}) else {
21742180
return false;
21752181
};
21762182

2177-
let path = self.tcx.def_path_str(adt.non_enum_variant().def_id);
2178-
21792183
err.multipart_suggestion(
2180-
format!("consider calling `{s}::new`"),
2184+
format!("consider calling `{nonzero_alias}::new`"),
21812185
vec![
2182-
(expr.span.shrink_to_lo(), format!("{path}::new(")),
2186+
(expr.span.shrink_to_lo(), format!("{nonzero_alias}::new(")),
21832187
(expr.span.shrink_to_hi(), format!("){unwrap}")),
21842188
],
21852189
Applicability::MaybeIncorrect,

compiler/rustc_span/src/symbol.rs

+1-11
Original file line numberDiff line numberDiff line change
@@ -246,17 +246,7 @@ symbols! {
246246
MutexGuard,
247247
N,
248248
NonNull,
249-
NonZeroI128,
250-
NonZeroI16,
251-
NonZeroI32,
252-
NonZeroI64,
253-
NonZeroI8,
254-
NonZeroU128,
255-
NonZeroU16,
256-
NonZeroU32,
257-
NonZeroU64,
258-
NonZeroU8,
259-
NonZeroUsize,
249+
NonZero,
260250
None,
261251
Normal,
262252
Ok,

library/core/src/num/mod.rs

+9-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,15 @@ pub use dec2flt::ParseFloatError;
6161
#[stable(feature = "rust1", since = "1.0.0")]
6262
pub use error::ParseIntError;
6363

64-
pub(crate) use nonzero::NonZero;
64+
#[unstable(
65+
feature = "nonzero_internals",
66+
reason = "implementation detail which may disappear or be replaced at any time",
67+
issue = "none"
68+
)]
69+
pub use nonzero::ZeroablePrimitive;
70+
71+
#[unstable(feature = "generic_nonzero", issue = "120257")]
72+
pub use nonzero::NonZero;
6573

6674
#[stable(feature = "nonzero", since = "1.28.0")]
6775
pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};

library/core/src/num/nonzero.rs

+32-18
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
use crate::cmp::Ordering;
44
use crate::fmt;
55
use crate::hash::{Hash, Hasher};
6+
#[cfg(bootstrap)]
7+
use crate::marker::StructuralEq;
68
use crate::marker::StructuralPartialEq;
79
use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem};
810
use crate::str::FromStr;
@@ -30,9 +32,7 @@ mod private {
3032
issue = "none"
3133
)]
3234
#[const_trait]
33-
pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {
34-
type NonZero;
35-
}
35+
pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {}
3636

3737
macro_rules! impl_zeroable_primitive {
3838
($NonZero:ident ( $primitive:ty )) => {
@@ -48,9 +48,7 @@ macro_rules! impl_zeroable_primitive {
4848
reason = "implementation detail which may disappear or be replaced at any time",
4949
issue = "none"
5050
)]
51-
impl const ZeroablePrimitive for $primitive {
52-
type NonZero = $NonZero;
53-
}
51+
impl const ZeroablePrimitive for $primitive {}
5452
};
5553
}
5654

@@ -67,12 +65,23 @@ impl_zeroable_primitive!(NonZeroI64(i64));
6765
impl_zeroable_primitive!(NonZeroI128(i128));
6866
impl_zeroable_primitive!(NonZeroIsize(isize));
6967

70-
#[unstable(
71-
feature = "nonzero_internals",
72-
reason = "implementation detail which may disappear or be replaced at any time",
73-
issue = "none"
74-
)]
75-
pub(crate) type NonZero<T> = <T as ZeroablePrimitive>::NonZero;
68+
/// A value that is known not to equal zero.
69+
///
70+
/// This enables some memory layout optimization.
71+
/// For example, `Option<NonZero<u32>>` is the same size as `u32`:
72+
///
73+
/// ```
74+
/// #![feature(generic_nonzero)]
75+
/// use core::mem::size_of;
76+
///
77+
/// assert_eq!(size_of::<Option<core::num::NonZero<u32>>>(), size_of::<u32>());
78+
/// ```
79+
#[unstable(feature = "generic_nonzero", issue = "120257")]
80+
#[repr(transparent)]
81+
#[rustc_layout_scalar_valid_range_start(1)]
82+
#[rustc_nonnull_optimization_guaranteed]
83+
#[rustc_diagnostic_item = "NonZero"]
84+
pub struct NonZero<T: ZeroablePrimitive>(T);
7685

7786
macro_rules! impl_nonzero_fmt {
7887
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
@@ -131,12 +140,7 @@ macro_rules! nonzero_integer {
131140
///
132141
/// [null pointer optimization]: crate::option#representation
133142
#[$stability]
134-
#[derive(Copy, Eq)]
135-
#[repr(transparent)]
136-
#[rustc_layout_scalar_valid_range_start(1)]
137-
#[rustc_nonnull_optimization_guaranteed]
138-
#[rustc_diagnostic_item = stringify!($Ty)]
139-
pub struct $Ty($Int);
143+
pub type $Ty = NonZero<$Int>;
140144

141145
impl $Ty {
142146
/// Creates a non-zero without checking whether the value is non-zero.
@@ -543,6 +547,9 @@ macro_rules! nonzero_integer {
543547
}
544548
}
545549

550+
#[$stability]
551+
impl Copy for $Ty {}
552+
546553
#[$stability]
547554
impl PartialEq for $Ty {
548555
#[inline]
@@ -559,6 +566,13 @@ macro_rules! nonzero_integer {
559566
#[unstable(feature = "structural_match", issue = "31434")]
560567
impl StructuralPartialEq for $Ty {}
561568

569+
#[$stability]
570+
impl Eq for $Ty {}
571+
572+
#[unstable(feature = "structural_match", issue = "31434")]
573+
#[cfg(bootstrap)]
574+
impl StructuralEq for $Ty {}
575+
562576
#[$stability]
563577
impl PartialOrd for $Ty {
564578
#[inline]

library/std/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,7 @@
323323
#![feature(float_gamma)]
324324
#![feature(float_minimum_maximum)]
325325
#![feature(float_next_up_down)]
326+
#![feature(generic_nonzero)]
326327
#![feature(hasher_prefixfree_extras)]
327328
#![feature(hashmap_internals)]
328329
#![feature(hint_assert_unchecked)]

library/std/src/num.rs

+10
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,16 @@ pub use core::num::Wrapping;
1616
#[stable(feature = "rust1", since = "1.0.0")]
1717
pub use core::num::{FpCategory, ParseFloatError, ParseIntError, TryFromIntError};
1818

19+
#[unstable(
20+
feature = "nonzero_internals",
21+
reason = "implementation detail which may disappear or be replaced at any time",
22+
issue = "none"
23+
)]
24+
pub use core::num::ZeroablePrimitive;
25+
26+
#[unstable(feature = "generic_nonzero", issue = "120257")]
27+
pub use core::num::NonZero;
28+
1929
#[stable(feature = "signed_nonzero", since = "1.34.0")]
2030
pub use core::num::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
2131
#[stable(feature = "nonzero", since = "1.28.0")]

src/etc/natvis/libcore.natvis

+1-34
Original file line numberDiff line numberDiff line change
@@ -41,40 +41,7 @@
4141
</Expand>
4242
</Type>
4343

44-
<Type Name="core::num::nonzero::NonZeroI8">
45-
<DisplayString>{__0}</DisplayString>
46-
</Type>
47-
<Type Name="core::num::nonzero::NonZeroI16">
48-
<DisplayString>{__0}</DisplayString>
49-
</Type>
50-
<Type Name="core::num::nonzero::NonZeroI32">
51-
<DisplayString>{__0}</DisplayString>
52-
</Type>
53-
<Type Name="core::num::nonzero::NonZeroI64">
54-
<DisplayString>{__0}</DisplayString>
55-
</Type>
56-
<Type Name="core::num::nonzero::NonZeroI128">
57-
<DisplayString>{__0}</DisplayString>
58-
</Type>
59-
<Type Name="core::num::nonzero::NonZeroIsize">
60-
<DisplayString>{__0}</DisplayString>
61-
</Type>
62-
<Type Name="core::num::nonzero::NonZeroU8">
63-
<DisplayString>{__0}</DisplayString>
64-
</Type>
65-
<Type Name="core::num::nonzero::NonZeroU16">
66-
<DisplayString>{__0}</DisplayString>
67-
</Type>
68-
<Type Name="core::num::nonzero::NonZeroU32">
69-
<DisplayString>{__0}</DisplayString>
70-
</Type>
71-
<Type Name="core::num::nonzero::NonZeroU64">
72-
<DisplayString>{__0}</DisplayString>
73-
</Type>
74-
<Type Name="core::num::nonzero::NonZeroU128">
75-
<DisplayString>{__0}</DisplayString>
76-
</Type>
77-
<Type Name="core::num::nonzero::NonZeroUsize">
44+
<Type Name="core::num::nonzero::NonZero&lt;*&gt;">
7845
<DisplayString>{__0}</DisplayString>
7946
</Type>
8047

src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs

+31-24
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use super::ARITHMETIC_SIDE_EFFECTS;
22
use clippy_utils::consts::{constant, constant_simple, Constant};
33
use clippy_utils::diagnostics::span_lint;
4-
use clippy_utils::ty::type_diagnostic_name;
4+
use clippy_utils::ty::is_type_diagnostic_item;
55
use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary};
66
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
77
use rustc_lint::{LateContext, LateLintPass};
8-
use rustc_middle::ty::Ty;
8+
use rustc_middle::ty::{self, Ty};
99
use rustc_session::impl_lint_pass;
1010
use rustc_span::source_map::Spanned;
1111
use rustc_span::symbol::sym;
@@ -88,37 +88,44 @@ impl ArithmeticSideEffects {
8888
}
8989

9090
/// Verifies built-in types that have specific allowed operations
91-
fn has_specific_allowed_type_and_operation(
92-
cx: &LateContext<'_>,
93-
lhs_ty: Ty<'_>,
91+
fn has_specific_allowed_type_and_operation<'tcx>(
92+
cx: &LateContext<'tcx>,
93+
lhs_ty: Ty<'tcx>,
9494
op: &Spanned<hir::BinOpKind>,
95-
rhs_ty: Ty<'_>,
95+
rhs_ty: Ty<'tcx>,
9696
) -> bool {
9797
let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem);
98-
let is_non_zero_u = |symbol: Option<Symbol>| {
99-
matches!(
100-
symbol,
101-
Some(
102-
sym::NonZeroU128
103-
| sym::NonZeroU16
104-
| sym::NonZeroU32
105-
| sym::NonZeroU64
106-
| sym::NonZeroU8
107-
| sym::NonZeroUsize
108-
)
109-
)
98+
let is_non_zero_u = |cx: &LateContext<'tcx>, ty: Ty<'tcx>| {
99+
let tcx = cx.tcx;
100+
101+
let ty::Adt(adt, substs) = ty.kind() else { return false };
102+
103+
if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) {
104+
return false;
105+
};
106+
107+
let int_type = substs.type_at(0);
108+
let unsigned_int_types = [
109+
tcx.types.u8,
110+
tcx.types.u16,
111+
tcx.types.u32,
112+
tcx.types.u64,
113+
tcx.types.u128,
114+
tcx.types.usize,
115+
];
116+
117+
unsigned_int_types.contains(&int_type)
110118
};
111119
let is_sat_or_wrap = |ty: Ty<'_>| {
112-
let is_sat = type_diagnostic_name(cx, ty) == Some(sym::Saturating);
113-
let is_wrap = type_diagnostic_name(cx, ty) == Some(sym::Wrapping);
114-
is_sat || is_wrap
120+
is_type_diagnostic_item(cx, ty, sym::Saturating) || is_type_diagnostic_item(cx, ty, sym::Wrapping)
115121
};
116122

117-
// If the RHS is NonZeroU*, then division or module by zero will never occur
118-
if is_non_zero_u(type_diagnostic_name(cx, rhs_ty)) && is_div_or_rem {
123+
// If the RHS is `NonZero<u*>`, then division or module by zero will never occur.
124+
if is_non_zero_u(cx, rhs_ty) && is_div_or_rem {
119125
return true;
120126
}
121-
// `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module
127+
128+
// `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module.
122129
if is_sat_or_wrap(lhs_ty) {
123130
return !is_div_or_rem;
124131
}

0 commit comments

Comments
 (0)