Skip to content

Commit ea8dfd3

Browse files
committed
Add LetSource to HIR
1 parent 9ccf661 commit ea8dfd3

File tree

10 files changed

+92
-88
lines changed

10 files changed

+92
-88
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+35-23
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
1+
use super::{
2+
ConditionScope, ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs,
3+
};
24

35
use rustc_ast::attr;
46
use rustc_ast::ptr::P as AstP;
@@ -15,6 +17,8 @@ use rustc_span::source_map::{respan, DesugaringKind, Span, Spanned};
1517
use rustc_span::symbol::{sym, Ident, Symbol};
1618
use rustc_span::{hygiene::ForLoopLoc, DUMMY_SP};
1719

20+
use std::mem;
21+
1822
impl<'hir> LoweringContext<'_, 'hir> {
1923
fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
2024
self.arena.alloc_from_iter(exprs.iter().map(|x| self.lower_expr_mut(x)))
@@ -87,7 +91,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
8791
hir::ExprKind::AddrOf(k, m, ohs)
8892
}
8993
ExprKind::Let(ref pat, ref scrutinee, span) => {
90-
hir::ExprKind::Let(self.lower_pat(pat), self.lower_expr(scrutinee), span)
94+
let source = match self.condition_scope {
95+
Some(ConditionScope::Guard) => hir::LetSource::Guard,
96+
Some(ConditionScope::If) => hir::LetSource::If,
97+
Some(ConditionScope::While) => hir::LetSource::While,
98+
_ => hir::LetSource::Local,
99+
};
100+
hir::ExprKind::Let(
101+
self.lower_pat(pat),
102+
self.lower_expr(scrutinee),
103+
span,
104+
source,
105+
)
91106
}
92107
ExprKind::If(ref cond, ref then, ref else_opt) => {
93108
self.lower_expr_if(cond, then, else_opt.as_deref())
@@ -354,14 +369,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
354369
then: &Block,
355370
else_opt: Option<&Expr>,
356371
) -> hir::ExprKind<'hir> {
357-
let lowered_cond = self.lower_expr(cond);
372+
let lowered_cond = self.with_condition_scope(ConditionScope::If, |t| t.lower_expr(cond));
358373
let new_cond = self.manage_let_cond(lowered_cond);
359-
let then_expr = self.lower_block_expr(then);
360-
if let Some(rslt) = else_opt {
361-
hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), Some(self.lower_expr(rslt)))
362-
} else {
363-
hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), None)
364-
}
374+
let then_expr = self.arena.alloc(self.lower_block_expr(then));
375+
let else_opt = else_opt.map(|e| self.lower_expr(e));
376+
hir::ExprKind::If(new_cond, then_expr, else_opt)
365377
}
366378

367379
// If `cond` kind is `let`, returns `let`. Otherwise, wraps and returns `cond`
@@ -400,7 +412,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
400412
body: &Block,
401413
opt_label: Option<Label>,
402414
) -> hir::ExprKind<'hir> {
403-
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
415+
let lowered_cond = self.with_condition_scope(ConditionScope::While, |t| t.lower_expr(cond));
404416
let new_cond = self.manage_let_cond(lowered_cond);
405417
let then = self.lower_block_expr(body);
406418
let expr_break = self.expr_break(span, ThinVec::new());
@@ -473,7 +485,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
473485
if let ExprKind::Let(ref pat, ref scrutinee, _) = cond.kind {
474486
hir::Guard::IfLet(self.lower_pat(pat), self.lower_expr(scrutinee))
475487
} else {
476-
hir::Guard::If(self.lower_expr(cond))
488+
let cond = self.with_condition_scope(ConditionScope::Guard, |t| t.lower_expr(cond));
489+
hir::Guard::If(cond)
477490
}
478491
});
479492
let hir_id = self.next_id();
@@ -732,7 +745,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
732745
(body_id, generator_option)
733746
});
734747

735-
// Lower outside new scope to preserve `is_in_loop_condition`.
748+
// Lower outside new scope to preserve `condition_scope`.
736749
let fn_decl = self.lower_fn_decl(decl, None, false, None);
737750

738751
hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option)
@@ -1132,7 +1145,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11321145
}
11331146

