1
Fork 0

Use a different hir type for patterns in pattern types than we use in match patterns

This commit is contained in:
Oli Scherer 2025-01-07 10:24:16 +00:00
parent 613bdd4997
commit f0308938ba
27 changed files with 311 additions and 168 deletions

View file

@ -412,8 +412,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
});
}
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
self.visit_pat(p)
fn visit_pattern_type_pattern(&mut self, pat: &'hir hir::TyPat<'hir>) {
self.insert(pat.span, pat.hir_id, Node::TyPat(pat));
self.with_parent(pat.hir_id, |this| {
intravisit::walk_ty_pat(this, pat);
});
}
fn visit_precise_capturing_arg(

View file

@ -1377,7 +1377,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
}
}
}
TyKind::Pat(ty, pat) => hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_pat(pat)),
TyKind::Pat(ty, pat) => {
hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat))
}
TyKind::MacCall(_) => {
span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")
}

View file

@ -4,10 +4,10 @@ use rustc_ast::ptr::P;
use rustc_ast::*;
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_hir as hir;
use rustc_hir::def::Res;
use rustc_hir::def::{DefKind, Res};
use rustc_middle::span_bug;
use rustc_span::source_map::{Spanned, respan};
use rustc_span::{Ident, Span};
use rustc_span::{Ident, Span, kw};
use super::errors::{
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
@ -429,4 +429,80 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
};
self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind })
}
pub(crate) fn lower_ty_pat(&mut self, pattern: &Pat) -> &'hir hir::TyPat<'hir> {
self.arena.alloc(self.lower_ty_pat_mut(pattern))
}
fn lower_ty_pat_mut(&mut self, mut pattern: &Pat) -> hir::TyPat<'hir> {
// loop here to avoid recursion
let pat_hir_id = self.lower_node_id(pattern.id);
let node = loop {
match &pattern.kind {
PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
let mut lower_expr = |e: &Expr| -> &_ {
let kind = if let ExprKind::Path(qself, path) = &e.kind {
hir::ConstArgKind::Path(self.lower_qpath(
e.id,
qself,
path,
ParamMode::Optional,
AllowReturnTypeNotation::No,
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None,
))
} else {
let node_id = self.next_node_id();
let def_id = self.create_def(
self.current_hir_id_owner.def_id,
node_id,
kw::Empty,
DefKind::AnonConst,
e.span,
);
let hir_id = self.lower_node_id(node_id);
let ac = self.arena.alloc(hir::AnonConst {
def_id,
hir_id,
body: self.lower_const_body(pattern.span, Some(e)),
span: self.lower_span(pattern.span),
});
hir::ConstArgKind::Anon(ac)
};
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind })
};
break hir::TyPatKind::Range(
e1.as_deref().map(|e| lower_expr(e)),
e2.as_deref().map(|e| lower_expr(e)),
self.lower_range_end(end, e2.is_some()),
);
}
// return inner to be processed in next loop
PatKind::Paren(inner) => pattern = inner,
PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
PatKind::Err(guar) => break hir::TyPatKind::Err(*guar),
PatKind::Deref(..)
| PatKind::Box(..)
| PatKind::Or(..)
| PatKind::Struct(..)
| PatKind::TupleStruct(..)
| PatKind::Tuple(..)
| PatKind::Ref(..)
| PatKind::Expr(..)
| PatKind::Guard(..)
| PatKind::Slice(_)
| PatKind::Ident(..)
| PatKind::Path(..)
| PatKind::Wild
| PatKind::Never
| PatKind::Rest => {
break hir::TyPatKind::Err(
self.dcx().span_err(pattern.span, "pattern not supported in pattern types"),
);
}
}
};
hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }
}
}