Skip to content

Commit 89d2600

Browse files
committed
Add let-else to AST
1 parent 6f388bb commit 89d2600

File tree

10 files changed

+92
-26
lines changed

10 files changed

+92
-26
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,13 +1005,42 @@ pub struct Local {
10051005
pub id: NodeId,
10061006
pub pat: P<Pat>,
10071007
pub ty: Option<P<Ty>>,
1008-
/// Initializer expression to set the value, if any.
1009-
pub init: Option<P<Expr>>,
1008+
pub kind: LocalKind,
10101009
pub span: Span,
10111010
pub attrs: AttrVec,
10121011
pub tokens: Option<LazyTokenStream>,
10131012
}
10141013

1014+
#[derive(Clone, Encodable, Decodable, Debug)]
1015+
pub enum LocalKind {
1016+
/// Local declaration.
1017+
/// Example: `let x;`
1018+
Decl,
1019+
/// Local declaration with an initializer.
1020+
/// Example: `let x = y;`
1021+
Init(P<Expr>),
1022+
/// Local declaration with an initializer and an `else` clause.
1023+
/// Example: `let Some(x) = y else { return };`
1024+
InitElse(P<Expr>, P<Block>),
1025+
}
1026+
1027+
impl LocalKind {
1028+
pub fn init(&self) -> Option<&Expr> {
1029+
match self {
1030+
Self::Decl => None,
1031+
Self::Init(i) | Self::InitElse(i, _) => Some(i),
1032+
}
1033+
}
1034+
1035+
pub fn init_else_opt(&self) -> Option<(&Expr, Option<&Block>)> {
1036+
match self {
1037+
Self::Decl => None,
1038+
Self::Init(init) => Some((init, None)),
1039+
Self::InitElse(init, els) => Some((init, Some(els))),
1040+
}
1041+
}
1042+
}
1043+
10151044
/// An arm of a 'match'.
10161045
///
10171046
/// E.g., `0..=10 => { println!("match!") }` as in

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -571,11 +571,20 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
571571
}
572572

573573
pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
574-
let Local { id, pat, ty, init, span, attrs, tokens } = local.deref_mut();
574+
let Local { id, pat, ty, kind, span, attrs, tokens } = local.deref_mut();
575575
vis.visit_id(id);
576576
vis.visit_pat(pat);
577577
visit_opt(ty, |ty| vis.visit_ty(ty));
578-
visit_opt(init, |init| vis.visit_expr(init));
578+
match kind {
579+
LocalKind::Decl => {}
580+
LocalKind::Init(init) => {
581+
vis.visit_expr(init);
582+
}
583+
LocalKind::InitElse(init, els) => {
584+
vis.visit_expr(init);
585+
vis.visit_block(els);
586+
}
587+
}
579588
vis.visit_span(span);
580589
visit_thin_attrs(attrs, vis);
581590
visit_lazy_tts(tokens, vis);

compiler/rustc_ast/src/visit.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,10 @@ pub fn walk_local<'a, V: Visitor<'a>>(visitor: &mut V, local: &'a Local) {
242242
}
243243
visitor.visit_pat(&local.pat);
244244
walk_list!(visitor, visit_ty, &local.ty);
245-
walk_list!(visitor, visit_expr, &local.init);
245+
if let Some((init, els)) = local.kind.init_else_opt() {
246+
visitor.visit_expr(init);
247+
walk_list!(visitor, visit_block, els);
248+
}
246249
}
247250

