Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22465 from Veykril/push-loxpxnnrkruk
internal: Improve syntax mapping in for loop desugaring
Lukas Wirth 9 days ago
parent c3af07a · parent f01fff8 · commit b48cc10
-rw-r--r--crates/hir-def/src/expr_store/lower.rs39
-rw-r--r--crates/hir-ty/src/tests/macros.rs8
-rw-r--r--crates/hir-ty/src/tests/never_type.rs12
-rw-r--r--crates/hir-ty/src/tests/patterns.rs4
-rw-r--r--crates/hir-ty/src/tests/regression.rs8
-rw-r--r--crates/ide-diagnostics/src/handlers/unimplemented_trait.rs16
-rw-r--r--crates/test-utils/src/lib.rs2
7 files changed, 56 insertions, 33 deletions
diff --git a/crates/hir-def/src/expr_store/lower.rs b/crates/hir-def/src/expr_store/lower.rs
index ef88188572..21b5b19986 100644
--- a/crates/hir-def/src/expr_store/lower.rs
+++ b/crates/hir-def/src/expr_store/lower.rs
@@ -2159,16 +2159,21 @@ impl<'db> ExprCollector<'db> {
) else {
return self.missing_expr();
};
- let head = self.collect_expr_opt(e.iterable());
- let into_iter_fn_expr = self.alloc_expr(Expr::Path(into_iter_fn), syntax_ptr);
- let iterator = self.alloc_expr(
+ let iterable = e.iterable();
+ let syntax_ptr_iterable = iterable.as_ref().map_or(syntax_ptr, AstPtr::new);
+ let loop_body = e.loop_body().map(|it| it.into());
+ let head = self.collect_expr_opt(iterable);
+ let into_iter_fn_expr =
+ self.alloc_expr_desugared_with_ptr(Expr::Path(into_iter_fn), syntax_ptr_iterable);
+ let iterator = self.alloc_expr_desugared_with_ptr(
Expr::Call { callee: into_iter_fn_expr, args: Box::new([head]) },
- syntax_ptr,
+ syntax_ptr_iterable,
);
let none_arm = MatchArm {
pat: self.alloc_pat_desugared(Pat::Path(option_none)),
guard: None,
- expr: self.alloc_expr(Expr::Break { expr: None, label: None }, syntax_ptr),
+ expr: self
+ .alloc_expr_desugared_with_ptr(Expr::Break { expr: None, label: None }, syntax_ptr),
};
let some_pat = Pat::TupleStruct {
path: option_some,
@@ -2181,26 +2186,26 @@ impl<'db> ExprCollector<'db> {
let some_arm = MatchArm {
pat: self.alloc_pat_desugared(some_pat),
guard: None,
- expr: self.with_opt_labeled_rib(label, |this| {
- this.collect_expr_opt(e.loop_body().map(|it| it.into()))
- }),
+ expr: self.with_opt_labeled_rib(label, |this| this.collect_expr_opt(loop_body)),
};
let iter_name = self.generate_new_name();
- let iter_expr = self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr);
- let iter_expr_mut = self.alloc_expr(
+ let iter_expr = self
+ .alloc_expr_desugared_with_ptr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr);
+ let iter_expr_mut = self.alloc_expr_desugared_with_ptr(
Expr::Ref { expr: iter_expr, rawness: Rawness::Ref, mutability: Mutability::Mut },
syntax_ptr,
);
- let iter_next_fn_expr = self.alloc_expr(Expr::Path(iter_next_fn), syntax_ptr);
- let iter_next_expr = self.alloc_expr(
+ let iter_next_fn_expr =
+ self.alloc_expr_desugared_with_ptr(Expr::Path(iter_next_fn), syntax_ptr);
+ let iter_next_expr = self.alloc_expr_desugared_with_ptr(
Expr::Call { callee: iter_next_fn_expr, args: Box::new([iter_expr_mut]) },
syntax_ptr,
);
- let loop_inner = self.alloc_expr(
+ let loop_inner = self.alloc_expr_desugared_with_ptr(
Expr::Match { expr: iter_next_expr, arms: Box::new([none_arm, some_arm]) },
syntax_ptr,
);
- let loop_inner = self.alloc_expr(
+ let loop_inner = self.alloc_expr_desugared_with_ptr(
Expr::Block {
id: None,
statements: Box::default(),
@@ -2209,8 +2214,10 @@ impl<'db> ExprCollector<'db> {
},
syntax_ptr,
);
- let loop_outer = self
- .alloc_expr(Expr::Loop { body: loop_inner, label: label.map(|it| it.1) }, syntax_ptr);
+ let loop_outer = self.alloc_expr_desugared_with_ptr(
+ Expr::Loop { body: loop_inner, label: label.map(|it| it.1) },
+ syntax_ptr,
+ );
let iter_binding =
self.alloc_binding(iter_name, BindingAnnotation::Mutable, HygieneId::ROOT);
let iter_pat = self.alloc_pat_desugared(Pat::Bind { id: iter_binding, subpat: None });
diff --git a/crates/hir-ty/src/tests/macros.rs b/crates/hir-ty/src/tests/macros.rs
index 28a688d4a3..f81028c174 100644
--- a/crates/hir-ty/src/tests/macros.rs
+++ b/crates/hir-ty/src/tests/macros.rs
@@ -196,8 +196,6 @@ fn expr_macro_def_expanded_in_various_places() {
!0..6 '1isize': isize
39..442 '{ ...!(); }': {unknown}
73..94 'spam!(...am!())': {unknown}
- 100..119 'for _ ...!() {}': fn into_iter<isize>(isize) -> <isize as IntoIterator>::IntoIter
- 100..119 'for _ ...!() {}': <isize as IntoIterator>::IntoIter
100..119 'for _ ...!() {}': !
100..119 'for _ ...!() {}': {unknown}
100..119 'for _ ...!() {}': &'? mut {unknown}
@@ -208,6 +206,8 @@ fn expr_macro_def_expanded_in_various_places() {
100..119 'for _ ...!() {}': ()
100..119 'for _ ...!() {}': ()
104..105 '_': {unknown}
+ 109..116 'spam!()': fn into_iter<isize>(isize) -> <isize as IntoIterator>::IntoIter
+ 109..116 'spam!()': <isize as IntoIterator>::IntoIter
117..119 '{}': ()
124..134 '|| spam!()': impl Fn() -> isize
140..156 'while ...!() {}': !
@@ -290,8 +290,6 @@ fn expr_macro_rules_expanded_in_various_places() {
!0..6 '1isize': isize
53..456 '{ ...!(); }': {unknown}
87..108 'spam!(...am!())': {unknown}
- 114..133 'for _ ...!() {}': fn into_iter<isize>(isize) -> <isize as IntoIterator>::IntoIter
- 114..133 'for _ ...!() {}': <isize as IntoIterator>::IntoIter
114..133 'for _ ...!() {}': !
114..133 'for _ ...!() {}': {unknown}
114..133 'for _ ...!() {}': &'? mut {unknown}
@@ -302,6 +300,8 @@ fn expr_macro_rules_expanded_in_various_places() {
114..133 'for _ ...!() {}': ()
114..133 'for _ ...!() {}': ()
118..119 '_': {unknown}
+ 123..130 'spam!()': fn into_iter<isize>(isize) -> <isize as IntoIterator>::IntoIter
+ 123..130 'spam!()': <isize as IntoIterator>::IntoIter
131..133 '{}': ()
138..148 '|| spam!()': impl Fn() -> isize
154..170 'while ...!() {}': !
diff --git a/crates/hir-ty/src/tests/never_type.rs b/crates/hir-ty/src/tests/never_type.rs
index 91273cd177..19a6a6b486 100644
--- a/crates/hir-ty/src/tests/never_type.rs
+++ b/crates/hir-ty/src/tests/never_type.rs
@@ -361,8 +361,6 @@ fn diverging_expression_3_break() {
97..343 '{ ...; }; }': ()
140..141 'x': u32
149..175 '{ for ...; }; }': u32
- 151..172 'for a ...eak; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
- 151..172 'for a ...eak; }': <{unknown} as IntoIterator>::IntoIter
151..172 'for a ...eak; }': !
151..172 'for a ...eak; }': {unknown}
151..172 'for a ...eak; }': &'? mut {unknown}
@@ -374,12 +372,12 @@ fn diverging_expression_3_break() {
151..172 'for a ...eak; }': ()
155..156 'a': {unknown}
160..161 'b': {unknown}
+ 160..161 'b': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
+ 160..161 'b': <{unknown} as IntoIterator>::IntoIter
162..172 '{ break; }': ()
164..169 'break': !
226..227 'x': u32
235..253 '{ for ... {}; }': u32
- 237..250 'for a in b {}': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
- 237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter
237..250 'for a in b {}': !
237..250 'for a in b {}': {unknown}
237..250 'for a in b {}': &'? mut {unknown}
@@ -391,11 +389,11 @@ fn diverging_expression_3_break() {
237..250 'for a in b {}': ()
241..242 'a': {unknown}
246..247 'b': {unknown}
+ 246..247 'b': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
+ 246..247 'b': <{unknown} as IntoIterator>::IntoIter
248..250 '{}': ()
304..305 'x': u32
313..340 '{ for ...; }; }': u32
- 315..337 'for a ...urn; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
- 315..337 'for a ...urn; }': <{unknown} as IntoIterator>::IntoIter
315..337 'for a ...urn; }': !
315..337 'for a ...urn; }': {unknown}
315..337 'for a ...urn; }': &'? mut {unknown}
@@ -407,6 +405,8 @@ fn diverging_expression_3_break() {
315..337 'for a ...urn; }': ()
319..320 'a': {unknown}
324..325 'b': {unknown}
+ 324..325 'b': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
+ 324..325 'b': <{unknown} as IntoIterator>::IntoIter
326..337 '{ return; }': ()
328..334 'return': !
149..175: expected u32, got ()
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index e719f43e74..c48112ee81 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -47,8 +47,6 @@ fn infer_pattern() {
82..94 '(1, "hello")': (i32, &'? str)
83..84 '1': i32
86..93 '"hello"': &'static str
- 101..150 'for (e... }': fn into_iter<[(i32, i32); 1]>([(i32, i32); 1]) -> <[(i32, i32); 1] as IntoIterator>::IntoIter
- 101..150 'for (e... }': IntoIter<(i32, i32), 1>
101..150 'for (e... }': !
101..150 'for (e... }': IntoIter<(i32, i32), 1>
101..150 'for (e... }': &'? mut IntoIter<(i32, i32), 1>
@@ -62,6 +60,8 @@ fn infer_pattern() {
106..107 'e': i32
109..110 'f': i32
115..123 '[(0, 1)]': [(i32, i32); 1]
+ 115..123 '[(0, 1)]': fn into_iter<[(i32, i32); 1]>([(i32, i32); 1]) -> <[(i32, i32); 1] as IntoIterator>::IntoIter
+ 115..123 '[(0, 1)]': IntoIter<(i32, i32), 1>
116..122 '(0, 1)': (i32, i32)
117..118 '0': i32
120..121 '1': i32
diff --git a/crates/hir-ty/src/tests/regression.rs b/crates/hir-ty/src/tests/regression.rs
index 5a90e700ac..c1c714f8d4 100644
--- a/crates/hir-ty/src/tests/regression.rs
+++ b/crates/hir-ty/src/tests/regression.rs
@@ -270,8 +270,6 @@ fn infer_std_crash_5() {
"#,
expect![[r#"
26..322 '{ ... } }': ()
- 32..320 'for co... }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
- 32..320 'for co... }': <{unknown} as IntoIterator>::IntoIter
32..320 'for co... }': !
32..320 'for co... }': {unknown}
32..320 'for co... }': &'? mut {unknown}
@@ -283,6 +281,8 @@ fn infer_std_crash_5() {
32..320 'for co... }': ()
36..43 'content': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
47..60 'doesnt_matter': {unknown}
+ 47..60 'doesnt_matter': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
+ 47..60 'doesnt_matter': <{unknown} as IntoIterator>::IntoIter
61..320 '{ ... }': ()
75..79 'name': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
82..166 'if doe... }': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown}
@@ -1261,8 +1261,6 @@ fn test() {
"#,
expect![[r#"
10..68 '{ ... } }': ()
- 16..66 'for _ ... }': fn into_iter<()>(()) -> <() as IntoIterator>::IntoIter
- 16..66 'for _ ... }': <() as IntoIterator>::IntoIter
16..66 'for _ ... }': !
16..66 'for _ ... }': {unknown}
16..66 'for _ ... }': &'? mut {unknown}
@@ -1274,6 +1272,8 @@ fn test() {
16..66 'for _ ... }': ()
20..21 '_': {unknown}
25..39 '{ let x = 0; }': ()
+ 25..39 '{ let x = 0; }': fn into_iter<()>(()) -> <() as IntoIterator>::IntoIter
+ 25..39 '{ let x = 0; }': <() as IntoIterator>::IntoIter
31..32 'x': i32
35..36 '0': i32
40..66 '{ ... }': ()
diff --git a/crates/ide-diagnostics/src/handlers/unimplemented_trait.rs b/crates/ide-diagnostics/src/handlers/unimplemented_trait.rs
index d94ceef642..4a253bc831 100644
--- a/crates/ide-diagnostics/src/handlers/unimplemented_trait.rs
+++ b/crates/ide-diagnostics/src/handlers/unimplemented_trait.rs
@@ -69,4 +69,20 @@ fn foo() {
"#,
);
}
+
+ #[test]
+ fn for_iterable() {
+ check_diagnostics(
+ r#"
+//- minicore: iterator
+fn foo() {
+ for _ in () {}
+ // ^^ error: the trait bound `(): Iterator` is not satisfied
+ // ^^ error: the trait bound `(): Iterator` is not satisfied
+ // | required by the bound `(): IntoIterator`
+}
+
+ "#,
+ );
+ }
}
diff --git a/crates/test-utils/src/lib.rs b/crates/test-utils/src/lib.rs
index 62867fd5b5..4eab7f4b18 100644
--- a/crates/test-utils/src/lib.rs
+++ b/crates/test-utils/src/lib.rs
@@ -260,7 +260,7 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
let &(_, idx) = prev_line_annotations
.iter()
.find(|&&(off, _idx)| off == offset)
- .unwrap();
+ .expect("annotation continuation not found");
res[idx].1.push('\n');
res[idx].1.push_str(&content);
res[idx].1.push('\n');