Add not-null pointer patterns to pattern types

This commit is contained in:
Oli Scherer
2025-01-24 12:19:17 +00:00
committed by Oli Scherer
parent d9f22d289c
commit ad4bd083f3
28 changed files with 353 additions and 22 deletions

View File

@@ -2579,6 +2579,9 @@ pub enum TyPatKind {
/// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`). /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
Range(Option<Box<AnonConst>>, Option<Box<AnonConst>>, Spanned<RangeEnd>), Range(Option<Box<AnonConst>>, Option<Box<AnonConst>>, Spanned<RangeEnd>),
/// A `!null` pattern for raw pointers.
NotNull,
Or(ThinVec<TyPat>), Or(ThinVec<TyPat>),
/// Placeholder for a pattern that wasn't syntactically well formed in some way. /// Placeholder for a pattern that wasn't syntactically well formed in some way.

View File

@@ -143,7 +143,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
} }
// return inner to be processed in next loop // return inner to be processed in next loop
PatKind::Paren(inner) => pattern = inner, PatKind::Paren(inner) => pattern = inner,
PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span), PatKind::MacCall(_) => {
panic!("{pattern:#?} shouldn't exist here")
}
PatKind::Err(guar) => break hir::PatKind::Err(*guar), PatKind::Err(guar) => break hir::PatKind::Err(*guar),
} }
}; };
@@ -460,6 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) )
}), }),
), ),
TyPatKind::NotNull => hir::TyPatKind::NotNull,
TyPatKind::Or(variants) => { TyPatKind::Or(variants) => {
hir::TyPatKind::Or(self.arena.alloc_from_iter( hir::TyPatKind::Or(self.arena.alloc_from_iter(
variants.iter().map(|pat| self.lower_ty_pat_mut(pat, base_type)), variants.iter().map(|pat| self.lower_ty_pat_mut(pat, base_type)),

View File

@@ -1232,6 +1232,7 @@ impl<'a> State<'a> {
self.print_expr_anon_const(end, &[]); self.print_expr_anon_const(end, &[]);
} }
} }
rustc_ast::TyPatKind::NotNull => self.word("!null"),
rustc_ast::TyPatKind::Or(variants) => { rustc_ast::TyPatKind::Or(variants) => {
let mut first = true; let mut first = true;
for pat in variants { for pat in variants {

View File

@@ -30,15 +30,21 @@ fn parse_pat_ty<'a>(
let ty = parser.parse_ty()?; let ty = parser.parse_ty()?;
parser.expect_keyword(exp!(Is))?; parser.expect_keyword(exp!(Is))?;
let pat = pat_to_ty_pat( let start = parser.token.span;
cx, let pat = if parser.eat(exp!(Bang)) {
parser.parse_pat_no_top_guard( parser.expect_keyword(exp!(Null))?;
None, ty_pat(TyPatKind::NotNull, start.to(parser.token.span))
RecoverComma::No, } else {
RecoverColon::No, pat_to_ty_pat(
CommaRecoveryMode::EitherTupleOrPipe, cx,
)?, parser.parse_pat_no_top_guard(
); None,
RecoverComma::No,
RecoverColon::No,
CommaRecoveryMode::EitherTupleOrPipe,
)?,
)
};
if parser.token != token::Eof { if parser.token != token::Eof {
parser.unexpected()?; parser.unexpected()?;

View File

@@ -1261,9 +1261,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
// When you extend this match, make sure to also add tests to // When you extend this match, make sure to also add tests to
// tests/ui/type/pattern_types/validity.rs(( // tests/ui/type/pattern_types/validity.rs((
match **pat { match **pat {
// Range patterns are precisely reflected into `valid_range` and thus // Range and non-null patterns are precisely reflected into `valid_range` and thus
// handled fully by `visit_scalar` (called below). // handled fully by `visit_scalar` (called below).
ty::PatternKind::Range { .. } => {}, ty::PatternKind::Range { .. } => {},
ty::PatternKind::NotNull => {},
// FIXME(pattern_types): check that the value is covered by one of the variants. // FIXME(pattern_types): check that the value is covered by one of the variants.
// For now, we rely on layout computation setting the scalar's `valid_range` to // For now, we rely on layout computation setting the scalar's `valid_range` to

View File

@@ -1854,6 +1854,9 @@ pub enum TyPatKind<'hir> {
/// A range pattern (e.g., `1..=2` or `1..2`). /// A range pattern (e.g., `1..=2` or `1..2`).
Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>), Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>),
/// A pattern that excludes null pointers
NotNull,
/// A list of patterns where only one needs to be satisfied /// A list of patterns where only one needs to be satisfied
Or(&'hir [TyPat<'hir>]), Or(&'hir [TyPat<'hir>]),

View File

@@ -725,7 +725,7 @@ pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>)
try_visit!(visitor.visit_const_arg_unambig(upper_bound)); try_visit!(visitor.visit_const_arg_unambig(upper_bound));
} }
TyPatKind::Or(patterns) => walk_list!(visitor, visit_pattern_type_pattern, patterns), TyPatKind::Or(patterns) => walk_list!(visitor, visit_pattern_type_pattern, patterns),
TyPatKind::Err(_) => (), TyPatKind::NotNull | TyPatKind::Err(_) => (),
} }
V::Result::output() V::Result::output()
} }

