Skip to content

Commit abe1185

Browse files
committed
Implement wide not-null pointer patterns
1 parent 6d08c10 commit abe1185

File tree

7 files changed

+87
-10
lines changed

7 files changed

+87
-10
lines changed

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -822,11 +822,21 @@ where
822822
| ty::FnDef(..)
823823
| ty::CoroutineWitness(..)
824824
| ty::Foreign(..)
825-
| ty::Pat(_, _)
826825
| ty::Dynamic(_, _, ty::Dyn) => {
827826
bug!("TyAndLayout::field({:?}): not applicable", this)
828827
}
829828

829+
// May contain wide pointers
830+
ty::Pat(base, pat) => match *pat {
831+
ty::PatternKind::NotNull => {
832+
assert_eq!(i, 0);
833+
TyMaybeWithLayout::Ty(base)
834+
}
835+
ty::PatternKind::Range { .. } | ty::PatternKind::Or(_) => {
836+
bug!("TyAndLayout::field({this:?}): only applicable to !null patterns")
837+
}
838+
},
839+
830840
ty::UnsafeBinder(bound_ty) => {
831841
let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into());
832842
field_ty_or_layout(TyAndLayout { ty, ..this }, cx, i)

compiler/rustc_ty_utils/src/layout.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,12 @@ fn layout_of_uncached<'tcx>(
273273
};
274274

275275
layout.largest_niche = Some(niche);
276+
// Make wide pointer pattern types contain only a single field
277+
// of the wide pointer type itself.
278+
layout.fields = FieldsShape::Arbitrary {
279+
offsets: [Size::ZERO].into_iter().collect(),
280+
memory_index: [0].into_iter().collect(),
281+
}
276282
} else {
277283
bug!(
278284
"pattern type with `!null` pattern but not scalar/pair layout: {ty:?}, {layout:?}"

tests/ui/consts/const-eval/raw-bytes.64bit.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::tran
5353
78 00 00 00 ff ff ff ff │ x.......
5454
}
5555

56-
error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1
56+
error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
5757
--> $DIR/raw-bytes.rs:58:1
5858
|
5959
LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
@@ -64,7 +64,7 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
6464
00 00 00 00 00 00 00 00 │ ........
6565
}
6666

67-
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
67+
error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
6868
--> $DIR/raw-bytes.rs:61:1
6969
|
7070
LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
@@ -75,7 +75,7 @@ LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
7575
00 │ .
7676
}
7777

78-
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
78+
error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
7979
--> $DIR/raw-bytes.rs:63:1
8080
|
8181
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
@@ -108,7 +108,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
108108
14 00 00 00 │ ....
109109
}
110110

111-
error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1
111+
error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
112112
--> $DIR/raw-bytes.rs:78:1
113113
|
114114
LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {

tests/ui/consts/const-eval/ub-nonnull.stderr

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1
1+
error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
22
--> $DIR/ub-nonnull.rs:16:1
33
|
44
LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) };
@@ -15,7 +15,7 @@ error[E0080]: in-bounds pointer arithmetic failed: attempting to offset pointer
1515
LL | let out_of_bounds_ptr = &ptr[255];
1616
| ^^^^^^^^^ evaluation of `OUT_OF_BOUNDS_PTR` failed here
1717

18-
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
18+
error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
1919
--> $DIR/ub-nonnull.rs:26:1
2020
|
2121
LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
@@ -26,7 +26,7 @@ LL | const NULL_U8: NonZero<u8> = unsafe { mem::transmute(0u8) };
2626
HEX_DUMP
2727
}
2828

29-
error[E0080]: constructing invalid value at .0.0: encountered 0, but expected something greater or equal to 1
29+
error[E0080]: constructing invalid value at .0: encountered 0, but expected something greater or equal to 1
3030
--> $DIR/ub-nonnull.rs:28:1
3131
|
3232
LL | const NULL_USIZE: NonZero<usize> = unsafe { mem::transmute(0usize) };
@@ -65,7 +65,7 @@ LL | const BAD_RANGE2: RestrictedRange2 = unsafe { RestrictedRange2(20) };
6565
HEX_DUMP
6666
}
6767

