Skip to content

Commit c9365dd

Browse files
committed
Exhaustively handle expressions in patterns
1 parent 5df6919 commit c9365dd

36 files changed

Lines changed: 447 additions & 197 deletions

File tree

‎compiler/rustc_ast_lowering/src/expr.rs‎

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
102102

103103
let kind = match&e.kind{
104104
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
105-
ExprKind::ConstBlock(c) => {
106-
let c = self.with_new_scopes(c.value.span, |this| {
107-
let def_id = this.local_def_id(c.id);
108-
hir::ConstBlock{
109-
def_id,
110-
hir_id: this.lower_node_id(c.id),
111-
body: this.lower_const_body(c.value.span,Some(&c.value)),
112-
}
113-
});
114-
hir::ExprKind::ConstBlock(c)
115-
}
105+
ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_const_block(c)),
116106
ExprKind::Repeat(expr, count) => {
117107
let expr = self.lower_expr(expr);
118108
let count = self.lower_array_length_to_const_arg(count);
@@ -153,18 +143,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
153143
let ohs = self.lower_expr(ohs);
154144
hir::ExprKind::Unary(op, ohs)
155145
}
156-
ExprKind::Lit(token_lit) => {
157-
let lit_kind = matchLitKind::from_token_lit(*token_lit){
158-
Ok(lit_kind) => lit_kind,
159-
Err(err) => {
160-
let guar =
161-
report_lit_error(&self.tcx.sess.psess, err,*token_lit, e.span);
162-
LitKind::Err(guar)
163-
}
164-
};
165-
let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind));
166-
hir::ExprKind::Lit(lit)
167-
}
146+
ExprKind::Lit(token_lit) => hir::ExprKind::Lit(self.lower_lit(token_lit, e.span)),
168147
ExprKind::IncludedBytes(bytes) => {
169148
let lit = self.arena.alloc(respan(
170149
self.lower_span(e.span),
@@ -403,6 +382,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
403382
})
404383
}
405384

385+
pub(crate)fnlower_const_block(&mutself,c:&AnonConst) -> hir::ConstBlock{
386+
self.with_new_scopes(c.value.span, |this| {
387+
let def_id = this.local_def_id(c.id);
388+
hir::ConstBlock{
389+
def_id,
390+
hir_id: this.lower_node_id(c.id),
391+
body: this.lower_const_body(c.value.span,Some(&c.value)),
392+
}
393+
})
394+
}
395+
396+
pub(crate)fnlower_lit(
397+
&mutself,
398+
token_lit:&token::Lit,
399+
span:Span,
400+
) -> &'hirSpanned<LitKind>{
401+
let lit_kind = matchLitKind::from_token_lit(*token_lit){
402+
Ok(lit_kind) => lit_kind,
403+
Err(err) => {
404+
let guar = report_lit_error(&self.tcx.sess.psess, err,*token_lit, span);
405+
LitKind::Err(guar)
406+
}
407+
};
408+
self.arena.alloc(respan(self.lower_span(span), lit_kind))
409+
}
410+
406411
fnlower_unop(&mutself,u:UnOp) -> hir::UnOp{
407412
match u {
408413
UnOp::Deref => hir::UnOp::Deref,

‎compiler/rustc_ast_lowering/src/index.rs‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
209209
});
210210
}
211211

