Skip to content

Commit c7621ff

Browse files
committed
Add not-null pointer patterns to pattern types
1 parent 318bb7a commit c7621ff

File tree

30 files changed

+295
-25
lines changed

30 files changed

+295
-25
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2472,6 +2472,9 @@ pub enum TyPatKind {
24722472
/// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
24732473
Range(Option<P<AnonConst>>, Option<P<AnonConst>>, Spanned<RangeEnd>),
24742474

2475+
/// A `!null` pattern for raw pointers.
2476+
NotNull,
2477+
24752478
Or(ThinVec<P<TyPat>>),
24762479

24772480
/// Placeholder for a pattern that wasn't syntactically well formed in some way.

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) {
603603
visit_opt(end, |c| vis.visit_anon_const(c));
604604
}
605605
TyPatKind::Or(variants) => visit_thin_vec(variants, |p| vis.visit_ty_pat(p)),
606-
TyPatKind::Err(_) => {}
606+
TyPatKind::NotNull | TyPatKind::Err(_) => {}
607607
}
608608
vis.visit_span(span);
609609
}

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@ pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Res
609609
visit_opt!(visitor, visit_anon_const, end);
610610
}
611611
TyPatKind::Or(variants) => walk_list!(visitor, visit_ty_pat, variants),
612-
TyPatKind::Err(_) => {}
612+
TyPatKind::NotNull | TyPatKind::Err(_) => {}
613613
}
614614
V::Result::output()
615615
}

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
143143
}
144144
// return inner to be processed in next loop
145145
PatKind::Paren(inner) => pattern = inner,
146-
PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
146+
PatKind::MacCall(_) => {
147+
panic!("{pattern:#?} shouldn't exist here")
148+
}
147149
PatKind::Err(guar) => break hir::PatKind::Err(*guar),
148150
}
149151
};
@@ -464,6 +466,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
464466
)
465467
}),
466468
),
469+
TyPatKind::NotNull => hir::TyPatKind::NotNull,
467470
TyPatKind::Or(variants) => {
468471
hir::TyPatKind::Or(self.arena.alloc_from_iter(
469472
variants.iter().map(|pat| self.lower_ty_pat_mut(pat, base_type)),

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1191,6 +1191,7 @@ impl<'a> State<'a> {
11911191
self.print_expr_anon_const(end, &[]);
11921192
}
11931193
}
1194+
rustc_ast::TyPatKind::NotNull => self.word("!null"),
11941195
rustc_ast::TyPatKind::Or(variants) => {
11951196
let mut first = true;
11961197
for pat in variants {

compiler/rustc_builtin_macros/src/pattern_type.rs

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,23 @@ fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P
2828
let ty = parser.parse_ty()?;
2929
parser.expect_keyword(exp!(Is))?;
3030

31-
let pat = pat_to_ty_pat(
32-
cx,
33-
parser
34-
.parse_pat_no_top_guard(
35-
None,
36-
RecoverComma::No,
37-
RecoverColon::No,
38-
CommaRecoveryMode::EitherTupleOrPipe,
39-
)?
40-
.into_inner(),
41-
);
31+
let start = parser.token.span;
32+
let pat = if parser.eat(exp!(Bang)) {
33+
parser.expect_keyword(exp!(Null))?;
34+
ty_pat(TyPatKind::NotNull, start.to(parser.token.span))
35+
} else {
36+
pat_to_ty_pat(
37+
cx,
38+
parser
39+
.parse_pat_no_top_guard(
40+
None,
41+
RecoverComma::No,
42+
RecoverColon::No,
43+
CommaRecoveryMode::EitherTupleOrPipe,
44+
)?
45+
.into_inner(),
46+
)
47+
};
4248

4349
if parser.token != token::Eof {
4450
parser.unexpected()?;

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,6 +1248,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
12481248
// Range patterns are precisely reflected into `valid_range` and thus
12491249
// handled fully by `visit_scalar` (called below).
12501250
ty::PatternKind::Range { .. } => {},
1251+
ty::PatternKind::NotNull => {},
12511252

12521253
// FIXME(pattern_types): check that the value is covered by one of the variants.
12531254
// For now, we rely on layout computation setting the scalar's `valid_range` to

compiler/rustc_hir/src/hir.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1824,6 +1824,9 @@ pub enum TyPatKind<'hir> {
18241824
/// A range pattern (e.g., `1..=2` or `1..2`).
18251825
Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>),
18261826

1827+
/// A pattern that excludes null pointers
1828+
NotNull,
1829+
18271830
/// A list of patterns where only one needs to be satisfied
18281831
Or(&'hir [TyPat<'hir>]),
18291832

compiler/rustc_hir/src/intravisit.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>)
711711
try_visit!(visitor.visit_const_arg_unambig(upper_bound));
712712
}
713713
TyPatKind::Or(patterns) => walk_list!(visitor, visit_pattern_type_pattern, patterns),
714-
TyPatKind::Err(_) => (),
714+
TyPatKind::NotNull | TyPatKind::Err(_) => (),
715715
}
716716
V::Result::output()
717717
}

compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2753,6 +2753,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
27532753
.span_delayed_bug(ty_span, "invalid base type for range pattern")),
27542754
}
27552755
}
2756+
hir::TyPatKind::NotNull => Ok(ty::PatternKind::NotNull),
27562757
hir::TyPatKind::Or(patterns) => {
27572758
self.tcx()
27582759
.mk_patterns_from_iter(patterns.iter().map(|pat| {

compiler/rustc_hir_analysis/src/variance/constraints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
340340
self.add_constraints_from_const(current, start, variance);
341341
self.add_constraints_from_const(current, end, variance);
342342
}
343+
ty::PatternKind::NotNull => {}
343344
ty::PatternKind::Or(patterns) => {
344345
for pat in patterns {
345346
self.add_constraints_from_pat(current, variance, pat)

compiler/rustc_hir_pretty/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,10 @@ impl<'a> State<'a> {
18701870
self.word("..=");
18711871
self.print_const_arg(end);
18721872
}
1873+
TyPatKind::NotNull => {
1874+
self.word_space("not");
1875+
self.word("null");
1876+
}
18731877
TyPatKind::Or(patterns) => {
18741878
self.popen();
18751879
let mut first = true;

compiler/rustc_lint/src/types.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,7 @@ fn pat_ty_is_known_nonnull<'tcx>(
902902
// to ensure we aren't wrapping over zero.
903903
start > 0 && end >= start
904904
}
905+
ty::PatternKind::NotNull => true,
905906
ty::PatternKind::Or(patterns) => {
906907
patterns.iter().all(|pat| pat_ty_is_known_nonnull(tcx, typing_env, pat))
907908
}
@@ -1063,7 +1064,9 @@ fn get_nullable_type_from_pat<'tcx>(
10631064
pat: ty::Pattern<'tcx>,
10641065
) -> Option<Ty<'tcx>> {
10651066
match *pat {
1066-
ty::PatternKind::Range { .. } => get_nullable_type(tcx, typing_env, base),
1067+
ty::PatternKind::NotNull | ty::PatternKind::Range { .. } => {
1068+
get_nullable_type(tcx, typing_env, base)
1069+
}
10671070
ty::PatternKind::Or(patterns) => {
10681071
let first = get_nullable_type_from_pat(tcx, typing_env, base, patterns[0])?;
10691072
for &pat in &patterns[1..] {

compiler/rustc_middle/src/ty/pattern.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ impl<'tcx> Flags for Pattern<'tcx> {
3030
}
3131
flags
3232
}
33+
ty::PatternKind::NotNull => rustc_type_ir::TypeFlags::empty(),
3334
}
3435
}
3536

@@ -45,6 +46,7 @@ impl<'tcx> Flags for Pattern<'tcx> {
4546
}
4647
idx
4748
}
49+
ty::PatternKind::NotNull => rustc_type_ir::INNERMOST,
4850
}
4951
}
5052
}
@@ -91,6 +93,7 @@ impl<'tcx> IrPrint<PatternKind<'tcx>> for TyCtxt<'tcx> {
9193

