Skip to content

Commit f030893

Browse files
committed
Use a different hir type for patterns in pattern types than we use in match patterns
1 parent 613bdd4 commit f030893

File tree

27 files changed

+310
-167
lines changed

27 files changed

+310
-167
lines changed

compiler/rustc_ast_lowering/src/index.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,12 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
412412
});
413413
}
414414

415-
fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
416-
self.visit_pat(p)
415+
fn visit_pattern_type_pattern(&mut self, pat: &'hir hir::TyPat<'hir>) {
416+
self.insert(pat.span, pat.hir_id, Node::TyPat(pat));
417+
418+
self.with_parent(pat.hir_id, |this| {
419+
intravisit::walk_ty_pat(this, pat);
420+
});
417421
}
418422

419423
fn visit_precise_capturing_arg(

compiler/rustc_ast_lowering/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1377,7 +1377,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13771377
}
13781378
}
13791379
}
1380-
TyKind::Pat(ty, pat) => hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_pat(pat)),
1380+
TyKind::Pat(ty, pat) => {
1381+
hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat))
1382+
}
13811383
TyKind::MacCall(_) => {
13821384
span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")
13831385
}

compiler/rustc_ast_lowering/src/pat.rs

+78-2
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ use rustc_ast::ptr::P;
44
use rustc_ast::*;
55
use rustc_data_structures::stack::ensure_sufficient_stack;
66
use rustc_hir as hir;
7-
use rustc_hir::def::Res;
7+
use rustc_hir::def::{DefKind, Res};
88
use rustc_middle::span_bug;
99
use rustc_span::source_map::{Spanned, respan};
10-
use rustc_span::{Ident, Span};
10+
use rustc_span::{Ident, Span, kw};
1111

1212
use super::errors::{
1313
ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
@@ -429,4 +429,80 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
429429
};
430430
self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind })
431431
}
432+
433+
pub(crate) fn lower_ty_pat(&mut self, pattern: &Pat) -> &'hir hir::TyPat<'hir> {
434+
self.arena.alloc(self.lower_ty_pat_mut(pattern))
435+
}
436+
437+
fn lower_ty_pat_mut(&mut self, mut pattern: &Pat) -> hir::TyPat<'hir> {
438+
// loop here to avoid recursion
439+
let pat_hir_id = self.lower_node_id(pattern.id);
440+
let node = loop {
441+
match &pattern.kind {
442+
PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
443+
let mut lower_expr = |e: &Expr| -> &_ {
444+
let kind = if let ExprKind::Path(qself, path) = &e.kind {
445+
hir::ConstArgKind::Path(self.lower_qpath(
446+
e.id,
447+
qself,
448+
path,
449+
ParamMode::Optional,
450+
AllowReturnTypeNotation::No,
451+
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
452+
None,
453+
))
454+
} else {
455+
let node_id = self.next_node_id();
456+
let def_id = self.create_def(
457+
self.current_hir_id_owner.def_id,
458+
node_id,
459+
kw::Empty,
460+
DefKind::AnonConst,
461+
e.span,
462+
);
463+
let hir_id = self.lower_node_id(node_id);
464+
let ac = self.arena.alloc(hir::AnonConst {
465+
def_id,
466+
hir_id,
467+
body: self.lower_const_body(pattern.span, Some(e)),
468+
span: self.lower_span(pattern.span),
469+
});
470+
hir::ConstArgKind::Anon(ac)
471+
};
472+
self.arena.alloc(hir::ConstArg { hir_id: self.next_id(), kind })
473+
};
474+
break hir::TyPatKind::Range(
475+
e1.as_deref().map(|e| lower_expr(e)),
476+
e2.as_deref().map(|e| lower_expr(e)),
477+
self.lower_range_end(end, e2.is_some()),
478+
);
479+
}
480+
// return inner to be processed in next loop
481+
PatKind::Paren(inner) => pattern = inner,
482+
PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
483+
PatKind::Err(guar) => break hir::TyPatKind::Err(*guar),
484+
PatKind::Deref(..)
485+
| PatKind::Box(..)
486+
| PatKind::Or(..)
487+
| PatKind::Struct(..)
488+
| PatKind::TupleStruct(..)
489+
| PatKind::Tuple(..)
490+
| PatKind::Ref(..)
491+
| PatKind::Expr(..)
492+
| PatKind::Guard(..)
493+
| PatKind::Slice(_)
494+
| PatKind::Ident(..)
495+
| PatKind::Path(..)
496+
| PatKind::Wild
497+
| PatKind::Never
498+
| PatKind::Rest => {
499+
break hir::TyPatKind::Err(
500+
self.dcx().span_err(pattern.span, "pattern not supported in pattern types"),
501+
);
502+
}
503+
}
504+
};
505+
506+
hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }
507+
}
432508
}

