Skip to content

Commit d0db6bc

Browse files
committed
Add or-patterns to pattern types
1 parent e578e31 commit d0db6bc

File tree

35 files changed

+477
-10
lines changed

35 files changed

+477
-10
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,6 +2364,8 @@ pub enum TyPatKind {
23642364
/// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
23652365
Range(Option<P<AnonConst>>, Option<P<AnonConst>>, Spanned<RangeEnd>),
23662366

2367+
Or(ThinVec<P<TyPat>>),
2368+
23672369
/// A `!null` pattern for raw pointers.
23682370
NotNull,
23692371

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,7 @@ pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) {
609609
visit_opt(start, |c| vis.visit_anon_const(c));
610610
visit_opt(end, |c| vis.visit_anon_const(c));
611611
}
612+
TyPatKind::Or(variants) => visit_thin_vec(variants, |p| vis.visit_ty_pat(p)),
612613
TyPatKind::NotNull | TyPatKind::Err(_) => {}
613614
}
614615
visit_lazy_tts(vis, tokens);

compiler/rustc_ast/src/visit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,7 @@ pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Res
565565
visit_opt!(visitor, visit_anon_const, start);
566566
visit_opt!(visitor, visit_anon_const, end);
567567
}
568+
TyPatKind::Or(variants) => walk_list!(visitor, visit_ty_pat, variants),
568569
TyPatKind::NotNull | TyPatKind::Err(_) => {}
569570
}
570571
V::Result::output()

compiler/rustc_ast_lowering/src/pat.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
465465
)
466466
}),
467467
),
468+
TyPatKind::Or(variants) => {
469+
hir::TyPatKind::Or(self.arena.alloc_from_iter(
470+
variants.iter().map(|pat| self.lower_ty_pat_mut(pat, base_type)),
471+
))
472+
}
468473
TyPatKind::NotNull => hir::TyPatKind::NotNull,
469474
TyPatKind::Err(guar) => hir::TyPatKind::Err(*guar),
470475
};

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,17 @@ impl<'a> State<'a> {
11671167
self.print_expr_anon_const(end, &[]);
11681168
}
11691169
}
1170+
rustc_ast::TyPatKind::Or(variants) => {
1171+
let mut first = true;
1172+
for pat in variants {
1173+
if first {
1174+
first = false
1175+
} else {
1176+
self.word(" | ");
1177+
}
1178+
self.print_ty_pat(pat);
1179+
}
1180+
}
11701181
rustc_ast::TyPatKind::NotNull => self.word("!null"),
11711182
rustc_ast::TyPatKind::Err(_) => {
11721183
self.popen();

compiler/rustc_builtin_macros/src/pattern_type.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast, token};
44
use rustc_errors::PResult;
55
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
66
use rustc_parse::exp;
7+
use rustc_parse::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
78
use rustc_span::Span;
89

910
pub(crate) fn expand<'cx>(
@@ -33,7 +34,17 @@ fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P
3334
let span = start.to(parser.token.span);
3435
ty_pat(TyPatKind::NotNull, span)
3536
} else {
36-
pat_to_ty_pat(cx, parser.parse_pat_no_top_alt(None, None)?.into_inner())
37+
pat_to_ty_pat(
38+
cx,
39+
parser
40+
.parse_pat_no_top_guard(
41+
None,
42+
RecoverComma::No,
43+
RecoverColon::No,
44+
CommaRecoveryMode::EitherTupleOrPipe,
45+
)?
46+
.into_inner(),
47+
)
3748
};
3849

3950
if parser.token != token::Eof {
@@ -53,6 +64,9 @@ fn pat_to_ty_pat(cx: &mut ExtCtxt<'_>, pat: ast::Pat) -> P<TyPat> {
5364
end.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
5465
include_end,
5566
),
67+
ast::PatKind::Or(variants) => TyPatKind::Or(
68+
variants.into_iter().map(|pat| pat_to_ty_pat(cx, pat.into_inner())).collect(),
69+
),
5670
ast::PatKind::Err(guar) => TyPatKind::Err(guar),
5771
_ => TyPatKind::Err(cx.dcx().span_err(pat.span, "pattern not supported in pattern types")),
5872
};

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ pub(crate) fn eval_nullary_intrinsic<'tcx>(
7070
ty::Pat(_, pat) => match **pat {
7171
ty::PatternKind::Range { .. } => ConstValue::from_target_usize(0u64, &tcx),
7272
ty::PatternKind::NotNull => ConstValue::from_target_usize(0_u64, &tcx),
73+
// FIXME(pattern_types): make this report the number of distinct variants used in the
74+
// or pattern in case the base type is an enum.
75+
ty::PatternKind::Or(_) => ConstValue::from_target_usize(0_u64, &tcx),
7376
},
7477
ty::Bound(_, _) => bug!("bound ty during ctfe"),
7578
ty::Bool

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1249,6 +1249,10 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
12491249
// handled fully by `visit_scalar` (called below).
12501250
ty::PatternKind::Range { .. } => {},
12511251
ty::PatternKind::NotNull => {},
1252+
1253+
// FIXME(pattern_types): check that the value is covered by one of the variants.
1254+
// The layout may pessimistically cover actually illegal ranges.
1255+
ty::PatternKind::Or(_patterns) => {}
12521256
}
12531257
}
12541258
_ => {

compiler/rustc_hir/src/hir.rs

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

1673+
/// A list of patterns where only one needs to be satisfied
1674+
Or(&'hir [TyPat<'hir>]),
1675+
16731676
/// A pattern that excludes null pointers
16741677
NotNull,
16751678

compiler/rustc_hir/src/intravisit.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -693,6 +693,7 @@ pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>)
693693
try_visit!(visitor.visit_const_arg_unambig(lower_bound));
694694
try_visit!(visitor.visit_const_arg_unambig(upper_bound));
695695
}
696+
TyPatKind::Or(patterns) => walk_list!(visitor, visit_pattern_type_pattern, patterns),
696697
TyPatKind::NotNull | TyPatKind::Err(_) => (),
697698
}
698699
V::Result::output()

0 commit comments

Comments
 (0)