Prefer -1 for None

Currently we pick "weird" numbers like `1114112` for `None::<char>`.  While that's not *wrong*, it's kinda *unnatural* -- a human wouldn't make that choice.

This PR instead picks `-1` for thinge like `None::<char>` -- like clang's `WEOF` -- and `None::<bool>` and such.

Any enums with more than one niched value (so not `Result` nor `Option`) remain as they were before.
This commit is contained in:
Scott McMurray
2026-04-17 02:38:45 -07:00
parent 9bc1313507
commit ba1a33e105
9 changed files with 53 additions and 21 deletions
+12 -3
View File
@@ -2051,8 +2051,7 @@ pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Sc
assert!(size.bits() <= 128);
let max_value = size.unsigned_int_max();
let niche = v.end.wrapping_add(1)..v.start;
let available = niche.end.wrapping_sub(niche.start) & max_value;
let available = v.start.wrapping_sub(v.end).wrapping_sub(1) & max_value;
if count > available {
return None;
}
@@ -2080,7 +2079,17 @@ pub fn reserve<C: HasDataLayout>(&self, cx: &C, count: u128) -> Option<(u128, Sc
Some((start, Scalar::Initialized { value, valid_range: v.with_end(end) }))
};
let distance_end_zero = max_value - v.end;
if v.start > v.end {
// FIXME: this ought to work for `bool` too, but that seems to be hitting a miscompilation
// <https://github.com/rust-lang/rust/pull/155473#issuecomment-4302036343>
if count == 1 && v != (WrappingRange { start: 0, end: 1 }) {
// We only need one, so just pick the one closest to zero.
// Not only does that obviously use zero if it's possible, but it also
// simplifies testing things like `Option<char>`, since looking for `-1`
// is easier than looking for `1114112` (and matches clang's `WEOF`).
let next_up = size.sign_extend(v.end.wrapping_add(1)).unsigned_abs();
let next_down = size.sign_extend(v.start.wrapping_sub(1)).unsigned_abs();
if next_down <= next_up { move_start(v) } else { move_end(v) }
} else if v.start > v.end {
// zero is unavailable because wrapping occurs
move_end(v)
} else if v.start <= distance_end_zero {
+12
View File
@@ -2,6 +2,7 @@
//@ only-64bit
#![crate_type = "lib"]
#![feature(pattern_types, pattern_type_macro)]
use std::cmp::Ordering;
use std::num::NonZero;
@@ -123,3 +124,14 @@ fn make_fully_uninhabited_result(v: u32, n: Never) -> Result<(u32, Never), (Neve
}
enum Never {}
#[repr(transparent)]
struct NewtypeIndex(std::pat::pattern_type!(u32 is 0..=0xFFFFFF00));
#[no_mangle]
pub fn make_none_newtype_index() -> Option<NewtypeIndex> {
// CHECK-LABEL: @make_none_newtype_index
// CHECK-NEXT: start:
// CHECK-NEXT: ret i32 -1
None
}
@@ -36,8 +36,8 @@ pub fn opt_bool_eq_discr(a: Option<bool>, b: Option<bool>) -> bool {
#[unsafe(no_mangle)]
pub fn opt_ord_eq_discr(a: Option<Ordering>, b: Option<Ordering>) -> bool {
// CHECK-LABEL: @opt_ord_eq_discr(
// CHECK: %[[A:.+]] = icmp ne i8 %a, 2
// CHECK: %[[B:.+]] = icmp eq i8 %b, 2
// CHECK: %[[A:.+]] = icmp ne i8 %a, -2
// CHECK: %[[B:.+]] = icmp eq i8 %b, -2
// CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
// CHECK: ret i1 %[[R]]
@@ -58,8 +58,8 @@ pub fn opt_nz32_eq_discr(a: Option<NonZero<u32>>, b: Option<NonZero<u32>>) -> bo
#[unsafe(no_mangle)]
pub fn opt_ac_eq_discr(a: Option<AC>, b: Option<AC>) -> bool {
// CHECK-LABEL: @opt_ac_eq_discr(
// CHECK: %[[A:.+]] = icmp ne i8 %a, -128
// CHECK: %[[B:.+]] = icmp eq i8 %b, -128
// CHECK: %[[A:.+]] = icmp ne i8 %a, -1
// CHECK: %[[B:.+]] = icmp eq i8 %b, -1
// CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
// CHECK: ret i1 %[[R]]
@@ -81,7 +81,7 @@ pub fn option_bool_match(x: Option<bool>) -> char {
#[no_mangle]
pub fn option_ordering_match(x: Option<Ordering>) -> char {
// CHECK: %[[RAW:.+]] = load i8, ptr %x
// CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], 2
// CHECK: %[[IS_NONE:.+]] = icmp eq i8 %[[RAW]], -2
// CHECK: %[[OPT_DISCR:.+]] = select i1 %[[IS_NONE]], i64 0, i64 1
// CHECK: %[[OPT_DISCR_T:.+]] = trunc nuw i64 %[[OPT_DISCR]] to i1
// CHECK: br i1 %[[OPT_DISCR_T]], label %[[BB_SOME:.+]], label %[[BB_NONE:.+]]
+11
View File
@@ -82,3 +82,14 @@ pub fn bool_eq(l: Option<bool>, r: Option<bool>) -> bool {
// CHECK-NEXT: ret i1
l == r
}
// CHECK-LABEL: @bool_ref_eq
#[no_mangle]
pub fn bool_ref_eq(l: &Option<bool>, r: &Option<bool>) -> bool {
// CHECK: start:
// CHECK-NEXT: load i8
// CHECK-NEXT: load i8
// CHECK-NEXT: icmp eq i8
// CHECK-NEXT: ret i1
l == r
}
+4 -4
View File
@@ -745,7 +745,7 @@ error: layout_of(Option<char>) = Layout {
I32,
false,
),
valid_range: 0..=1114112,
valid_range: (..=1114111) | (4294967295..),
},
),
fields: Arbitrary {
@@ -763,7 +763,7 @@ error: layout_of(Option<char>) = Layout {
I32,
false,
),
valid_range: 0..=1114112,
valid_range: (..=1114111) | (4294967295..),
},
),
uninhabited: false,
@@ -773,12 +773,12 @@ error: layout_of(Option<char>) = Layout {
I32,
false,
),
valid_range: 0..=1114112,
valid_range: (..=1114111) | (4294967295..),
},
tag_encoding: Niche {
untagged_variant: 1,
niche_variants: 0..=0,
niche_start: 1114112,
niche_start: 4294967295,
},
tag_field: 0,
variants: [
@@ -370,7 +370,7 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
I16,
false,
),
valid_range: 0..=1,
valid_range: (..=0) | (65535..),
},
),
uninhabited: false,
@@ -380,12 +380,12 @@ error: layout_of(Result<[u32; 0], Packed<U16IsZero>>) = Layout {
I16,
false,
),
valid_range: 0..=1,
valid_range: (..=0) | (65535..),
},
tag_encoding: Niche {
untagged_variant: 1,
niche_variants: 0..=0,
niche_start: 1,
niche_start: 65535,
},
tag_field: 0,
variants: [
+2 -2
View File
@@ -57,7 +57,7 @@ error: layout_of(Option<(*const ()) is !null>) = Layout {
0,
),
),
valid_range: (..=0) | (1..),
valid_range: 0..=18446744073709551615,
},
),
fields: Arbitrary {
@@ -77,7 +77,7 @@ error: layout_of(Option<(*const ()) is !null>) = Layout {
0,
),
),
valid_range: (..=0) | (1..),
valid_range: 0..=18446744073709551615,
},
tag_encoding: Niche {
untagged_variant: 1,
@@ -99,7 +99,7 @@ error: layout_of(Option<(u32) is 1..>) = Layout {
I32,
false,
),
valid_range: (..=0) | (1..),
valid_range: 0..=4294967295,
},
),
fields: Arbitrary {
@@ -118,7 +118,7 @@ error: layout_of(Option<(u32) is 1..>) = Layout {
I32,
false,
),
valid_range: (..=0) | (1..),
valid_range: 0..=4294967295,
},
tag_encoding: Niche {
untagged_variant: 1,
@@ -210,7 +210,7 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
I32,
false,
),
valid_range: (..=0) | (1..),
valid_range: 0..=4294967295,
},
),
fields: Arbitrary {
@@ -229,7 +229,7 @@ error: layout_of(Option<NonZero<u32>>) = Layout {
I32,
false,
),
valid_range: (..=0) | (1..),
valid_range: 0..=4294967295,
},
tag_encoding: Niche {
untagged_variant: 1,