View File

@@ -2611,6 +2611,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
.span_delayed_bug(ty_span, "invalid base type for range pattern")), .span_delayed_bug(ty_span, "invalid base type for range pattern")),
} }
} }
hir::TyPatKind::NotNull => Ok(ty::PatternKind::NotNull),
hir::TyPatKind::Or(patterns) => { hir::TyPatKind::Or(patterns) => {
self.tcx() self.tcx()
.mk_patterns_from_iter(patterns.iter().map(|pat| { .mk_patterns_from_iter(patterns.iter().map(|pat| {

View File

@@ -340,6 +340,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_const(current, start, variance); self.add_constraints_from_const(current, start, variance);
self.add_constraints_from_const(current, end, variance); self.add_constraints_from_const(current, end, variance);
} }
ty::PatternKind::NotNull => {}
ty::PatternKind::Or(patterns) => { ty::PatternKind::Or(patterns) => {
for pat in patterns { for pat in patterns {
self.add_constraints_from_pat(current, variance, pat) self.add_constraints_from_pat(current, variance, pat)

View File

@@ -1888,6 +1888,10 @@ impl<'a> State<'a> {
self.word("..="); self.word("..=");
self.print_const_arg(end); self.print_const_arg(end);
} }
TyPatKind::NotNull => {
self.word_space("not");
self.word("null");
}
TyPatKind::Or(patterns) => { TyPatKind::Or(patterns) => {
self.popen(); self.popen();
let mut first = true; let mut first = true;

View File

@@ -758,6 +758,7 @@ fn pat_ty_is_known_nonnull<'tcx>(
// to ensure we aren't wrapping over zero. // to ensure we aren't wrapping over zero.
start > 0 && end >= start start > 0 && end >= start
} }
ty::PatternKind::NotNull => true,
ty::PatternKind::Or(patterns) => { ty::PatternKind::Or(patterns) => {
patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat)) patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat))
} }
@@ -918,7 +919,9 @@ fn get_nullable_type_from_pat<'tcx>(
pat: ty::Pattern<'tcx>, pat: ty::Pattern<'tcx>,
) -> Option<Ty<'tcx>> { ) -> Option<Ty<'tcx>> {
match *pat { match *pat {
ty::PatternKind::Range { .. } => get_nullable_type(tcx, typing_env, base), ty::PatternKind::NotNull | ty::PatternKind::Range { .. } => {
get_nullable_type(tcx, typing_env, base)
}
ty::PatternKind::Or(patterns) => { ty::PatternKind::Or(patterns) => {
let first = get_nullable_type_from_pat(tcx, typing_env, base, patterns[0])?; let first = get_nullable_type_from_pat(tcx, typing_env, base, patterns[0])?;
for &pat in &patterns[1..] { for &pat in &patterns[1..] {

View File

@@ -30,6 +30,7 @@ impl<'tcx> Flags for Pattern<'tcx> {
} }
flags flags
} }
ty::PatternKind::NotNull => rustc_type_ir::TypeFlags::empty(),
} }
} }
@@ -45,6 +46,7 @@ impl<'tcx> Flags for Pattern<'tcx> {
} }
idx idx
} }
ty::PatternKind::NotNull => rustc_type_ir::INNERMOST,
} }
} }
} }
@@ -91,6 +93,7 @@ impl<'tcx> IrPrint<PatternKind<'tcx>> for TyCtxt<'tcx> {
write!(f, "..={end}") write!(f, "..={end}")
} }
PatternKind::NotNull => write!(f, "!null"),
PatternKind::Or(patterns) => { PatternKind::Or(patterns) => {
write!(f, "(")?; write!(f, "(")?;
let mut first = true; let mut first = true;

View File

@@ -35,6 +35,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
let end = relation.relate(end_a, end_b)?; let end = relation.relate(end_a, end_b)?;
Ok(tcx.mk_pat(ty::PatternKind::Range { start, end })) Ok(tcx.mk_pat(ty::PatternKind::Range { start, end }))
} }
(ty::PatternKind::NotNull, ty::PatternKind::NotNull) => Ok(a),
(&ty::PatternKind::Or(a), &ty::PatternKind::Or(b)) => { (&ty::PatternKind::Or(a), &ty::PatternKind::Or(b)) => {
if a.len() != b.len() { if a.len() != b.len() {
return Err(TypeError::Mismatch); return Err(TypeError::Mismatch);
@@ -43,7 +44,10 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
let patterns = tcx.mk_patterns_from_iter(v)?; let patterns = tcx.mk_patterns_from_iter(v)?;
Ok(tcx.mk_pat(ty::PatternKind::Or(patterns))) Ok(tcx.mk_pat(ty::PatternKind::Or(patterns)))
} }
(ty::PatternKind::Range { .. } | ty::PatternKind::Or(_), _) => Err(TypeError::Mismatch), (
ty::PatternKind::NotNull | ty::PatternKind::Range { .. } | ty::PatternKind::Or(_),
_,
) => Err(TypeError::Mismatch),
} }
} }
} }

