Skip to content

Commit

Permalink
Unrolled build for rust-lang#136646
Browse files Browse the repository at this point in the history
Rollup merge of rust-lang#136646 - oli-obk:pattern-types-ast, r=BoxyUwU

Add a TyPat in the AST to reuse the generic arg lowering logic

This simplifies ast lowering significantly with little cost to the pattern types parser.

Also fixes any problems we've had with generic args (well, pushes any problems onto the `generic_const_exprs` feature gate)

follow-up to rust-lang#136284 (comment)

r? ``@BoxyUwU``
  • Loading branch information
rust-timer authored Feb 12, 2025
2 parents 672e3aa + 6d7ce4e commit aad75b1
Show file tree
Hide file tree
Showing 21 changed files with 241 additions and 264 deletions.
23 changes: 22 additions & 1 deletion compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2249,7 +2249,7 @@ pub enum TyKind {
CVarArgs,
/// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`,
/// just as part of the type system.
Pat(P<Ty>, P<Pat>),
Pat(P<Ty>, P<TyPat>),
/// Sometimes we need a dummy value when no error has occurred.
Dummy,
/// Placeholder for a kind that has failed to be defined.
Expand Down Expand Up @@ -2277,6 +2277,27 @@ impl TyKind {
}
}

/// A pattern type pattern.
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct TyPat {
pub id: NodeId,
pub kind: TyPatKind,
pub span: Span,
pub tokens: Option<LazyAttrTokenStream>,
}

/// All the different flavors of pattern that Rust recognizes.
//
// Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`.
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum TyPatKind {
/// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
Range(Option<P<AnonConst>>, Option<P<AnonConst>>, Spanned<RangeEnd>),

/// Placeholder for a pattern that wasn't syntactically well formed in some way.
Err(ErrorGuaranteed),
}

/// Syntax used to declare a trait object.
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
#[repr(u8)]
Expand Down
20 changes: 19 additions & 1 deletion compiler/rustc_ast/src/mut_visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,10 @@ pub trait MutVisitor: Sized {
walk_ty(self, t);
}

fn visit_ty_pat(&mut self, t: &mut P<TyPat>) {
walk_ty_pat(self, t);
}

fn visit_lifetime(&mut self, l: &mut Lifetime) {
walk_lifetime(self, l);
}
Expand Down Expand Up @@ -570,7 +574,7 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
TyKind::Paren(ty) => vis.visit_ty(ty),
TyKind::Pat(ty, pat) => {
vis.visit_ty(ty);
vis.visit_pat(pat);
vis.visit_ty_pat(pat);
}
TyKind::Path(qself, path) => {
vis.visit_qself(qself);
Expand All @@ -594,6 +598,20 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
vis.visit_span(span);
}

pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) {
let TyPat { id, kind, span, tokens } = ty.deref_mut();
vis.visit_id(id);
match kind {
TyPatKind::Range(start, end, _include_end) => {
visit_opt(start, |c| vis.visit_anon_const(c));
visit_opt(end, |c| vis.visit_anon_const(c));
}
TyPatKind::Err(_) => {}
}
visit_lazy_tts(vis, tokens);
vis.visit_span(span);
}

fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) {
let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
visit_safety(vis, safety);
Expand Down
17 changes: 16 additions & 1 deletion compiler/rustc_ast/src/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ pub trait Visitor<'ast>: Sized {
fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result {
walk_ty(self, t)
}
fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
walk_ty_pat(self, t)
}
fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result {
walk_generic_param(self, param)
}
Expand Down Expand Up @@ -534,7 +537,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
}
TyKind::Pat(ty, pat) => {
try_visit!(visitor.visit_ty(ty));
try_visit!(visitor.visit_pat(pat));
try_visit!(visitor.visit_ty_pat(pat));
}
TyKind::Array(ty, length) => {
try_visit!(visitor.visit_ty(ty));
Expand All @@ -555,6 +558,18 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
V::Result::output()
}

pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Result {
let TyPat { id: _, kind, span: _, tokens: _ } = tp;
match kind {
TyPatKind::Range(start, end, _include_end) => {
visit_opt!(visitor, visit_anon_const, start);
visit_opt!(visitor, visit_anon_const, end);
}
TyPatKind::Err(_) => {}
}
V::Result::output()
}

fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option<P<QSelf>>) -> V::Result {
if let Some(qself) = qself {
let QSelf { ty, path_span: _, position: _ } = &**qself;
Expand Down
80 changes: 11 additions & 69 deletions compiler/rustc_ast_lowering/src/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{DefKind, Res};
use rustc_hir::def::Res;
use rustc_middle::span_bug;
use rustc_span::source_map::{Spanned, respan};
use rustc_span::{Ident, Span, kw};
use rustc_span::{Ident, Span};

use super::errors::{
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
Expand Down Expand Up @@ -430,78 +430,20 @@ 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> {
pub(crate) fn lower_ty_pat(&mut self, pattern: &TyPat) -> &'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> {
fn lower_ty_pat_mut(&mut self, pattern: &TyPat) -> 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, .. }) => {
// FIXME(pattern_types): remove this closure and call `lower_const_arg` instead.
// That requires first modifying the AST to have const args here.
let mut lower_expr = |e: &Expr| -> &_ {
if let ExprKind::Path(None, path) = &e.kind
&& let Some(res) = self
.resolver
.get_partial_res(e.id)
.and_then(|partial_res| partial_res.full_res())
{
self.lower_const_path_to_const_arg(path, res, e.id, e.span)
} 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),
});
self.arena.alloc(hir::ConstArg {
hir_id: self.next_id(),
kind: hir::ConstArgKind::Anon(ac),
})
}
};
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"),
);
}
}
let node = match &pattern.kind {
TyPatKind::Range(e1, e2, Spanned { node: end, .. }) => hir::TyPatKind::Range(
e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
e2.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
self.lower_range_end(end, e2.is_some()),
),
TyPatKind::Err(guar) => hir::TyPatKind::Err(*guar),
};

hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }
Expand Down
24 changes: 23 additions & 1 deletion compiler/rustc_ast_pretty/src/pprust/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1148,6 +1148,28 @@ impl<'a> State<'a> {
}
}

pub fn print_ty_pat(&mut self, pat: &ast::TyPat) {
match &pat.kind {
rustc_ast::TyPatKind::Range(start, end, include_end) => {
if let Some(start) = start {
self.print_expr_anon_const(start, &[]);
}
self.word("..");
if let Some(end) = end {
if let RangeEnd::Included(_) = include_end.node {
self.word("=");
}
self.print_expr_anon_const(end, &[]);
}
}
rustc_ast::TyPatKind::Err(_) => {
self.popen();
self.word("/*ERROR*/");
self.pclose();
}
}
}

pub fn print_type(&mut self, ty: &ast::Ty) {
self.maybe_print_comment(ty.span.lo());
self.ibox(0);
Expand Down Expand Up @@ -1252,7 +1274,7 @@ impl<'a> State<'a> {
ast::TyKind::Pat(ty, pat) => {
self.print_type(ty);
self.word(" is ");
self.print_pat(pat);
self.print_ty_pat(pat);
}
}
self.end();
Expand Down
18 changes: 15 additions & 3 deletions compiler/rustc_builtin_macros/src/pattern_type.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rustc_ast::ptr::P;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{Pat, Ty, ast};
use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast};
use rustc_errors::PResult;
use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_parse::exp;
Expand All @@ -21,12 +21,24 @@ pub(crate) fn expand<'cx>(
ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat))))
}

fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<Pat>)> {
fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<TyPat>)> {
let mut parser = cx.new_parser_from_tts(stream);

let ty = parser.parse_ty()?;
parser.expect_keyword(exp!(Is))?;
let pat = parser.parse_pat_no_top_alt(None, None)?;
let pat = parser.parse_pat_no_top_alt(None, None)?.into_inner();

let kind = match pat.kind {
ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
start.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
end.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
include_end,
),
ast::PatKind::Err(guar) => TyPatKind::Err(guar),
_ => TyPatKind::Err(cx.dcx().span_err(pat.span, "pattern not supported in pattern types")),
};

let pat = P(TyPat { id: pat.id, kind, span: pat.span, tokens: pat.tokens });

Ok((ty, pat))
}
15 changes: 15 additions & 0 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -923,6 +923,21 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
self.diag_metadata.current_trait_object = prev;
self.diag_metadata.current_type_path = prev_ty;
}

fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
match &t.kind {
TyPatKind::Range(start, end, _) => {
if let Some(start) = start {
self.resolve_anon_const(start, AnonConstKind::ConstArg(IsRepeatExpr::No));
}
if let Some(end) = end {
self.resolve_anon_const(end, AnonConstKind::ConstArg(IsRepeatExpr::No));
}
}
TyPatKind::Err(_) => {}
}
}

fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) {
let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo());
self.with_generic_param_rib(
Expand Down
Loading

0 comments on commit aad75b1

Please sign in to comment.