diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 0adf4f898ab6..e21155002b0f 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2579,6 +2579,9 @@ pub enum TyPatKind { /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`). Range(Option>, Option>, Spanned), + /// A `!null` pattern for raw pointers. + NotNull, + Or(ThinVec), /// Placeholder for a pattern that wasn't syntactically well formed in some way. diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 03aeb064d7f1..7e4fa840f252 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -143,7 +143,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { } // return inner to be processed in next loop 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), } }; @@ -460,6 +462,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { ) }), ), + TyPatKind::NotNull => hir::TyPatKind::NotNull, TyPatKind::Or(variants) => { hir::TyPatKind::Or(self.arena.alloc_from_iter( variants.iter().map(|pat| self.lower_ty_pat_mut(pat, base_type)), diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 41b520b04c99..a5e2bcaa3bd0 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1232,6 +1232,7 @@ impl<'a> State<'a> { self.print_expr_anon_const(end, &[]); } } + rustc_ast::TyPatKind::NotNull => self.word("!null"), rustc_ast::TyPatKind::Or(variants) => { let mut first = true; for pat in variants { diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs index 8b64bdf02d3b..87a5a440140e 100644 --- a/compiler/rustc_builtin_macros/src/pattern_type.rs +++ b/compiler/rustc_builtin_macros/src/pattern_type.rs @@ -30,15 +30,21 @@ fn parse_pat_ty<'a>( let ty = parser.parse_ty()?; parser.expect_keyword(exp!(Is))?; - let pat = pat_to_ty_pat( - cx, - parser.parse_pat_no_top_guard( - None, - RecoverComma::No, - RecoverColon::No, - CommaRecoveryMode::EitherTupleOrPipe, - )?, - ); + let start = parser.token.span; + let pat = if parser.eat(exp!(Bang)) { + parser.expect_keyword(exp!(Null))?; + ty_pat(TyPatKind::NotNull, start.to(parser.token.span)) + } else { + pat_to_ty_pat( + cx, + parser.parse_pat_no_top_guard( + None, + RecoverComma::No, + RecoverColon::No, + CommaRecoveryMode::EitherTupleOrPipe, + )?, + ) + }; if parser.token != token::Eof { parser.unexpected()?; diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index c62a23eb0b34..89a3303eb390 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -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 // tests/ui/type/pattern_types/validity.rs(( 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). ty::PatternKind::Range { .. } => {}, + ty::PatternKind::NotNull => {}, // 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 diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 394747f81581..90bf82f15f81 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1854,6 +1854,9 @@ pub enum TyPatKind<'hir> { /// A range pattern (e.g., `1..=2` or `1..2`). 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 Or(&'hir [TyPat<'hir>]), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index eb682f32111a..dde71e499c47 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -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)); } TyPatKind::Or(patterns) => walk_list!(visitor, visit_pattern_type_pattern, patterns), - TyPatKind::Err(_) => (), + TyPatKind::NotNull | TyPatKind::Err(_) => (), } V::Result::output() } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 58bd8e3bbbf3..00f909575780 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2611,6 +2611,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .span_delayed_bug(ty_span, "invalid base type for range pattern")), } } + hir::TyPatKind::NotNull => Ok(ty::PatternKind::NotNull), hir::TyPatKind::Or(patterns) => { self.tcx() .mk_patterns_from_iter(patterns.iter().map(|pat| { diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index be841675821c..ce4668736b57 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -340,6 +340,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { self.add_constraints_from_const(current, start, variance); self.add_constraints_from_const(current, end, variance); } + ty::PatternKind::NotNull => {} ty::PatternKind::Or(patterns) => { for pat in patterns { self.add_constraints_from_pat(current, variance, pat) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b9d8eed54a9e..ed5f61b3c69a 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1888,6 +1888,10 @@ impl<'a> State<'a> { self.word("..="); self.print_const_arg(end); } + TyPatKind::NotNull => { + self.word_space("not"); + self.word("null"); + } TyPatKind::Or(patterns) => { self.popen(); let mut first = true; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7c6655926958..8ce74ff76eff 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -758,6 +758,7 @@ fn pat_ty_is_known_nonnull<'tcx>( // to ensure we aren't wrapping over zero. start > 0 && end >= start } + ty::PatternKind::NotNull => true, ty::PatternKind::Or(patterns) => { 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>, ) -> Option> { 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) => { let first = get_nullable_type_from_pat(tcx, typing_env, base, patterns[0])?; for &pat in &patterns[1..] { diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs index 5af9b17dd777..335e5c064743 100644 --- a/compiler/rustc_middle/src/ty/pattern.rs +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -30,6 +30,7 @@ impl<'tcx> Flags for Pattern<'tcx> { } flags } + ty::PatternKind::NotNull => rustc_type_ir::TypeFlags::empty(), } } @@ -45,6 +46,7 @@ impl<'tcx> Flags for Pattern<'tcx> { } idx } + ty::PatternKind::NotNull => rustc_type_ir::INNERMOST, } } } @@ -91,6 +93,7 @@ impl<'tcx> IrPrint> for TyCtxt<'tcx> { write!(f, "..={end}") } + PatternKind::NotNull => write!(f, "!null"), PatternKind::Or(patterns) => { write!(f, "(")?; let mut first = true; diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 2f96970af478..9f2a1187a9dd 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -35,6 +35,7 @@ impl<'tcx> Relate> for ty::Pattern<'tcx> { let end = relation.relate(end_a, end_b)?; 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)) => { if a.len() != b.len() { return Err(TypeError::Mismatch); @@ -43,7 +44,10 @@ impl<'tcx> Relate> for ty::Pattern<'tcx> { let patterns = tcx.mk_patterns_from_iter(v)?; 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), } } } diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs index bd4bb368df05..4c4f09ab3ea8 100644 --- a/compiler/rustc_parse/src/parser/token_type.rs +++ b/compiler/rustc_parse/src/parser/token_type.rs @@ -139,6 +139,7 @@ pub enum TokenType { SymNomem, SymNoreturn, SymNostack, + SymNull, SymOptions, SymOut, SymPreservesFlags, @@ -273,6 +274,7 @@ impl TokenType { SymNomem, SymNoreturn, SymNostack, + SymNull, SymOptions, SymOut, SymPreservesFlags, @@ -348,6 +350,7 @@ impl TokenType { TokenType::SymNomem => Some(sym::nomem), TokenType::SymNoreturn => Some(sym::noreturn), TokenType::SymNostack => Some(sym::nostack), + TokenType::SymNull => Some(sym::null), TokenType::SymOptions => Some(sym::options), TokenType::SymOut => Some(sym::out), TokenType::SymPreservesFlags => Some(sym::preserves_flags), @@ -562,6 +565,7 @@ macro_rules! exp { (Nomem) => { exp!(@sym, nomem, SymNomem) }; (Noreturn) => { exp!(@sym, noreturn, SymNoreturn) }; (Nostack) => { exp!(@sym, nostack, SymNostack) }; + (Null) => { exp!(@sym, null, SymNull) }; (Options) => { exp!(@sym, options, SymOptions) }; (Out) => { exp!(@sym, out, SymOut) }; (PreservesFlags) => { exp!(@sym, preserves_flags, SymPreservesFlags) }; diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index 59440e5407f4..36fc5724d51a 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -485,6 +485,7 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> { end: Some(end.stable(tables, cx)), include_end: true, }, + ty::PatternKind::NotNull => todo!(), ty::PatternKind::Or(_) => todo!(), } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8c6e9f6fb3a4..fd7ace368aa6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -968,7 +968,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc self.visit_ty_pat(pat) } } - TyPatKind::Err(_) => {} + TyPatKind::NotNull | TyPatKind::Err(_) => {} } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ef72c478951b..38340f9bd7ec 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1554,6 +1554,7 @@ symbols! { not, notable_trait, note, + null, nvptx_target_feature, object_safe_for_dispatch, of, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index d5bc831b650a..2c71b22c4a2b 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -266,6 +266,9 @@ impl<'tcx> V0SymbolMangler<'tcx> { self.print_const(start)?; self.print_const(end)?; } + ty::PatternKind::NotNull => { + self.tcx.types.unit.print(self)?; + } ty::PatternKind::Or(patterns) => { self.push("O"); for pat in patterns { diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 45cbb56b1c2e..db7bd635f32e 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -705,6 +705,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { check(start); check(end); } + ty::PatternKind::NotNull => {} ty::PatternKind::Or(patterns) => { for pat in patterns { self.add_wf_preds_for_pat_ty(base_ty, pat) diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 80067b4eab7d..b3c0953b8e14 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -216,9 +216,7 @@ fn layout_of_uncached<'tcx>( let mut layout = LayoutData::clone(&layout.0); match *pat { ty::PatternKind::Range { start, end } => { - if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) = - &mut layout.backend_repr - { + if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr { scalar.valid_range_mut().start = extract_const_value(cx, ty, start)? .try_to_bits(tcx, cx.typing_env) .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:?}") } } + 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::Range { .. } => { 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) .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?, )), - ty::PatternKind::Or(_) => { + ty::PatternKind::NotNull | ty::PatternKind::Or(_) => { 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"), }, } diff --git a/compiler/rustc_type_ir/src/pattern.rs b/compiler/rustc_type_ir/src/pattern.rs index d757ac625f2d..1f8b7158cb11 100644 --- a/compiler/rustc_type_ir/src/pattern.rs +++ b/compiler/rustc_type_ir/src/pattern.rs @@ -14,6 +14,7 @@ use crate::Interner; pub enum PatternKind { Range { start: I::Const, end: I::Const }, Or(I::PatList), + NotNull, } impl Eq for PatternKind {} diff --git a/compiler/rustc_type_ir/src/walk.rs b/compiler/rustc_type_ir/src/walk.rs index 6d51817a7bf4..e48d598a5328 100644 --- a/compiler/rustc_type_ir/src/walk.rs +++ b/compiler/rustc_type_ir/src/walk.rs @@ -178,5 +178,6 @@ fn push_ty_pat(stack: &mut TypeWalkerStack, pat: I::Pat) { push_ty_pat::(stack, pat) } } + ty::PatternKind::NotNull => {} } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index a6d821c99c1b..974596a81a40 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1123,7 +1123,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_ty_pat(variant); } }, - TyPatKind::Err(_) => {}, + TyPatKind::NotNull | TyPatKind::Err(_) => {}, } } diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index 5dce9a0c8d0f..242d8c23113c 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1099,7 +1099,7 @@ impl Rewrite for ast::TyPat { } Ok(s) } - ast::TyPatKind::Err(_) => Err(RewriteError::Unknown), + ast::TyPatKind::NotNull | ast::TyPatKind::Err(_) => Err(RewriteError::Unknown), } } } diff --git a/tests/ui/type/pattern_types/bad_pat.rs b/tests/ui/type/pattern_types/bad_pat.rs index 549b0d11dd18..7e2b4cb996f2 100644 --- a/tests/ui/type/pattern_types/bad_pat.rs +++ b/tests/ui/type/pattern_types/bad_pat.rs @@ -10,4 +10,15 @@ type Positive2 = pattern_type!(i32 is 0..=); type Wild = pattern_type!(() is _); //~^ 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() {} diff --git a/tests/ui/type/pattern_types/bad_pat.stderr b/tests/ui/type/pattern_types/bad_pat.stderr index d2a5a20bf89b..e72279542280 100644 --- a/tests/ui/type/pattern_types/bad_pat.stderr +++ b/tests/ui/type/pattern_types/bad_pat.stderr @@ -30,6 +30,24 @@ error: pattern not supported in pattern types 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`. diff --git a/tests/ui/type/pattern_types/non_null.rs b/tests/ui/type/pattern_types/non_null.rs new file mode 100644 index 000000000000..7e86b8b684d1 --- /dev/null +++ b/tests/ui/type/pattern_types/non_null.rs @@ -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 = pattern_type!(*const T is !null); //~ ERROR layout_of + +#[rustc_layout(debug)] +type Test = Option>; //~ ERROR layout_of + +#[rustc_layout(debug)] +type Wide = pattern_type!(*const [u8] is !null); //~ ERROR layout_of + +const _: () = assert!(size_of::>() == size_of::>>()); + +fn main() {} diff --git a/tests/ui/type/pattern_types/non_null.stderr b/tests/ui/type/pattern_types/non_null.stderr new file mode 100644 index 000000000000..ad61e9a59147 --- /dev/null +++ b/tests/ui/type/pattern_types/non_null.stderr @@ -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 = 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>; + | ^^^^^^^^^ + +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 +