View File

@@ -139,6 +139,7 @@ pub enum TokenType {
SymNomem, SymNomem,
SymNoreturn, SymNoreturn,
SymNostack, SymNostack,
SymNull,
SymOptions, SymOptions,
SymOut, SymOut,
SymPreservesFlags, SymPreservesFlags,
@@ -273,6 +274,7 @@ impl TokenType {
SymNomem, SymNomem,
SymNoreturn, SymNoreturn,
SymNostack, SymNostack,
SymNull,
SymOptions, SymOptions,
SymOut, SymOut,
SymPreservesFlags, SymPreservesFlags,
@@ -348,6 +350,7 @@ impl TokenType {
TokenType::SymNomem => Some(sym::nomem), TokenType::SymNomem => Some(sym::nomem),
TokenType::SymNoreturn => Some(sym::noreturn), TokenType::SymNoreturn => Some(sym::noreturn),
TokenType::SymNostack => Some(sym::nostack), TokenType::SymNostack => Some(sym::nostack),
TokenType::SymNull => Some(sym::null),
TokenType::SymOptions => Some(sym::options), TokenType::SymOptions => Some(sym::options),
TokenType::SymOut => Some(sym::out), TokenType::SymOut => Some(sym::out),
TokenType::SymPreservesFlags => Some(sym::preserves_flags), TokenType::SymPreservesFlags => Some(sym::preserves_flags),
@@ -562,6 +565,7 @@ macro_rules! exp {
(Nomem) => { exp!(@sym, nomem, SymNomem) }; (Nomem) => { exp!(@sym, nomem, SymNomem) };
(Noreturn) => { exp!(@sym, noreturn, SymNoreturn) }; (Noreturn) => { exp!(@sym, noreturn, SymNoreturn) };
(Nostack) => { exp!(@sym, nostack, SymNostack) }; (Nostack) => { exp!(@sym, nostack, SymNostack) };
(Null) => { exp!(@sym, null, SymNull) };
(Options) => { exp!(@sym, options, SymOptions) }; (Options) => { exp!(@sym, options, SymOptions) };
(Out) => { exp!(@sym, out, SymOut) }; (Out) => { exp!(@sym, out, SymOut) };
(PreservesFlags) => { exp!(@sym, preserves_flags, SymPreservesFlags) }; (PreservesFlags) => { exp!(@sym, preserves_flags, SymPreservesFlags) };

View File

@@ -485,6 +485,7 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
end: Some(end.stable(tables, cx)), end: Some(end.stable(tables, cx)),
include_end: true, include_end: true,
}, },
ty::PatternKind::NotNull => todo!(),
ty::PatternKind::Or(_) => todo!(), ty::PatternKind::Or(_) => todo!(),
} }
} }