compiler/rustc_driver_impl/src/pretty.rs

+4
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ impl<'tcx> pprust_hir::PpAnn for HirIdentifiedAnn<'tcx> {
101101
s.s.space();
102102
s.synth_comment(format!("pat hir_id: {}", pat.hir_id));
103103
}
104+
pprust_hir::AnnNode::TyPat(pat) => {
105+
s.s.space();
106+
s.synth_comment(format!("ty pat hir_id: {}", pat.hir_id));
107+
}
104108
pprust_hir::AnnNode::Arm(arm) => {
105109
s.s.space();
106110
s.synth_comment(format!("arm hir_id: {}", arm.hir_id));

compiler/rustc_hir/src/hir.rs

+20-1
Original file line numberDiff line numberDiff line change
@@ -1418,6 +1418,14 @@ impl<'hir> Block<'hir> {
14181418
}
14191419
}
14201420

1421+
#[derive(Debug, Clone, Copy, HashStable_Generic)]
1422+
pub struct TyPat<'hir> {
1423+
#[stable_hasher(ignore)]
1424+
pub hir_id: HirId,
1425+
pub kind: TyPatKind<'hir>,
1426+
pub span: Span,
1427+
}
1428+
14211429
#[derive(Debug, Clone, Copy, HashStable_Generic)]
14221430
pub struct Pat<'hir> {
14231431
#[stable_hasher(ignore)]
@@ -1591,6 +1599,15 @@ pub enum PatExprKind<'hir> {
15911599
Path(QPath<'hir>),
15921600
}
15931601

1602+
#[derive(Debug, Clone, Copy, HashStable_Generic)]
1603+
pub enum TyPatKind<'hir> {
1604+
/// A range pattern (e.g., `1..=2` or `1..2`).
1605+
Range(Option<&'hir ConstArg<'hir>>, Option<&'hir ConstArg<'hir>>, RangeEnd),
1606+
1607+
/// A placeholder for a pattern that wasn't well formed in some way.
1608+
Err(ErrorGuaranteed),
1609+
}
1610+
15941611
#[derive(Debug, Clone, Copy, HashStable_Generic)]
15951612
pub enum PatKind<'hir> {
15961613
/// Represents a wildcard pattern (i.e., `_`).
@@ -3345,7 +3362,7 @@ pub enum TyKind<'hir, Unambig = ()> {
33453362
/// Placeholder for a type that has failed to be defined.
33463363
Err(rustc_span::ErrorGuaranteed),
33473364
/// Pattern types (`pattern_type!(u32 is 1..)`)
3348-
Pat(&'hir Ty<'hir>, &'hir Pat<'hir>),
3365+
Pat(&'hir Ty<'hir>, &'hir TyPat<'hir>),
33493366
/// `TyKind::Infer` means the type should be inferred instead of it having been
33503367
/// specified. This can appear anywhere in a type.
33513368
///
@@ -4331,6 +4348,7 @@ pub enum Node<'hir> {
43314348
AssocItemConstraint(&'hir AssocItemConstraint<'hir>),
43324349
TraitRef(&'hir TraitRef<'hir>),
43334350
OpaqueTy(&'hir OpaqueTy<'hir>),
4351+
TyPat(&'hir TyPat<'hir>),
43344352
Pat(&'hir Pat<'hir>),
43354353
PatField(&'hir PatField<'hir>),
43364354
/// Needed as its own node with its own HirId for tracking
@@ -4393,6 +4411,7 @@ impl<'hir> Node<'hir> {
43934411
| Node::Block(..)
43944412
| Node::Ctor(..)
43954413
| Node::Pat(..)
4414+
| Node::TyPat(..)
43964415
| Node::PatExpr(..)
43974416
| Node::Arm(..)
43984417
| Node::LetStmt(..)

compiler/rustc_hir/src/intravisit.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -393,10 +393,8 @@ pub trait Visitor<'v>: Sized {
393393
fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
394394
walk_expr_field(self, field)
395395
}
396-
fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) {
397-
// Do nothing. Only a few visitors need to know the details of the pattern type,
398-
// and they opt into it. All other visitors will just choke on our fake patterns
399-
// because they aren't in a body.
396+
fn visit_pattern_type_pattern(&mut self, p: &'v TyPat<'v>) -> Self::Result {
397+
walk_ty_pat(self, p)
400398
}
401399
fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
402400
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
702700
visitor.visit_expr(arm.body)
703701
}
704702