9294
write!(f, "..={end}")
9395
}
96+
PatternKind::NotNull => write!(f, "!null"),
9497
PatternKind::Or(patterns) => {
9598
write!(f, "(")?;
9699
let mut first = true;

compiler/rustc_middle/src/ty/relate.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
5959
let end = relation.relate(end_a, end_b)?;
6060
Ok(tcx.mk_pat(ty::PatternKind::Range { start, end }))
6161
}
62+
(ty::PatternKind::NotNull, ty::PatternKind::NotNull) => Ok(a),
6263
(&ty::PatternKind::Or(a), &ty::PatternKind::Or(b)) => {
6364
if a.len() != b.len() {
6465
return Err(TypeError::Mismatch);
@@ -67,7 +68,10 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
6768
let patterns = tcx.mk_patterns_from_iter(v)?;
6869
Ok(tcx.mk_pat(ty::PatternKind::Or(patterns)))
6970
}
70-
(ty::PatternKind::Range { .. } | ty::PatternKind::Or(_), _) => Err(TypeError::Mismatch),
71+
(
72+
ty::PatternKind::NotNull | ty::PatternKind::Range { .. } | ty::PatternKind::Or(_),
73+
_,
74+
) => Err(TypeError::Mismatch),
7175
}
7276
}
7377
}

compiler/rustc_parse/src/parser/token_type.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ pub enum TokenType {
139139
SymNomem,
140140
SymNoreturn,
141141
SymNostack,
142+
SymNull,
142143
SymOptions,
143144
SymOut,
144145
SymPreservesFlags,
@@ -273,6 +274,7 @@ impl TokenType {
273274
SymNomem,
274275
SymNoreturn,
275276
SymNostack,
277+
SymNull,
276278
SymOptions,
277279
SymOut,
278280
SymPreservesFlags,
@@ -348,6 +350,7 @@ impl TokenType {
348350
TokenType::SymNomem => Some(sym::nomem),
349351
TokenType::SymNoreturn => Some(sym::noreturn),
350352
TokenType::SymNostack => Some(sym::nostack),
353+
TokenType::SymNull => Some(sym::null),
351354
TokenType::SymOptions => Some(sym::options),
352355
TokenType::SymOut => Some(sym::out),
353356
TokenType::SymPreservesFlags => Some(sym::preserves_flags),
@@ -562,6 +565,7 @@ macro_rules! exp {
562565
(Nomem) => { exp!(@sym, nomem, SymNomem) };
563566
(Noreturn) => { exp!(@sym, noreturn, SymNoreturn) };
564567
(Nostack) => { exp!(@sym, nostack, SymNostack) };
568+
(Null) => { exp!(@sym, null, SymNull) };
565569
(Options) => { exp!(@sym, options, SymOptions) };
566570
(Out) => { exp!(@sym, out, SymOut) };
567571
(PreservesFlags) => { exp!(@sym, preserves_flags, SymPreservesFlags) };

compiler/rustc_resolve/src/late.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -963,7 +963,7 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
963963
self.visit_ty_pat(pat)
964964
}
965965
}
966-
TyPatKind::Err(_) => {}
966+
TyPatKind::NotNull | TyPatKind::Err(_) => {}
967967
}
968968
}
969969