212+
fnvisit_pat_expr(&mutself,expr:&'hirPatExpr<'hir>){
213+
self.insert(expr.span, expr.hir_id,Node::PatExpr(expr));
214+
215+
self.with_parent(expr.hir_id, |this| {
216+
intravisit::walk_pat_expr(this, expr);
217+
});
218+
}
219+
212220
fnvisit_pat_field(&mutself,field:&'hirPatField<'hir>){
213221
self.insert(field.span, field.hir_id,Node::PatField(field));
214222
self.with_parent(field.hir_id, |this| {

‎compiler/rustc_ast_lowering/src/lib.rs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#![doc(rust_logo)]
3636
#![feature(assert_matches)]
3737
#![feature(box_patterns)]
38+
#![feature(if_let_guard)]
3839
#![feature(let_chains)]
3940
#![feature(rustdoc_internals)]
4041
#![warn(unreachable_pub)]

‎compiler/rustc_ast_lowering/src/pat.rs‎

Lines changed: 46 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1+
use std::sync::Arc;
2+
13
use rustc_ast::ptr::P;
24
use rustc_ast::*;
35
use rustc_data_structures::stack::ensure_sufficient_stack;
46
use rustc_hir as hir;
57
use rustc_hir::def::Res;
6-
use rustc_span::source_map::Spanned;
8+
use rustc_middle::span_bug;
9+
use rustc_span::source_map::{Spanned, respan};
710
use rustc_span::{Ident,Span};
811

912
usesuper::errors::{
@@ -367,24 +370,54 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
367370
// }
368371
// m!(S);
369372
// ```
370-
fnlower_expr_within_pat(&mutself,expr:&Expr,allow_paths:bool) -> &'hir hir::Expr<'hir>{
371-
match&expr.kind{
372-
ExprKind::Lit(..)
373-
| ExprKind::ConstBlock(..)
374-
| ExprKind::IncludedBytes(..)
375-
| ExprKind::Err(_)
376-
| ExprKind::Dummy => {}
377-
ExprKind::Path(..)if allow_paths => {}
378-
ExprKind::Unary(UnOp::Neg, inner)ifmatches!(inner.kind,ExprKind::Lit(_)) => {}
373+
fnlower_expr_within_pat(
374+
&mutself,
375+
expr:&Expr,
376+
allow_paths:bool,
377+
) -> &'hir hir::PatExpr<'hir>{
378+
let err = |guar| hir::PatExprKind::Lit{
379+
lit:self.arena.alloc(respan(self.lower_span(expr.span),LitKind::Err(guar))),
380+
negated:false,
381+
};
382+
let kind = match&expr.kind{
383+
ExprKind::Lit(lit) => {
384+
hir::PatExprKind::Lit{lit:self.lower_lit(lit, expr.span),negated:false}
385+
}
386+
ExprKind::ConstBlock(c) => hir::PatExprKind::ConstBlock(self.lower_const_block(c)),
387+
ExprKind::IncludedBytes(bytes) => hir::PatExprKind::Lit{
388+
lit:self.arena.alloc(respan(
389+
self.lower_span(expr.span),
390+
LitKind::ByteStr(Arc::clone(bytes),StrStyle::Cooked),
391+
)),
392+
negated:false,
393+
},
394+
ExprKind::Err(guar) => err(*guar),
395+
ExprKind::Dummy => span_bug!(expr.span,"lowered ExprKind::Dummy"),
396+
ExprKind::Path(qself, path)if allow_paths => hir::PatExprKind::Path(self.lower_qpath(
397+
expr.id,
398+
qself,
399+
path,
400+
ParamMode::Optional,
401+
AllowReturnTypeNotation::No,
402+
ImplTraitContext::Disallowed(ImplTraitPosition::Path),
403+
None,
404+
)),
405+
ExprKind::Unary(UnOp::Neg, inner)ifletExprKind::Lit(lit) = &inner.kind => {
406+
hir::PatExprKind::Lit{lit:self.lower_lit(lit, expr.span),negated:true}
407+
}
379408
_ => {
380409
let pattern_from_macro = expr.is_approximately_pattern();
381410
let guar = self.dcx().emit_err(ArbitraryExpressionInPattern{
382411
span: expr.span,
383412
pattern_from_macro_note: pattern_from_macro,
384413
});
385-
returnself.arena.alloc(self.expr_err(expr.span,guar));
414+
err(guar)
386415
}
387-
}
388-
self.lower_expr(expr)
416+
};
417+
self.arena.alloc(hir::PatExpr{
418+
hir_id:self.lower_node_id(expr.id),
419+
span: expr.span,
420+
kind,
421+
})
389422
}
390423
}

‎compiler/rustc_hir/src/hir.rs‎

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,6 +1519,26 @@ impl fmt::Debug for DotDotPos {
15191519
}
15201520
}
15211521

1522+
#[derive(Debug,Clone,Copy,HashStable_Generic)]
1523+
pubstructPatExpr<'hir>{
1524+
pubhir_id:HirId,
1525+
pubspan:Span,
1526+
pubkind:PatExprKind<'hir>,
1527+
}
1528+
1529+
#[derive(Debug,Clone,Copy,HashStable_Generic)]
1530+
pubenumPatExprKind<'hir>{
1531+
Lit{
1532+
lit:&'hirLit,
1533+
// FIXME: move this into `Lit` and handle negated literal expressions
1534+
// once instead of matching on unop neg expressions everywhere.
1535+
negated:bool,
1536+
},
1537+
ConstBlock(ConstBlock),
1538+
/// A path pattern for a unit struct/variant or a (maybe-associated) constant.
1539+
Path(QPath<'hir>),
1540+
}
1541+
15221542
#[derive(Debug,Clone,Copy,HashStable_Generic)]
15231543
pubenumPatKind<'hir>{
15241544
/// Represents a wildcard pattern (i.e., `_`).
@@ -1564,13 +1584,13 @@ pub enum PatKind<'hir> {
15641584
Ref(&'hirPat<'hir>,Mutability),
15651585

15661586
/// A literal.
1567-
Lit(&'hirExpr<'hir>),
1587+
Lit(&'hirPatExpr<'hir>),
15681588

15691589
/// A guard pattern (e.g., `x if guard(x)`).
15701590
Guard(&'hirPat<'hir>,&'hirExpr<'hir>),
15711591

15721592
/// A range pattern (e.g., `1..=2` or `1..2`).
1573-
Range(Option<&'hirExpr<'hir>>,Option<&'hirExpr<'hir>>,RangeEnd),
1593+
Range(Option<&'hirPatExpr<'hir>>,Option<&'hirPatExpr<'hir>>,RangeEnd),
15741594

15751595
/// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
15761596
///
@@ -4144,6 +4164,10 @@ pub enum Node<'hir> {
41444164
OpaqueTy(&'hirOpaqueTy<'hir>),
41454165
Pat(&'hirPat<'hir>),
41464166
PatField(&'hirPatField<'hir>),
4167+
/// Needed as its own node with its own HirId for tracking
4168+
/// the unadjusted type of literals within patterns
4169+
/// (e.g. byte str literals not being of slice type).
4170+
PatExpr(&'hirPatExpr<'hir>),
41474171
Arm(&'hirArm<'hir>),
41484172
Block(&'hirBlock<'hir>),
41494173
LetStmt(&'hirLetStmt<'hir>),
@@ -4200,6 +4224,7 @@ impl<'hir> Node<'hir> {
42004224
| Node::Block(..)
42014225
| Node::Ctor(..)
42024226
| Node::Pat(..)
4227+
| Node::PatExpr(..)
42034228
| Node::Arm(..)
42044229
| Node::LetStmt(..)
42054230
| Node::Crate(..)

‎compiler/rustc_hir/src/intravisit.rs‎

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ pub trait Visitor<'v>: Sized {
342342
fnvisit_pat_field(&mutself,f:&'vPatField<'v>) -> Self::Result{
343343
walk_pat_field(self, f)
344344
}
345+
fnvisit_pat_expr(&mutself,expr:&'vPatExpr<'v>) -> Self::Result{
346+
walk_pat_expr(self, expr)
347+
}
345348
fnvisit_anon_const(&mutself,c:&'vAnonConst) -> Self::Result{
346349
walk_anon_const(self, c)
347350
}
@@ -685,10 +688,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
685688
try_visit!(visitor.visit_ident(ident));
686689
visit_opt!(visitor, visit_pat, optional_subpattern);
687690
}
688-
PatKind::Lit(ref expression) => try_visit!(visitor.visit_expr(expression)),
691+
PatKind::Lit(ref expression) => try_visit!(visitor.visit_pat_expr(expression)),
689692
PatKind::Range(ref lower_bound,ref upper_bound, _) => {
690-
visit_opt!(visitor,visit_expr, lower_bound);
691-
visit_opt!(visitor,visit_expr, upper_bound);
693+
visit_opt!(visitor,visit_pat_expr, lower_bound);
694+
visit_opt!(visitor,visit_pat_expr, upper_bound);
692695
}
693696
PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
694697
PatKind::Slice(prepatterns,ref slice_pattern, postpatterns) => {
@@ -710,6 +713,15 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
710713
visitor.visit_pat(field.pat)
711714
}
712715

716+
pubfnwalk_pat_expr<'v,V:Visitor<'v>>(visitor:&mutV,expr:&'vPatExpr<'v>) -> V::Result{
717+
try_visit!(visitor.visit_id(expr.hir_id));
718+
match&expr.kind{
719+
PatExprKind::Lit{ .. } => V::Result::output(),
720+
PatExprKind::ConstBlock(c) => visitor.visit_inline_const(c),
721+
PatExprKind::Path(qpath) => visitor.visit_qpath(qpath, expr.hir_id, expr.span),
722+
}
723+
}
724+
713725
pubfnwalk_anon_const<'v,V:Visitor<'v>>(visitor:&mutV,constant:&'vAnonConst) -> V::Result{
714726
try_visit!(visitor.visit_id(constant.hir_id));
715727
visitor.visit_nested_body(constant.body)

‎compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs‎

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2449,17 +2449,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24492449
Ty::new_error(tcx, err)
24502450
}
24512451
hir::PatKind::Range(start, end, include_end) => {
2452-
let expr_to_const = |expr:&'tcx hir::Expr<'tcx>| -> ty::Const<'tcx>{
2453-
let(expr, neg) = match expr.kind{
2454-
hir::ExprKind::Unary(hir::UnOp::Neg, negated) => {
2455-
(negated,Some((expr.hir_id, expr.span)))
2456-
}
2457-
_ => (expr,None),
2458-
};
2459-
let(c, c_ty) = match&expr.kind{
2460-
hir::ExprKind::Lit(lit) => {
2452+
let expr_to_const = |expr:&'tcx hir::PatExpr<'tcx>| -> ty::Const<'tcx>{
2453+
let(c, c_ty) = match expr.kind{
2454+
hir::PatExprKind::Lit{ lit, negated } => {
24612455
let lit_input =
2462-
LitToConstInput{lit:&lit.node, ty,neg:neg.is_some()};
2456+
LitToConstInput{lit:&lit.node, ty,neg:negated};
24632457
let ct = match tcx.lit_to_const(lit_input){
24642458
Ok(c) => c,
24652459
Err(LitToConstError::Reported(err)) => {
@@ -2470,23 +2464,30 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24702464
(ct, ty)
24712465
}
24722466

2473-
hir::ExprKind::Path(hir::QPath::Resolved(
2467+
hir::PatExprKind::Path(hir::QPath::Resolved(
24742468
_,
24752469
path @ &hir::Path{
24762470
res:Res::Def(DefKind::ConstParam, def_id),
24772471
..
24782472
},
24792473
)) => {
2480-
let _ =self.prohibit_generic_args(
2474+
matchself.prohibit_generic_args(
24812475
path.segments.iter(),
24822476
GenericsArgsErrExtend::Param(def_id),
2483-
);
2484-
let ty = tcx
2485-
.type_of(def_id)
2486-
.no_bound_vars()
2487-
.expect("const parameter types cannot be generic");
2488-
let ct = self.lower_const_param(def_id, expr.hir_id);
2489-
(ct, ty)
2477+
){
2478+
Ok(()) => {
2479+
let ty = tcx
2480+
.type_of(def_id)
2481+
.no_bound_vars()
2482+
.expect("const parameter types cannot be generic");
2483+
let ct = self.lower_const_param(def_id, expr.hir_id);
2484+
(ct, ty)
2485+
}
2486+
Err(guar) => (
2487+
ty::Const::new_error(tcx, guar),
2488+
Ty::new_error(tcx, guar),
2489+
),
2490+
}
24902491
}
24912492

24922493
_ => {
@@ -2497,9 +2498,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
24972498
}
24982499
};
24992500
self.record_ty(expr.hir_id, c_ty, expr.span);
2500-
ifletSome((id, span)) = neg {
2501-
self.record_ty(id, c_ty, span);
2502-
}
25032501
c
25042502
};
25052503

‎compiler/rustc_hir_pretty/src/lib.rs‎

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@ impl<'a> State<'a> {
199199
Node::OpaqueTy(o) => self.print_opaque_ty(o),
200200
Node::Pat(a) => self.print_pat(a),
201201
Node::PatField(a) => self.print_patfield(a),
202+
Node::PatExpr(a) => self.print_pat_expr(a),
202203
Node::Arm(a) => self.print_arm(a),
203204
Node::Infer(_) => self.word("_"),
204205
Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
@@ -1849,6 +1850,19 @@ impl<'a> State<'a> {
18491850
}
18501851
}
18511852

1853+
fnprint_pat_expr(&mutself,expr:&hir::PatExpr<'_>){
1854+
match&expr.kind{
1855+
hir::PatExprKind::Lit{ lit, negated } => {
1856+
if*negated {
1857+
self.word("-");
1858+
}
1859+
self.print_literal(lit);
1860+
}
1861+
hir::PatExprKind::ConstBlock(c) => self.print_inline_const(c),
1862+
hir::PatExprKind::Path(qpath) => self.print_qpath(qpath,true),
1863+
}
1864+
}
1865+
18521866
fnprint_pat(&mutself,pat:&hir::Pat<'_>){
18531867
self.maybe_print_comment(pat.span.lo());
18541868
self.ann.pre(self,AnnNode::Pat(pat));
@@ -1966,17 +1980,17 @@ impl<'a> State<'a> {
19661980
self.pclose();
19671981
}
19681982
}
1969-
PatKind::Lit(e) => self.print_expr(e),
1983+
PatKind::Lit(e) => self.print_pat_expr(e),
19701984
PatKind::Range(begin, end, end_kind) => {
19711985
ifletSome(expr) = begin {
1972-
self.print_expr(expr);
1986+
self.print_pat_expr(expr);
19731987
}
19741988
match end_kind {
19751989
RangeEnd::Included => self.word("..."),
19761990
RangeEnd::Excluded => self.word(".."),
19771991
}
19781992
ifletSome(expr) = end {
1979-
self.print_expr(expr);
1993+
self.print_pat_expr(expr);
19801994
}
19811995
}
19821996
PatKind::Slice(before, slice, after) => {

0 commit comments

Comments
 (0)