diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast/src/ast.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/mut_visit.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_ast/src/visit.rs | 17 | ||||
| -rw-r--r-- | compiler/rustc_ast_lowering/src/pat.rs | 80 | ||||
| -rw-r--r-- | compiler/rustc_ast_pretty/src/pprust/state.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_builtin_macros/src/pattern_type.rs | 18 | ||||
| -rw-r--r-- | compiler/rustc_resolve/src/late.rs | 15 |
7 files changed, 121 insertions, 76 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index deee3a597ae..29c1d34a125 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -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. @@ -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)] diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index a9961cca583..de9f049704a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -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); } @@ -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); @@ -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); diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 714b074f930..3242d414595 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -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) } @@ -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)); @@ -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; diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index bb9b2a13185..e1f3afbcf59 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -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, @@ -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) } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index eeec24e5ea4..0bf5de3ef89 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -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); @@ -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(); diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs index a600a9f316a..a55c7e962d0 100644 --- a/compiler/rustc_builtin_macros/src/pattern_type.rs +++ b/compiler/rustc_builtin_macros/src/pattern_type.rs @@ -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; @@ -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)) } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 508bd831ccb..03aeb8720ca 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -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( |