compiler/rustc_smir/src/rustc_smir/convert/ty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
412412
end: Some(end.stable(tables)),
413413
include_end: true,
414414
},
415+
ty::PatternKind::NotNull => todo!(),
415416
ty::PatternKind::Or(_) => todo!(),
416417
}
417418
}

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1469,6 +1469,7 @@ symbols! {
14691469
not,
14701470
notable_trait,
14711471
note,
1472+
null,
14721473
object_safe_for_dispatch,
14731474
of,
14741475
off,

compiler/rustc_symbol_mangling/src/v0.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,9 @@ impl<'tcx> SymbolMangler<'tcx> {
262262
Ty::new_array_with_const_len(self.tcx, self.tcx.types.unit, ct).print(self)?;
263263
}
264264
}
265+
ty::PatternKind::NotNull => {
266+
self.tcx.types.unit.print(self)?;
267+
}
265268
ty::PatternKind::Or(patterns) => {
266269
for pat in patterns {
267270
self.print_pat(pat)?;

compiler/rustc_trait_selection/src/traits/wf.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -696,6 +696,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
696696
check(start);
697697
check(end);
698698
}
699+
ty::PatternKind::NotNull => {}
699700
ty::PatternKind::Or(patterns) => {
700701
for pat in patterns {
701702
self.add_wf_preds_for_pat_ty(base_ty, pat)

compiler/rustc_ty_utils/src/layout.rs

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -213,9 +213,7 @@ fn layout_of_uncached<'tcx>(
213213
let mut layout = LayoutData::clone(&layout.0);
214214
match *pat {
215215
ty::PatternKind::Range { start, end } => {
216-
if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
217-
&mut layout.backend_repr
218-
{
216+
if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
219217
scalar.valid_range_mut().start = extract_const_value(cx, ty, start)?
220218
.try_to_bits(tcx, cx.typing_env)
221219
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
@@ -263,6 +261,25 @@ fn layout_of_uncached<'tcx>(
263261
bug!("pattern type with range but not scalar layout: {ty:?}, {layout:?}")
264262
}
265263
}
264+
ty::PatternKind::NotNull => {
265+
if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
266+
&mut layout.backend_repr
267+
{
268+
scalar.valid_range_mut().start = 1;
269+
let niche = Niche {
270+
offset: Size::ZERO,
271+
value: scalar.primitive(),
272+
valid_range: scalar.valid_range(cx),
273+
};
274+
275+
layout.largest_niche = Some(niche);
276+
} else {
277+
bug!(
278+
"pattern type with `!null` pattern but not scalar/pair layout: {ty:?}, {layout:?}"
279+
)
280+
}
281+
}
282+
266283
ty::PatternKind::Or(variants) => match *variants[0] {
267284
ty::PatternKind::Range { .. } => {
268285
if let BackendRepr::Scalar(scalar) = &mut layout.backend_repr {
@@ -279,7 +296,7 @@ fn layout_of_uncached<'tcx>(
279296
.try_to_bits(tcx, cx.typing_env)
280297
.ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?,
281298
)),
282-
ty::PatternKind::Or(_) => {
299+
ty::PatternKind::NotNull | ty::PatternKind::Or(_) => {
283300
unreachable!("mixed or patterns are not allowed")
284301
}
285302
})
@@ -344,6 +361,7 @@ fn layout_of_uncached<'tcx>(
344361
)
345362
}
346363
}
364+
ty::PatternKind::NotNull => bug!("or patterns can't contain `!null` patterns"),
347365
ty::PatternKind::Or(..) => bug!("patterns cannot have nested or patterns"),
348366
},
349367
}

compiler/rustc_type_ir/src/pattern.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ use crate::Interner;
1414
pub enum PatternKind<I: Interner> {
1515
Range { start: I::Const, end: I::Const },
1616
Or(I::PatList),
17+
NotNull,
1718
}

compiler/rustc_type_ir/src/walk.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,5 +178,6 @@ fn push_ty_pat<I: Interner>(stack: &mut TypeWalkerStack<I>, pat: I::Pat) {
178178
push_ty_pat::<I>(stack, pat)
179179
}
180180
}
181+
ty::PatternKind::NotNull => {}
181182
}
182183
}

src/tools/clippy/clippy_utils/src/hir_utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1122,7 +1122,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
11221122
self.hash_ty_pat(variant);
11231123
}
11241124
},
1125-
TyPatKind::Err(_) => {},
1125+
TyPatKind::NotNull | TyPatKind::Err(_) => {},
11261126
}
11271127
}
11281128

src/tools/rustfmt/src/types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1106,7 +1106,7 @@ impl Rewrite for ast::TyPat {
11061106
}
11071107
Ok(s)
11081108
}
1109-
ast::TyPatKind::Err(_) => Err(RewriteError::Unknown),
1109+
ast::TyPatKind::NotNull | ast::TyPatKind::Err(_) => Err(RewriteError::Unknown),
11101110
}
11111111
}
11121112
}

tests/ui/type/pattern_types/bad_pat.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,15 @@ type Positive2 = pattern_type!(i32 is 0..=);
1010
type Wild = pattern_type!(() is _);
1111
//~^ ERROR: pattern not supported in pattern types
1212

13+
// FIXME: confusing diagnostic because `not` can be a binding
14+
type NonNull = pattern_type!(*const () is not null);
15+
//~^ ERROR: expected one of `@` or `|`, found `null`
16+
//~| ERROR: pattern not supported in pattern types
17+
18+
type NonNull2 = pattern_type!(*const () is !nil);
19+
//~^ ERROR: expected `null`, found `nil`
20+
21+
// FIXME: reject with a type mismatch
22+
type Mismatch2 = pattern_type!(() is !null);
23+
1324
fn main() {}

0 commit comments

Comments
 (0)