248251
pub fn walk_label<'a, V: Visitor<'a>>(visitor: &mut V, label: &'a Label) {

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1798,7 +1798,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
17981798
.ty
17991799
.as_ref()
18001800
.map(|t| self.lower_ty(t, ImplTraitContext::Disallowed(ImplTraitPosition::Binding)));
1801-
let init = l.init.as_ref().map(|e| self.lower_expr(e));
1801+
let init = l.kind.init().map(|init| self.lower_expr(init));
18021802
let hir_id = self.lower_node_id(l.id);
18031803
self.lower_attrs(hir_id, &l.attrs);
18041804
hir::Local {

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,13 +1518,19 @@ impl<'a> State<'a> {
15181518
self.ibox(INDENT_UNIT);
15191519
self.print_local_decl(loc);
15201520
self.end();
1521-
if let Some(ref init) = loc.init {
1521+
if let Some((init, els)) = loc.kind.init_else_opt() {
15221522
self.nbsp();
15231523
self.word_space("=");
15241524
self.print_expr(init);
1525+
if let Some(els) = els {
1526+
self.cbox(INDENT_UNIT);
1527+
self.ibox(INDENT_UNIT);
1528+
self.s.word(" else ");
1529+
self.print_block(els);
1530+
}
15251531
}
15261532
self.s.word(";");
1527-
self.end();
1533+
self.end(); // `let` ibox
15281534
}
15291535
ast::StmtKind::Item(ref item) => self.print_item(item),
15301536
ast::StmtKind::Expr(ref expr) => {

compiler/rustc_builtin_macros/src/deriving/debug.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::deriving::generic::*;
33
use crate::deriving::path_std;
44

55
use rustc_ast::ptr::P;
6-
use rustc_ast::{self as ast, Expr, MetaItem};
6+
use rustc_ast::{self as ast, Expr, LocalKind, MetaItem};
77
use rustc_expand::base::{Annotatable, ExtCtxt};
88
use rustc_span::symbol::{sym, Ident};
99
use rustc_span::{Span, DUMMY_SP};
@@ -135,8 +135,8 @@ fn stmt_let_underscore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<ast::Expr>) -> as
135135
let local = P(ast::Local {
136136
pat: cx.pat_wild(sp),
137137
ty: None,
138-
init: Some(expr),
139138
id: ast::DUMMY_NODE_ID,
139+
kind: LocalKind::Init(expr),
140140
span: sp,
141141
attrs: ast::AttrVec::new(),
142142
tokens: None,

compiler/rustc_expand/src/build.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::base::ExtCtxt;
22

33
use rustc_ast::attr;
44
use rustc_ast::ptr::P;
5-
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, PatKind, UnOp};
5+
use rustc_ast::{self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, PatKind, UnOp};
66
use rustc_span::source_map::Spanned;
77
use rustc_span::symbol::{kw, sym, Ident, Symbol};
88

@@ -153,8 +153,8 @@ impl<'a> ExtCtxt<'a> {
153153
let local = P(ast::Local {
154154
pat,
155155
ty: None,
156-
init: Some(ex),
157156
id: ast::DUMMY_NODE_ID,
157+
kind: LocalKind::Init(ex),
158158
span: sp,
159159
attrs: AttrVec::new(),
160160
tokens: None,
@@ -167,8 +167,8 @@ impl<'a> ExtCtxt<'a> {
167167
let local = P(ast::Local {
168168
pat: self.pat_wild(span),
169169
ty: Some(ty),
170-
init: None,
171170
id: ast::DUMMY_NODE_ID,
171+
kind: LocalKind::Decl,
172172
span,
173173
attrs: AttrVec::new(),
174174
tokens: None,

compiler/rustc_lint/src/unused.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,7 @@ trait UnusedDelimLint {
618618
fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) {
619619
match s.kind {
620620
StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => {
621-
if let Some(ref value) = local.init {
621+
if let Some(value) = local.kind.init() {
622622
self.check_unused_delims_expr(
623623
cx,
624624
&value,

compiler/rustc_parse/src/parser/stmt.rs

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ use rustc_ast as ast;
1111
use rustc_ast::ptr::P;
1212
use rustc_ast::token::{self, TokenKind};
1313
use rustc_ast::util::classify;
14-
use rustc_ast::AstLike;
15-
use rustc_ast::{AttrStyle, AttrVec, Attribute, MacCall, MacCallStmt, MacStmtStyle};
14+
use rustc_ast::{
15+
AstLike, AttrStyle, AttrVec, Attribute, LocalKind, MacCall, MacCallStmt, MacStmtStyle,
16+
};
1617
use rustc_ast::{Block, BlockCheckMode, Expr, ExprKind, Local, Stmt};
1718
use rustc_ast::{StmtKind, DUMMY_NODE_ID};
1819
use rustc_errors::{Applicability, PResult};
@@ -292,8 +293,19 @@ impl<'a> Parser<'a> {
292293
return Err(err);
293294
}
294295
};
296+
let kind = match init {
297+
None => LocalKind::Decl,
298+
Some(init) => {
299+
if self.eat_keyword(kw::Else) {
300+
let els = self.parse_block()?;
301+
LocalKind::InitElse(init, els)
302+
} else {
303+
LocalKind::Init(init)
304+
}
305+
}
306+
};
295307
let hi = if self.token == token::Semi { self.token.span } else { self.prev_token.span };
296-
Ok(P(ast::Local { ty, pat, init, id: DUMMY_NODE_ID, span: lo.to(hi), attrs, tokens: None }))
308+
Ok(P(ast::Local { ty, pat, kind, id: DUMMY_NODE_ID, span: lo.to(hi), attrs, tokens: None }))
297309
}
298310

299311
/// Parses the RHS of a local variable declaration (e.g., `= 14;`).
@@ -495,13 +507,13 @@ impl<'a> Parser<'a> {
495507
StmtKind::Expr(_) | StmtKind::MacCall(_) => {}
496508
StmtKind::Local(ref mut local) if let Err(e) = self.expect_semi() => {
497509
// We might be at the `,` in `let x = foo<bar, baz>;`. Try to recover.
498-
match &mut local.init {
499-
Some(ref mut expr) => {
500-
self.check_mistyped_turbofish_with_multiple_type_params(e, expr)?;
501-
// We found `foo<bar, baz>`, have we fully recovered?
502-
self.expect_semi()?;
503-
}
504-
None => return Err(e),
510+
match &mut local.kind {
511+
LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => {
512+
self.check_mistyped_turbofish_with_multiple_type_params(e, expr)?;
513+
// We found `foo<bar, baz>`, have we fully recovered?
514+
self.expect_semi()?;
515+
}
516+
LocalKind::Decl => return Err(e),
505517
}
506518
eat_semi = false;
507519
}

compiler/rustc_resolve/src/late.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
454454
_ => Some((
455455
local.pat.span,
456456
local.ty.as_ref().map(|ty| ty.span),
457-
local.init.as_ref().map(|init| init.span),
457+
local.kind.init().map(|init| init.span),
458458
)),
459459
};
460460
let original = replace(&mut self.diagnostic_metadata.current_let_binding, local_spans);
@@ -1426,7 +1426,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
14261426
walk_list!(self, visit_ty, &local.ty);
14271427

14281428
// Resolve the initializer.
1429-
walk_list!(self, visit_expr, &local.init);
1429+
if let Some((init, els)) = local.kind.init_else_opt() {
1430+
self.visit_expr(init);
1431+
1432+
// Resolve the `else` block
1433+
if let Some(els) = els {
1434+
self.visit_block(els);
1435+
}
1436+
}
14301437

14311438
// Resolve the pattern.
14321439
self.resolve_pattern_top(&local.pat, PatternSource::Let);

0 commit comments

Comments
 (0)