View File

@@ -968,7 +968,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc
self.visit_ty_pat(pat) self.visit_ty_pat(pat)
} }
} }
TyPatKind::Err(_) => {} TyPatKind::NotNull | TyPatKind::Err(_) => {}
} }
} }

View File

@@ -1554,6 +1554,7 @@ symbols! {
not, not,
notable_trait, notable_trait,
note, note,
null,
nvptx_target_feature, nvptx_target_feature,
object_safe_for_dispatch, object_safe_for_dispatch,
of, of,

View File

@@ -266,6 +266,9 @@ impl<'tcx> V0SymbolMangler<'tcx> {
self.print_const(start)?; self.print_const(start)?;
self.print_const(end)?; self.print_const(end)?;
} }
ty::PatternKind::NotNull => {
self.tcx.types.unit.print(self)?;
}
ty::PatternKind::Or(patterns) => { ty::PatternKind::Or(patterns) => {
self.push("O"); self.push("O");
for pat in patterns { for pat in patterns {

View File

@@ -705,6 +705,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
check(start); check(start);
check(end); check(end);
} }
ty::PatternKind::NotNull => {}
ty::PatternKind::Or(patterns) => { ty::PatternKind::Or(patterns) => {
for pat in patterns { for pat in patterns {
self.add_wf_preds_for_pat_ty(base_ty, pat) self.add_wf_preds_for_pat_ty(base_ty, pat)

View File

@@ -216,9 +216,7 @@ fn layout_of_uncached<'tcx>(
let mut layout = LayoutData::clone(&layout.0); let mut layout = LayoutData::clone(&layout.0);
match *pat { match *pat {
ty::PatternKind::Range { start, end } => { ty::PatternKind::Range { start, end } => {
if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) = if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
&mut layout.backend_repr
{
scalar.valid_range_mut().start = extract_const_value(cx, ty, start)? scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
.try_to_bits(tcx, cx.typing_env) .try_to_bits(tcx, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
@@ -266,6 +264,25 @@ fn layout_of_uncached<'tcx>(
bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}") bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}")
} }
} }
ty::PatternKind::NotNull => {
if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
&mut layout.backend_repr
{
scalar.valid_range_mut().start = 1;
let niche = Niche {
offset: Size::ZERO,
value: scalar.primitive(),
valid_range: scalar.valid_range(cx),
};
layout.largest_niche = Some(niche);
} else {
bug!(
"pattern type with `!null` pattern but not scalar/pair layout: {ty:?}, {layout:?}"
)
}
}
ty::PatternKind::Or(variants) => match *variants[0] { ty::PatternKind::Or(variants) => match *variants[0] {
ty::PatternKind::Range { .. } => { ty::PatternKind::Range { .. } => {
if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr { if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
@@ -282,7 +299,7 @@ fn layout_of_uncached<'tcx>(
.try_to_bits(tcx, cx.typing_env) .try_to_bits(tcx, cx.typing_env)
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?, .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
)), )),
ty::PatternKind::Or(_) => { ty::PatternKind::NotNull | ty::PatternKind::Or(_) => {
unreachable!("mixed or patterns are not allowed") unreachable!("mixed or patterns are not allowed")
} }
}) })
@@ -347,6 +364,7 @@ fn layout_of_uncached<'tcx>(
) )
} }
} }
ty::PatternKind::NotNull => bug!("or patterns can't contain `!null` patterns"),
ty::PatternKind::Or(..) => bug!("patterns cannot have nested or patterns"), ty::PatternKind::Or(..) => bug!("patterns cannot have nested or patterns"),
}, },
} }

