1
Fork 0

Rollup merge of #136284 - oli-obk:push-zsxuwnzmonnl, r=lcnr

Allow using named consts in pattern types

This required a refactoring first: I had to stop using `hir::Pat`in `hir::TyKind::Pat` and instead create a separate `TyPat` that has `ConstArg` for range ends instead of `PatExpr`. Within the type system we should be using `ConstArg` for all constants, as otherwise we'd be maintaining two separate const systems that could diverge. The big advantage of this PR is that we now inherit all the rules from const generics and don't have a separate system. While this makes things harder for users (const generic rules wrt what is allowed in those consts), it also means we don't accidentally allow some things like referring to assoc consts or doing math on generic consts.
This commit is contained in:
Matthias Krüger 2025-02-04 18:49:37 +01:00 committed by GitHub
commit b07fa7696b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 475 additions and 202 deletions

View file

@ -1418,6 +1418,14 @@ impl<'hir> Block<'hir> {
}
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct TyPat<'hir> {
#[stable_hasher(ignore)]
pub hir_id: HirId,
pub kind: TyPatKind<'hir>,
pub span: Span,
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub struct Pat<'hir> {
#[stable_hasher(ignore)]
@ -1591,6 +1599,15 @@ pub enum PatExprKind<'hir> {
Path(QPath<'hir>),
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum TyPatKind<'hir> {
/// A range pattern (e.g., `1..=2` or `1..2`).
Range(Option<&'hir ConstArg<'hir>>, Option<&'hir ConstArg<'hir>>, RangeEnd),
/// A placeholder for a pattern that wasn't well formed in some way.
Err(ErrorGuaranteed),
}
#[derive(Debug, Clone, Copy, HashStable_Generic)]
pub enum PatKind<'hir> {
/// Represents a wildcard pattern (i.e., `_`).
@ -3384,7 +3401,7 @@ pub enum TyKind<'hir, Unambig = ()> {
/// Placeholder for a type that has failed to be defined.
Err(rustc_span::ErrorGuaranteed),
/// Pattern types (`pattern_type!(u32 is 1..)`)
Pat(&'hir Ty<'hir>, &'hir Pat<'hir>),
Pat(&'hir Ty<'hir>, &'hir TyPat<'hir>),
/// `TyKind::Infer` means the type should be inferred instead of it having been
/// specified. This can appear anywhere in a type.
///
@ -4370,6 +4387,7 @@ pub enum Node<'hir> {
AssocItemConstraint(&'hir AssocItemConstraint<'hir>),
TraitRef(&'hir TraitRef<'hir>),
OpaqueTy(&'hir OpaqueTy<'hir>),
TyPat(&'hir TyPat<'hir>),
Pat(&'hir Pat<'hir>),
PatField(&'hir PatField<'hir>),
/// Needed as its own node with its own HirId for tracking
@ -4432,6 +4450,7 @@ impl<'hir> Node<'hir> {
| Node::Block(..)
| Node::Ctor(..)
| Node::Pat(..)
| Node::TyPat(..)
| Node::PatExpr(..)
| Node::Arm(..)
| Node::LetStmt(..)

View file

@ -393,10 +393,8 @@ pub trait Visitor<'v>: Sized {
fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
walk_expr_field(self, field)
}
fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) {
// Do nothing. Only a few visitors need to know the details of the pattern type,
// and they opt into it. All other visitors will just choke on our fake patterns
// because they aren't in a body.
fn visit_pattern_type_pattern(&mut self, p: &'v TyPat<'v>) -> Self::Result {
walk_ty_pat(self, p)
}
fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
walk_generic_param(self, p)
@ -702,6 +700,18 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Res
visitor.visit_expr(arm.body)
}
pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) -> V::Result {
try_visit!(visitor.visit_id(pattern.hir_id));
match pattern.kind {
TyPatKind::Range(lower_bound, upper_bound, _) => {
visit_opt!(visitor, visit_const_arg_unambig, lower_bound);
visit_opt!(visitor, visit_const_arg_unambig, upper_bound);
}
TyPatKind::Err(_) => (),
}
V::Result::output()
}
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V::Result {
try_visit!(visitor.visit_id(pattern.hir_id));
match pattern.kind {