11341147
fn lower_jump_destination(&mut self, id: NodeId, opt_label: Option<Label>) -> hir::Destination {
1135-
if self.is_in_loop_condition && opt_label.is_none() {
1148+
if opt_label.is_none() && self.condition_scope == Some(ConditionScope::While) {
11361149
hir::Destination {
11371150
label: None,
11381151
target_id: Err(hir::LoopIdError::UnlabeledCfInWhileCondition),
@@ -1160,8 +1173,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
11601173

11611174
fn with_loop_scope<T>(&mut self, loop_id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
11621175
// We're no longer in the base loop's condition; we're in another loop.
1163-
let was_in_loop_condition = self.is_in_loop_condition;
1164-
self.is_in_loop_condition = false;
1176+
let condition_scope = mem::take(&mut self.condition_scope);
11651177

11661178
let len = self.loop_scopes.len();
11671179
self.loop_scopes.push(loop_id);
@@ -1175,19 +1187,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
11751187

11761188
self.loop_scopes.pop().unwrap();
11771189

1178-
self.is_in_loop_condition = was_in_loop_condition;
1190+
self.condition_scope = condition_scope;
11791191

11801192
result
11811193
}
11821194

1183-
fn with_loop_condition_scope<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
1184-
let was_in_loop_condition = self.is_in_loop_condition;
1185-
self.is_in_loop_condition = true;
1186-
1195+
fn with_condition_scope<T>(
1196+
&mut self,
1197+
condition_scope: ConditionScope,
1198+
f: impl FnOnce(&mut Self) -> T,
1199+
) -> T {
1200+
let condition_scope = mem::replace(&mut self.condition_scope, Some(condition_scope));
11871201
let result = f(self);
1188-
1189-
self.is_in_loop_condition = was_in_loop_condition;
1190-
1202+
self.condition_scope = condition_scope;
11911203
result
11921204
}
11931205

compiler/rustc_ast_lowering/src/lib.rs

+11-8
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,8 @@ struct LoweringContext<'a, 'hir: 'a> {
122122
current_item: Option<Span>,
123123

124124
catch_scopes: Vec<NodeId>,
125+
condition_scope: Option<ConditionScope>,
125126
loop_scopes: Vec<NodeId>,
126-
is_in_loop_condition: bool,
127127
is_in_trait_impl: bool,
128128
is_in_dyn_type: bool,
129129

@@ -332,8 +332,8 @@ pub fn lower_crate<'a, 'hir>(
332332
attrs: BTreeMap::default(),
333333
non_exported_macro_attrs: Vec::new(),
334334
catch_scopes: Vec::new(),
335+
condition_scope: None,
335336
loop_scopes: Vec::new(),
336-
is_in_loop_condition: false,
337337
is_in_trait_impl: false,
338338
is_in_dyn_type: false,
339339
anonymous_lifetime_mode: AnonymousLifetimeMode::PassThrough,
@@ -419,6 +419,13 @@ enum AnonymousLifetimeMode {
419419
PassThrough,
420420
}
421421

422+
#[derive(Copy, Clone, Debug, PartialEq)]
423+
enum ConditionScope {
424+
Guard,
425+
If,
426+
While,
427+
}
428+
422429
impl<'a, 'hir> LoweringContext<'a, 'hir> {
423430
fn lower_crate(mut self, c: &Crate) -> &'hir hir::Crate<'hir> {
424431
/// Full-crate AST visitor that inserts into a fresh
@@ -957,17 +964,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
957964
}
958965

959966
fn with_new_scopes<T>(&mut self, f: impl FnOnce(&mut Self) -> T) -> T {
960-
let was_in_loop_condition = self.is_in_loop_condition;
961-
self.is_in_loop_condition = false;
962-
963967
let catch_scopes = mem::take(&mut self.catch_scopes);
968+
let condition_scope = mem::take(&mut self.condition_scope);
964969
let loop_scopes = mem::take(&mut self.loop_scopes);
965970
let ret = f(self);
966971
self.catch_scopes = catch_scopes;
972+
self.condition_scope = condition_scope;
967973
self.loop_scopes = loop_scopes;
968-
969-
self.is_in_loop_condition = was_in_loop_condition;
970-
971974
ret
972975
}
973976

compiler/rustc_hir/src/hir.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1732,7 +1732,7 @@ pub enum ExprKind<'hir> {
17321732
///
17331733
/// These are not `Local` and only occur as expressions.
17341734
/// The `let Some(x) = foo()` in `if let Some(x) = foo()` is an example of `Let(..)`.
1735-
Let(&'hir Pat<'hir>, &'hir Expr<'hir>, Span),
1735+
Let(&'hir Pat<'hir>, &'hir Expr<'hir>, Span, LetSource),
17361736
/// An `if` block, with an optional else block.
17371737
///
17381738
/// I.e., `if <expr> { <expr> } else { <expr> }`.
@@ -1886,6 +1886,15 @@ pub enum LocalSource {
18861886
AssignDesugar(Span),
18871887
}
18881888

1889+
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
1890+
#[derive(HashStable_Generic)]
1891+
pub enum LetSource {
1892+
Guard,
1893+
If,
1894+
Local,
1895+
While,
1896+
}
1897+
18891898
/// Hints at the original code for a `match _ { .. }`.
18901899
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Hash, Debug)]
18911900
#[derive(HashStable_Generic)]

compiler/rustc_hir/src/intravisit.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
11631163
ExprKind::DropTemps(ref subexpression) => {
11641164
visitor.visit_expr(subexpression);
11651165
}
1166-
ExprKind::Let(ref pat, ref expr, _) => {
1166+
ExprKind::Let(ref pat, ref expr, ..) => {
11671167
visitor.visit_expr(expr);
11681168
visitor.visit_pat(pat);
11691169
}

compiler/rustc_hir_pretty/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1526,7 +1526,7 @@ impl<'a> State<'a> {
15261526
// Print `}`:
15271527
self.bclose_maybe_open(expr.span, true);
15281528
}
1529-
hir::ExprKind::Let(ref pat, ref scrutinee, _) => {
1529+
hir::ExprKind::Let(ref pat, ref scrutinee, ..) => {
15301530
self.print_let(pat, scrutinee);
15311531
}
15321532
hir::ExprKind::If(ref test, ref blk, ref elseopt) => {

compiler/rustc_mir_build/src/thir/cx/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,7 @@ impl<'tcx> Cx<'tcx> {
590590
},
591591
Err(err) => bug!("invalid loop id for continue: {}", err),
592592
},
593-
hir::ExprKind::Let(ref pat, ref expr, _) => {
593+
hir::ExprKind::Let(ref pat, ref expr, ..) => {
594594
ExprKind::Let { expr: self.mirror_expr(expr), pat: self.pattern_from_hir(pat) }
595595
}
596596
hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {

0 commit comments

Comments
 (0)