View File

@@ -14,6 +14,7 @@ use crate::Interner;
pub enum PatternKind<I: Interner> { pub enum PatternKind<I: Interner> {
Range { start: I::Const, end: I::Const }, Range { start: I::Const, end: I::Const },
Or(I::PatList), Or(I::PatList),
NotNull,
} }
impl<I: Interner> Eq for PatternKind<I> {} impl<I: Interner> Eq for PatternKind<I> {}

View File

@@ -178,5 +178,6 @@ fn push_ty_pat<I: Interner>(stack: &mut TypeWalkerStack<I>, pat: I::Pat) {
push_ty_pat::<I>(stack, pat) push_ty_pat::<I>(stack, pat)
} }
} }
ty::PatternKind::NotNull => {}
} }
} }

View File

@@ -1123,7 +1123,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_ty_pat(variant); self.hash_ty_pat(variant);
} }
}, },
TyPatKind::Err(_) => {}, TyPatKind::NotNull | TyPatKind::Err(_) => {},
} }
} }

View File

@@ -1099,7 +1099,7 @@ impl Rewrite for ast::TyPat {
} }
Ok(s) Ok(s)
} }
ast::TyPatKind::Err(_) => Err(RewriteError::Unknown), ast::TyPatKind::NotNull | ast::TyPatKind::Err(_) => Err(RewriteError::Unknown),
} }
} }
} }

View File

@@ -10,4 +10,15 @@ type Positive2 = pattern_type!(i32 is 0..=);
type Wild = pattern_type!(() is _); type Wild = pattern_type!(() is _);
//~^ ERROR: pattern not supported in pattern types //~^ ERROR: pattern not supported in pattern types
// FIXME: confusing diagnostic because `not` can be a binding
type NonNull = pattern_type!(*const () is not null);
//~^ ERROR: expected one of `@` or `|`, found `null`
//~| ERROR: pattern not supported in pattern types
type NonNull2 = pattern_type!(*const () is !nil);
//~^ ERROR: expected `null`, found `nil`
// FIXME: reject with a type mismatch
type Mismatch2 = pattern_type!(() is !null);
fn main() {} fn main() {}

View File

@@ -30,6 +30,24 @@ error: pattern not supported in pattern types
LL | type Wild = pattern_type!(() is _); LL | type Wild = pattern_type!(() is _);
| ^ | ^
error: aborting due to 3 previous errors error: pattern not supported in pattern types
--> $DIR/bad_pat.rs:14:43
|
LL | type NonNull = pattern_type!(*const () is not null);
| ^^^
error: expected one of `@` or `|`, found `null`
--> $DIR/bad_pat.rs:14:47
|
LL | type NonNull = pattern_type!(*const () is not null);
| ^^^^ expected one of `@` or `|`
error: expected `null`, found `nil`
--> $DIR/bad_pat.rs:18:45
|
LL | type NonNull2 = pattern_type!(*const () is !nil);
| ^^^ expected `null`
error: aborting due to 6 previous errors
For more information about this error, try `rustc --explain E0586`. For more information about this error, try `rustc --explain E0586`.

View File

@@ -0,0 +1,21 @@
//! Show that pattern-types non-null is the same as libstd's
//@ normalize-stderr: "randomization_seed: \d+" -> "randomization_seed: $$SEED"
//@ only-64bit
#![feature(pattern_type_macro, pattern_types, rustc_attrs)]
use std::pat::pattern_type;
#[rustc_layout(debug)]
type NonNull<T> = pattern_type!(*const T is !null); //~ ERROR layout_of
#[rustc_layout(debug)]
type Test = Option<NonNull<()>>; //~ ERROR layout_of
#[rustc_layout(debug)]
type Wide = pattern_type!(*const [u8] is !null); //~ ERROR layout_of
const _: () = assert!(size_of::<NonNull<()>>() == size_of::<Option<NonNull<()>>>());
fn main() {}

