Skip to content

Commit 50882fb

Browse files
committed
Auto merge of #18045 - Veykril:fix-loop-lower, r=Veykril
fix: Fix lowering of for loops dropping the loop block
2 parents a3f302e + fbca403 commit 50882fb

File tree

6 files changed

+65
-9
lines changed

6 files changed

+65
-9
lines changed

crates/hir-def/src/body/lower.rs

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -737,7 +737,7 @@ impl ExprCollector<'_> {
737737
/// `try { <stmts>; }` into `'<new_label>: { <stmts>; ::std::ops::Try::from_output(()) }`
738738
/// and save the `<new_label>` to use it as a break target for desugaring of the `?` operator.
739739
fn desugar_try_block(&mut self, e: BlockExpr) -> ExprId {
740-
let Some(try_from_output) = LangItem::TryTraitFromOutput.path(self.db, self.krate) else {
740+
let Some(try_from_output) = self.lang_path(LangItem::TryTraitFromOutput) else {
741741
return self.collect_block(e);
742742
};
743743
let label = self
@@ -840,10 +840,10 @@ impl ExprCollector<'_> {
840840
fn collect_for_loop(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::ForExpr) -> ExprId {
841841
let Some((into_iter_fn, iter_next_fn, option_some, option_none)) = (|| {
842842
Some((
843-
LangItem::IntoIterIntoIter.path(self.db, self.krate)?,
844-
LangItem::IteratorNext.path(self.db, self.krate)?,
845-
LangItem::OptionSome.path(self.db, self.krate)?,
846-
LangItem::OptionNone.path(self.db, self.krate)?,
843+
self.lang_path(LangItem::IntoIterIntoIter)?,
844+
self.lang_path(LangItem::IteratorNext)?,
845+
self.lang_path(LangItem::OptionSome)?,
846+
self.lang_path(LangItem::OptionNone)?,
847847
))
848848
})() else {
849849
// Some of the needed lang items are missing, so we can't desugar
@@ -896,6 +896,15 @@ impl ExprCollector<'_> {
896896
Expr::Match { expr: iter_next_expr, arms: Box::new([none_arm, some_arm]) },
897897
syntax_ptr,
898898
);
899+
let loop_inner = self.alloc_expr(
900+
Expr::Block {
901+
id: None,
902+
statements: Box::default(),
903+
tail: Some(loop_inner),
904+
label: None,
905+
},
906+
syntax_ptr,
907+
);
899908
let loop_outer = self.alloc_expr(Expr::Loop { body: loop_inner, label }, syntax_ptr);
900909
let iter_binding = self.alloc_binding(iter_name, BindingAnnotation::Mutable);
901910
let iter_pat = self.alloc_pat_desugared(Pat::Bind { id: iter_binding, subpat: None });
@@ -923,10 +932,10 @@ impl ExprCollector<'_> {
923932
fn collect_try_operator(&mut self, syntax_ptr: AstPtr<ast::Expr>, e: ast::TryExpr) -> ExprId {
924933
let Some((try_branch, cf_continue, cf_break, try_from_residual)) = (|| {
925934
Some((
926-
LangItem::TryTraitBranch.path(self.db, self.krate)?,
927-
LangItem::ControlFlowContinue.path(self.db, self.krate)?,
928-
LangItem::ControlFlowBreak.path(self.db, self.krate)?,
929-
LangItem::TryTraitFromResidual.path(self.db, self.krate)?,
935+
self.lang_path(LangItem::TryTraitBranch)?,
936+
self.lang_path(LangItem::ControlFlowContinue)?,
937+
self.lang_path(LangItem::ControlFlowBreak)?,
938+
self.lang_path(LangItem::TryTraitFromResidual)?,
930939
))
931940
})() else {
932941
// Some of the needed lang items are missing, so we can't desugar
@@ -2053,6 +2062,10 @@ impl ExprCollector<'_> {
20532062
})
20542063
}
20552064
// endregion: format
2065+
2066+
fn lang_path(&self, lang: LangItem) -> Option<Path> {
2067+
lang.path(self.db, self.krate)
2068+
}
20562069
}
20572070

20582071
fn pat_literal_to_hir(lit: &ast::LiteralPat) -> Option<(Literal, ast::Literal)> {

crates/hir-def/src/body/tests.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,41 @@ mod m {
142142
);
143143
}
144144

145+
#[test]
146+
fn desugar_for_loop() {
147+
let (db, body, def) = lower(
148+
r#"
149+
//- minicore: iterator
150+
fn main() {
151+
for ident in 0..10 {
152+
foo();
153+
bar()
154+
}
155+
}
156+
"#,
157+
);
158+
159+
expect![[r#"
160+
fn main() -> () {
161+
match builtin#lang(into_iter)(
162+
(0) ..(10) ,
163+
) {
164+
mut <ra@gennew>11 => loop {
165+
match builtin#lang(next)(
166+
&mut <ra@gennew>11,
167+
) {
168+
builtin#lang(None) => break,
169+
builtin#lang(Some)(ident) => {
170+
foo();
171+
bar()
172+
},
173+
}
174+
},
175+
}
176+
}"#]]
177+
.assert_eq(&body.pretty_print(&db, def, Edition::CURRENT))
178+
}
179+
145180
#[test]
146181
fn desugar_builtin_format_args() {
147182
let (db, body, def) = lower(

crates/hir-ty/src/tests/macros.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ fn expr_macro_def_expanded_in_various_places() {
206206
100..119 'for _ ...!() {}': ()
207207
100..119 'for _ ...!() {}': ()
208208
100..119 'for _ ...!() {}': ()
209+
100..119 'for _ ...!() {}': ()
209210
104..105 '_': IntoIterator::Item<isize>
210211
117..119 '{}': ()
211212
124..134 '|| spam!()': impl Fn() -> isize
@@ -299,6 +300,7 @@ fn expr_macro_rules_expanded_in_various_places() {
299300
114..133 'for _ ...!() {}': ()
300301
114..133 'for _ ...!() {}': ()
301302
114..133 'for _ ...!() {}': ()
303+
114..133 'for _ ...!() {}': ()
302304
118..119 '_': IntoIterator::Item<isize>
303305
131..133 '{}': ()
304306
138..148 '|| spam!()': impl Fn() -> isize

crates/hir-ty/src/tests/never_type.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,6 +371,7 @@ fn diverging_expression_3_break() {
371371
151..172 'for a ...eak; }': ()
372372
151..172 'for a ...eak; }': ()
373373
151..172 'for a ...eak; }': ()
374+
151..172 'for a ...eak; }': ()
374375
155..156 'a': {unknown}
375376
160..161 'b': {unknown}
376377
162..172 '{ break; }': ()
@@ -387,6 +388,7 @@ fn diverging_expression_3_break() {
387388
237..250 'for a in b {}': ()
388389
237..250 'for a in b {}': ()
389390
237..250 'for a in b {}': ()
391+
237..250 'for a in b {}': ()
390392
241..242 'a': {unknown}
391393
246..247 'b': {unknown}
392394
248..250 '{}': ()
@@ -402,6 +404,7 @@ fn diverging_expression_3_break() {
402404
315..337 'for a ...urn; }': ()
403405
315..337 'for a ...urn; }': ()
404406
315..337 'for a ...urn; }': ()
407+
315..337 'for a ...urn; }': ()
405408
319..320 'a': {unknown}
406409
324..325 'b': {unknown}
407410
326..337 '{ return; }': ()

crates/hir-ty/src/tests/patterns.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ fn infer_pattern() {
5757
101..151 'for (e... }': ()
5858
101..151 'for (e... }': ()
5959
101..151 'for (e... }': ()
60+
101..151 'for (e... }': ()
6061
105..111 '(e, f)': ({unknown}, {unknown})
6162
106..107 'e': {unknown}
6263
109..110 'f': {unknown}

crates/hir-ty/src/tests/regression.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ fn infer_std_crash_5() {
275275
32..320 'for co... }': ()
276276
32..320 'for co... }': ()
277277
32..320 'for co... }': ()
278+
32..320 'for co... }': ()
278279
36..43 'content': {unknown}
279280
47..60 'doesnt_matter': {unknown}
280281
61..320 '{ ... }': ()
@@ -1244,6 +1245,7 @@ fn test() {
12441245
16..66 'for _ ... }': ()
12451246
16..66 'for _ ... }': ()
12461247
16..66 'for _ ... }': ()
1248+
16..66 'for _ ... }': ()
12471249
20..21 '_': IntoIterator::Item<()>
12481250
25..39 '{ let x = 0; }': ()
12491251
31..32 'x': i32

0 commit comments

Comments
 (0)