703+
pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) -> V::Result {
704+
try_visit!(visitor.visit_id(pattern.hir_id));
705+
match pattern.kind {
706+
TyPatKind::Range(lower_bound, upper_bound, _) => {
707+
visit_opt!(visitor, visit_const_arg_unambig, lower_bound);
708+
visit_opt!(visitor, visit_const_arg_unambig, upper_bound);
709+
}
710+
TyPatKind::Err(_) => (),
711+
}
712+
V::Result::output()
713+
}
714+
705715
pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V::Result {
706716
try_visit!(visitor.visit_id(pattern.hir_id));
707717
match pattern.kind {

compiler/rustc_hir_analysis/messages.ftl

-3
Original file line numberDiff line numberDiff line change
@@ -436,9 +436,6 @@ hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a t
436436
hir_analysis_parenthesized_fn_trait_expansion =
437437
parenthesized trait syntax expands to `{$expanded_type}`
438438
439-
hir_analysis_pattern_type_non_const_range = range patterns must have constant range start and end
440-
hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pattern types
441-
.label = this type is the same as the inner type without a pattern
442439
hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
443440
.label = not allowed in type signatures
444441
hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias

compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -831,8 +831,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
831831
}
832832

833833
#[instrument(level = "debug", skip(self))]
834-
fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::Pat<'tcx>) {
835-
intravisit::walk_pat(self, p)
834+
fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::TyPat<'tcx>) {
835+
intravisit::walk_ty_pat(self, p)
836836
}
837837

838838
#[instrument(level = "debug", skip(self))]

compiler/rustc_hir_analysis/src/collect/type_of.rs

+16-5
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ use crate::hir_ty_lowering::HirTyLowerer;
1818

1919
mod opaque;
2020

21-
fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
21+
fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
2222
use hir::*;
2323
use rustc_middle::ty::Ty;
24+
let tcx = icx.tcx;
2425
let hir_id = tcx.local_def_id_to_hir_id(def_id);
2526

2627
let node = tcx.hir_node(hir_id);
@@ -54,7 +55,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
5455
hir_id: arg_hir_id,
5556
kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }),
5657
..
57-
}) if anon_hir_id == hir_id => const_arg_anon_type_of(tcx, arg_hir_id, span),
58+
}) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span),
5859

5960
// Anon consts outside the type system.
6061
Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
@@ -138,18 +139,28 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
138139
}
139140
}
140141

141-
fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> {
142+
fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> {
142143
use hir::*;
143144
use rustc_middle::ty::Ty;
144145

146+
let tcx = icx.tcx;
147+
145148
match tcx.parent_hir_node(arg_hir_id) {
146149
// Array length const arguments do not have `type_of` fed as there is never a corresponding
147150
// generic parameter definition.
148151
Node::Ty(&hir::Ty { kind: TyKind::Array(_, ref constant), .. })
149152
| Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
150153
if constant.hir_id == arg_hir_id =>
151154
{
152-
return tcx.types.usize;
155+
tcx.types.usize
156+
}
157+
158+
Node::TyPat(pat) => {
159+
let hir::TyKind::Pat(ty, p) = tcx.parent_hir_node(pat.hir_id).expect_ty().kind else {
160+
bug!()
161+
};
162+
assert_eq!(p.hir_id, pat.hir_id);
163+
icx.lower_ty(ty)
153164
}
154165

155166
// This is not a `bug!` as const arguments in path segments that did not resolve to anything
@@ -344,7 +355,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
344355
tcx.typeck(def_id).node_type(hir_id)
345356
}
346357

347-
Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
358+
Node::AnonConst(_) => anon_const_type_of(&icx, def_id),
348359

349360
Node::ConstBlock(_) => {
350361
let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id());

compiler/rustc_hir_analysis/src/errors.rs

-7
Original file line numberDiff line numberDiff line change
@@ -1605,13 +1605,6 @@ pub(crate) struct OpaqueCapturesHigherRankedLifetime {
16051605
pub bad_place: &'static str,
16061606
}
16071607

1608-
#[derive(Diagnostic)]
1609-
#[diag(hir_analysis_pattern_type_non_const_range)]
1610-
pub(crate) struct NonConstRange {
1611-
#[primary_span]
1612-
pub span: Span,
1613-
}
1614-
16151608
#[derive(Subdiagnostic)]
16161609
pub(crate) enum InvalidReceiverTyHint {
16171610
#[note(hir_analysis_invalid_receiver_ty_help_weak_note)]

compiler/rustc_hir_analysis/src/errors/pattern_types.rs

-7
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,6 @@ use rustc_macros::Diagnostic;
22
use rustc_middle::ty::Ty;
33
use rustc_span::Span;
44

5-
#[derive(Diagnostic)]
6-
#[diag(hir_analysis_pattern_type_wild_pat)]
7-
pub(crate) struct WildPatTy {
8-
#[primary_span]
9-
pub span: Span,
10-
}
11-
125
#[derive(Diagnostic)]
136
#[diag(hir_analysis_invalid_base_type)]
147
pub(crate) struct InvalidBaseType<'tcx> {

0 commit comments

Comments
 (0)