View File

@@ -0,0 +1,218 @@
error: layout_of((*const T) is !null) = Layout {
size: Size(8 bytes),
align: AbiAlign {
abi: Align(8 bytes),
},
backend_repr: Scalar(
Initialized {
value: Pointer(
AddressSpace(
0,
),
),
valid_range: 1..=18446744073709551615,
},
),
fields: Arbitrary {
offsets: [
Size(0 bytes),
],
memory_index: [
0,
],
},
largest_niche: Some(
Niche {
offset: Size(0 bytes),
value: Pointer(
AddressSpace(
0,
),
),
valid_range: 1..=18446744073709551615,
},
),
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(8 bytes),
randomization_seed: $SEED,
}
--> $DIR/non_null.rs:11:1
|
LL | type NonNull<T> = pattern_type!(*const T is !null);
| ^^^^^^^^^^^^^^^
error: layout_of(Option<(*const ()) is !null>) = Layout {
size: Size(8 bytes),
align: AbiAlign {
abi: Align(8 bytes),
},
backend_repr: Scalar(
Initialized {
value: Pointer(
AddressSpace(
0,
),
),
valid_range: (..=0) | (1..),
},
),
fields: Arbitrary {
offsets: [
Size(0 bytes),
],
memory_index: [
0,
],
},
largest_niche: None,
uninhabited: false,
variants: Multiple {
tag: Initialized {
value: Pointer(
AddressSpace(
0,
),
),
valid_range: (..=0) | (1..),
},
tag_encoding: Niche {
untagged_variant: 1,
niche_variants: 0..=0,
niche_start: 0,
},
tag_field: 0,
variants: [
Layout {
size: Size(0 bytes),
align: AbiAlign {
abi: Align(1 bytes),
},
backend_repr: Memory {
sized: true,
},
fields: Arbitrary {
offsets: [],
memory_index: [],
},
largest_niche: None,
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(1 bytes),
randomization_seed: $SEED,
},
Layout {
size: Size(8 bytes),
align: AbiAlign {
abi: Align(8 bytes),
},
backend_repr: Scalar(
Initialized {
value: Pointer(
AddressSpace(
0,
),
),
valid_range: 1..=18446744073709551615,
},
),
fields: Arbitrary {
offsets: [
Size(0 bytes),
],
memory_index: [
0,
],
},
largest_niche: Some(
Niche {
offset: Size(0 bytes),
value: Pointer(
AddressSpace(
0,
),
),
valid_range: 1..=18446744073709551615,
},
),
uninhabited: false,
variants: Single {
index: 1,
},
max_repr_align: None,
unadjusted_abi_align: Align(8 bytes),
randomization_seed: $SEED,
},
],
},
max_repr_align: None,
unadjusted_abi_align: Align(8 bytes),
randomization_seed: $SEED,
}
--> $DIR/non_null.rs:14:1
|
LL | type Test = Option<NonNull<()>>;
| ^^^^^^^^^
error: layout_of((*const [u8]) is !null) = Layout {
size: Size(16 bytes),
align: AbiAlign {
abi: Align(8 bytes),
},
backend_repr: ScalarPair(
Initialized {
value: Pointer(
AddressSpace(
0,
),
),
valid_range: 1..=18446744073709551615,
},
Initialized {
value: Int(
I64,
false,
),
valid_range: 0..=18446744073709551615,
},
),
fields: Arbitrary {
offsets: [
Size(0 bytes),
],
memory_index: [
0,
],
},
largest_niche: Some(
Niche {
offset: Size(0 bytes),
value: Pointer(
AddressSpace(
0,
),
),
valid_range: 1..=18446744073709551615,
},
),
uninhabited: false,
variants: Single {
index: 0,
},
max_repr_align: None,
unadjusted_abi_align: Align(8 bytes),
randomization_seed: $SEED,
}
--> $DIR/non_null.rs:17:1
|
LL | type Wide = pattern_type!(*const [u8] is !null);
| ^^^^^^^^^
error: aborting due to 3 previous errors