68-
error[E0080]: constructing invalid value at .pointer: encountered 0, but expected something greater or equal to 1
68+
error[E0080]: constructing invalid value: encountered 0, but expected something greater or equal to 1
6969
--> $DIR/ub-nonnull.rs:53:1
7070
|
7171
LL | const NULL_FAT_PTR: NonNull<dyn Send> = unsafe {

tests/ui/lint/invalid_value.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ LL | let _val: NonNull<i32> = mem::uninitialized();
314314
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
315315
|
316316
= note: `std::ptr::NonNull<i32>` must be non-null
317+
= note: raw pointers must be initialized
317318

318319
error: the type `(NonZero<u32>, i32)` does not permit zero-initialization
319320
--> $DIR/invalid_value.rs:94:41
@@ -332,6 +333,7 @@ LL | let _val: (NonZero<u32>, i32) = mem::uninitialized();
332333
|
333334
= note: `std::num::NonZero<u32>` must be non-null
334335
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
336+
= note: integers must be initialized
335337

336338
error: the type `*const dyn Send` does not permit zero-initialization
337339
--> $DIR/invalid_value.rs:97:37
@@ -428,6 +430,7 @@ note: because `std::num::NonZero<u32>` must be non-null (in this field of the on
428430
LL | Banana(NonZero<u32>),
429431
| ^^^^^^^^^^^^
430432
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
433+
= note: integers must be initialized
431434

432435
error: the type `bool` does not permit being left uninitialized
433436
--> $DIR/invalid_value.rs:111:26
@@ -622,6 +625,7 @@ LL | let _val: NonNull<i32> = MaybeUninit::uninit().assume_init();
622625
| help: use `MaybeUninit<T>` instead, and only call `assume_init` after initialization is done
623626
|
624627
= note: `std::ptr::NonNull<i32>` must be non-null
628+
= note: raw pointers must be initialized
625629

626630
error: the type `bool` does not permit being left uninitialized
627631
--> $DIR/invalid_value.rs:158:26

tests/ui/type/pattern_types/non_null.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ type NonNull<T> = pattern_type!(*const T is !null); //~ ERROR layout_of
1212
#[rustc_layout(debug)]
1313
type Test = Option<NonNull<()>>; //~ ERROR layout_of
1414

15+
#[rustc_layout(debug)]
16+
type Wide = pattern_type!(*const [u8] is !null); //~ ERROR layout_of
17+
1518
const _: () = assert!(size_of::<NonNull<()>>() == size_of::<Option<NonNull<()>>>());
1619

1720
fn main() {}

tests/ui/type/pattern_types/non_null.stderr

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,5 +160,59 @@ error: layout_of(Option<(*const ()) is !null>) = Layout {
160160
LL | type Test = Option<NonNull<()>>;
161161
| ^^^^^^^^^
162162

163-
error: aborting due to 2 previous errors
163+
error: layout_of((*const [u8]) is !null) = Layout {
164+
size: Size(16 bytes),
165+
align: AbiAlign {
166+
abi: Align(8 bytes),
167+
},
168+
backend_repr: ScalarPair(
169+
Initialized {
170+
value: Pointer(
171+
AddressSpace(
172+
0,
173+
),
174+
),
175+
valid_range: 1..=18446744073709551615,
176+
},
177+
Initialized {
178+
value: Int(
179+
I64,
180+
false,
181+
),
182+
valid_range: 0..=18446744073709551615,
183+
},
184+
),
185+
fields: Arbitrary {
186+
offsets: [
187+
Size(0 bytes),
188+
],
189+
memory_index: [
190+
0,
191+
],
192+
},
193+
largest_niche: Some(
194+
Niche {
195+
offset: Size(0 bytes),
196+
value: Pointer(
197+
AddressSpace(
198+
0,
199+
),
200+
),
201+
valid_range: 1..=18446744073709551615,
202+
},
203+
),
204+
uninhabited: false,
205+
variants: Single {
206+
index: 0,
207+
},
208+
max_repr_align: None,
209+
unadjusted_abi_align: Align(8 bytes),
210+
randomization_seed: $SEED,
211+
}
212+
--> $DIR/non_null.rs:16:1
213+
|
214+
LL | type Wide = pattern_type!(*const [u8] is !null);
215+
| ^^^^^^^^^
216+
217+
error: aborting due to 3 previous errors
164218

0 commit comments

Comments
 (0)