Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/tests/closure_captures.rs')
-rw-r--r--crates/hir-ty/src/tests/closure_captures.rs247
1 files changed, 138 insertions, 109 deletions
diff --git a/crates/hir-ty/src/tests/closure_captures.rs b/crates/hir-ty/src/tests/closure_captures.rs
index 9e68756821..5324d8c605 100644
--- a/crates/hir-ty/src/tests/closure_captures.rs
+++ b/crates/hir-ty/src/tests/closure_captures.rs
@@ -1,24 +1,68 @@
use expect_test::{Expect, expect};
use hir_def::{
- DefWithBodyId,
+ AdtId, DefWithBodyId, LocalFieldId, VariantId,
expr_store::{Body, ExpressionStore},
+ hir::{BindingId, ExprOrPatId},
};
use hir_expand::{HirFileId, files::InFileWrapper};
use itertools::Itertools;
-use span::TextRange;
+use rustc_type_ir::inherent::{AdtDef as _, IntoKind};
+use span::{Edition, TextRange};
+use stdx::{format_to, never};
use syntax::{AstNode, AstPtr};
use test_fixture::WithFixture;
use crate::{
InferenceResult,
- db::HirDatabase,
+ closure_analysis::Place,
display::{DisplayTarget, HirDisplay},
- mir::MirSpan,
+ next_solver::TyKind,
test_db::TestDB,
};
use super::{setup_tracing, visit_module};
+fn display_place(db: &TestDB, store: &ExpressionStore, place: &Place, local: BindingId) -> String {
+ let mut result = store[local].name.display(db, Edition::LATEST).to_string();
+ let mut last_was_deref = false;
+ for (i, proj) in place.projections.iter().enumerate() {
+ match proj.kind {
+ hir_ty::closure_analysis::ProjectionKind::Deref => {
+ result.insert(0, '*');
+ last_was_deref = true;
+ }
+ hir_ty::closure_analysis::ProjectionKind::Field { field_idx, variant_idx } => {
+ if last_was_deref {
+ result.insert(0, '(');
+ result.push(')');
+ last_was_deref = false;
+ }
+
+ let ty = place.ty_before_projection(i);
+ match ty.kind() {
+ TyKind::Tuple(_) => format_to!(result, ".{field_idx}"),
+ TyKind::Adt(adt_def, _) => {
+ let variant = match adt_def.def_id().0 {
+ AdtId::StructId(id) => VariantId::from(id),
+ AdtId::UnionId(id) => id.into(),
+ AdtId::EnumId(id) => {
+ // Can't really do that for an enum, unfortunately, so try to do something alike.
+ id.enum_variants(db).variants[variant_idx as usize].0.into()
+ }
+ };
+ let field = &variant.fields(db).fields()
+ [LocalFieldId::from_raw(la_arena::RawIdx::from_u32(field_idx))];
+ format_to!(result, ".{}", field.name.display(db, Edition::LATEST));
+ }
+ _ => never!("mismatching projection type"),
+ }
+ }
+ _ => never!("unexpected projection kind"),
+ }
+ }
+ result
+}
+
fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
let _tracing = setup_tracing();
let (db, file_id) = TestDB::with_single_file(ra_fixture);
@@ -40,84 +84,69 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
};
let infer = InferenceResult::of(&db, def);
let db = &db;
- captures_info.extend(infer.closure_info.iter().flat_map(
- |(closure_id, (captures, _))| {
- let closure = db.lookup_intern_closure(*closure_id);
- let body_owner = closure.0;
- let source_map = ExpressionStore::with_source_map(db, body_owner).1;
- let closure_text_range = source_map
- .expr_syntax(closure.1)
- .expect("failed to map closure to SyntaxNode")
- .value
- .text_range();
- captures.iter().map(move |capture| {
- fn text_range<N: AstNode>(
- db: &TestDB,
- syntax: InFileWrapper<HirFileId, AstPtr<N>>,
- ) -> TextRange {
- let root = syntax.file_syntax(db);
- syntax.value.to_node(&root).syntax().text_range()
+ captures_info.extend(infer.closures_data.iter().flat_map(|(closure, closure_data)| {
+ let (body, source_map) = Body::with_source_map(db, def);
+ let closure_text_range = source_map
+ .expr_syntax(*closure)
+ .expect("failed to map closure to SyntaxNode")
+ .value
+ .text_range();
+ closure_data.min_captures.values().flatten().map(move |capture| {
+ fn text_range<N: AstNode>(
+ db: &TestDB,
+ syntax: InFileWrapper<HirFileId, AstPtr<N>>,
+ ) -> TextRange {
+ let root = syntax.file_syntax(db);
+ syntax.value.to_node(&root).syntax().text_range()
+ }
+
+ // FIXME: Deduplicate this with hir::Local::sources().
+ let captured_local = capture.captured_local();
+ let local_text_range = match body.self_param.zip(source_map.self_param_syntax())
+ {
+ Some((param, source)) if param == captured_local => {
+ format!("{:?}", text_range(db, source))
}
-
- // FIXME: Deduplicate this with hir::Local::sources().
- let (body, source_map) =
- Body::with_source_map(db, body_owner.as_def_with_body().unwrap());
- let local_text_range =
- match body.self_param.zip(source_map.self_param_syntax()) {
- Some((param, source)) if param == capture.local() => {
- format!("{:?}", text_range(db, source))
- }
- _ => source_map
- .patterns_for_binding(capture.local())
- .iter()
- .map(|&definition| {
- text_range(db, source_map.pat_syntax(definition).unwrap())
- })
- .map(|it| format!("{it:?}"))
- .join(", "),
- };
- let place = capture.display_place(body_owner, db);
- let capture_ty = capture
- .ty
- .get()
- .skip_binder()
- .display_test(db, DisplayTarget::from_crate(db, module.krate(db)))
- .to_string();
- let spans = capture
- .spans()
+ _ => source_map
+ .patterns_for_binding(captured_local)
.iter()
- .flat_map(|span| match *span {
- MirSpan::ExprId(expr) => {
- vec![text_range(db, source_map.expr_syntax(expr).unwrap())]
- }
- MirSpan::PatId(pat) => {
- vec![text_range(db, source_map.pat_syntax(pat).unwrap())]
- }
- MirSpan::BindingId(binding) => source_map
- .patterns_for_binding(binding)
- .iter()
- .map(|pat| text_range(db, source_map.pat_syntax(*pat).unwrap()))
- .collect(),
- MirSpan::SelfParam => {
- vec![text_range(db, source_map.self_param_syntax().unwrap())]
- }
- MirSpan::Unknown => Vec::new(),
+ .map(|&definition| {
+ text_range(db, source_map.pat_syntax(definition).unwrap())
})
- .sorted_by_key(|it| it.start())
.map(|it| format!("{it:?}"))
- .join(",");
-
- (
- closure_text_range,
- local_text_range,
- spans,
- place,
- capture_ty,
- capture.kind(),
- )
- })
- },
- ));
+ .join(", "),
+ };
+ let place = display_place(db, body, &capture.place, captured_local);
+ let capture_ty = capture
+ .captured_ty(db)
+ .display_test(db, DisplayTarget::from_crate(db, module.krate(db)))
+ .to_string();
+ let spans = capture
+ .info
+ .sources
+ .iter()
+ .flat_map(|span| match span.final_source() {
+ ExprOrPatId::ExprId(expr) => {
+ vec![text_range(db, source_map.expr_syntax(expr).unwrap())]
+ }
+ ExprOrPatId::PatId(pat) => {
+ vec![text_range(db, source_map.pat_syntax(pat).unwrap())]
+ }
+ })
+ .sorted_by_key(|it| it.start())
+ .map(|it| format!("{it:?}"))
+ .join(",");
+
+ (
+ closure_text_range,
+ local_text_range,
+ spans,
+ place,
+ capture_ty,
+ capture.info.capture_kind,
+ )
+ })
+ }));
}
captures_info.sort_unstable_by_key(|(closure_text_range, local_text_range, ..)| {
(closure_text_range.start(), local_text_range.clone())
@@ -146,7 +175,7 @@ fn main() {
let closure = || { let b = *a; };
}
"#,
- expect!["53..71;20..21;66..68 ByRef(Shared) *a &'? bool"],
+ expect!["53..71;20..21;66..68 ByRef(Immutable) *a &'<erased> bool"],
);
}
@@ -160,7 +189,7 @@ fn main() {
let closure = || { let &mut ref b = a; };
}
"#,
- expect!["53..79;20..21;67..72 ByRef(Shared) *a &'? bool"],
+ expect!["53..79;20..21;62..72 ByRef(Immutable) *a &'<erased> bool"],
);
check_closure_captures(
r#"
@@ -170,7 +199,7 @@ fn main() {
let closure = || { let &mut ref mut b = a; };
}
"#,
- expect!["53..83;20..21;67..76 ByRef(Mut { kind: Default }) *a &'? mut bool"],
+ expect!["53..83;20..21;62..76 ByRef(Mutable) *a &'<erased> mut bool"],
);
}
@@ -184,7 +213,7 @@ fn main() {
let closure = || { *a = false; };
}
"#,
- expect!["53..71;20..21;58..60 ByRef(Mut { kind: Default }) *a &'? mut bool"],
+ expect!["53..71;20..21;58..60 ByRef(Mutable) *a &'<erased> mut bool"],
);
}
@@ -198,7 +227,7 @@ fn main() {
let closure = || { let ref mut b = *a; };
}
"#,
- expect!["53..79;20..21;62..71 ByRef(Mut { kind: Default }) *a &'? mut bool"],
+ expect!["53..79;20..21;74..76 ByRef(Mutable) *a &'<erased> mut bool"],
);
}
@@ -212,7 +241,7 @@ fn main() {
let closure = || { let _ = *a else { return; }; };
}
"#,
- expect!["53..88;20..21;66..68 ByRef(Shared) *a &'? bool"],
+ expect![""],
);
}
@@ -244,8 +273,8 @@ fn main() {
}
"#,
expect![[r#"
- 71..89;36..41;84..86 ByRef(Shared) a &'? NonCopy
- 109..131;36..41;122..128 ByRef(Mut { kind: Default }) a &'? mut NonCopy"#]],
+ 71..89;36..41;85..86 ByRef(Immutable) a &'<erased> NonCopy
+ 109..131;36..41;127..128 ByRef(Mutable) a &'<erased> mut NonCopy"#]],
);
}
@@ -260,7 +289,7 @@ fn main() {
let closure = || { let b = a.a; };
}
"#,
- expect!["92..111;50..51;105..108 ByRef(Shared) a.a &'? i32"],
+ expect!["92..111;50..51;105..108 ByRef(Immutable) a.a &'<erased> i32"],
);
}
@@ -281,8 +310,8 @@ fn main() {
}
"#,
expect![[r#"
- 133..212;87..92;154..158 ByRef(Shared) a.a &'? i32
- 133..212;87..92;176..184 ByRef(Mut { kind: Default }) a.b &'? mut i32
+ 133..212;87..92;155..158 ByRef(Immutable) a.a &'<erased> i32
+ 133..212;87..92;181..184 ByRef(Mutable) a.b &'<erased> mut i32
133..212;87..92;202..205 ByValue a.c NonCopy"#]],
);
}
@@ -304,8 +333,8 @@ fn main() {
}
"#,
expect![[r#"
- 123..133;92..97;126..127 ByRef(Shared) a &'? Foo
- 153..164;92..97;156..157 ByRef(Mut { kind: Default }) a &'? mut Foo"#]],
+ 123..133;92..97;126..127 ByRef(Immutable) a &'<erased> Foo
+ 153..164;92..97;156..157 ByRef(Mutable) a &'<erased> mut Foo"#]],
);
}
@@ -332,7 +361,7 @@ fn main() {
}
"#,
expect![[r#"
- 113..167;36..41;127..128,154..160 ByRef(Mut { kind: Default }) a &'? mut &'? mut bool
+ 113..167;36..41;127..128,159..160 ByRef(Mutable) a &'<erased> mut &'? mut bool
231..304;196..201;252..253,276..277,296..297 ByValue a NonCopy"#]],
);
}
@@ -371,8 +400,8 @@ fn main() {
}
"#,
expect![[r#"
- 125..163;36..41;134..135 ByRef(Shared) a &'? NonCopy
- 183..225;36..41;192..193 ByRef(Mut { kind: Default }) a &'? mut NonCopy"#]],
+ 125..163;36..41;134..135 ByRef(Immutable) a &'<erased> NonCopy
+ 183..225;36..41;192..193 ByRef(Mutable) a &'<erased> mut NonCopy"#]],
);
}
@@ -386,7 +415,7 @@ fn main() {
let mut closure = || { let (b | b) = a; };
}
"#,
- expect!["57..80;20..25;76..77,76..77 ByRef(Shared) a &'? bool"],
+ expect!["57..80;20..25;76..77 ByRef(Immutable) a &'<erased> bool"],
);
}
@@ -406,7 +435,7 @@ fn main() {
}
"#,
expect![
- "57..149;20..25;78..80,98..100,118..124,134..135 ByRef(Mut { kind: Default }) a &'? mut bool"
+ "57..149;20..25;79..80,99..100,123..124,134..135 ByRef(Mutable) a &'<erased> mut bool"
],
);
}
@@ -421,7 +450,7 @@ fn main() {
let mut closure = || { let b = *&mut a; };
}
"#,
- expect!["57..80;20..25;71..77 ByRef(Mut { kind: Default }) a &'? mut bool"],
+ expect!["57..80;20..25;76..77 ByRef(Mutable) a &'<erased> mut bool"],
);
}
@@ -440,10 +469,10 @@ fn main() {
}
"#,
expect![[r#"
- 54..72;20..25;67..69 ByRef(Shared) a &'? &'? bool
- 92..114;20..25;105..111 ByRef(Mut { kind: Default }) a &'? mut &'? bool
- 158..176;124..125;171..173 ByRef(Shared) a &'? &'? mut bool
- 196..218;124..125;209..215 ByRef(Mut { kind: Default }) a &'? mut &'? mut bool"#]],
+ 54..72;20..25;68..69 ByRef(Immutable) a &'<erased> &'? bool
+ 92..114;20..25;110..111 ByRef(Mutable) a &'<erased> mut &'? bool
+ 158..176;124..125;172..173 ByRef(Immutable) a &'<erased> &'? mut bool
+ 196..218;124..125;214..215 ByRef(Mutable) a &'<erased> mut &'? mut bool"#]],
);
}
@@ -451,7 +480,7 @@ fn main() {
fn multiple_capture_usages() {
check_closure_captures(
r#"
-//- minicore:copy, fn
+//- minicore: copy, fn
struct A { a: i32, b: bool }
fn main() {
let mut a = A { a: 123, b: false };
@@ -462,7 +491,7 @@ fn main() {
closure();
}
"#,
- expect!["99..165;49..54;120..121,133..134 ByRef(Mut { kind: Default }) a &'? mut A"],
+ expect!["99..165;49..54;120..121,133..134 ByRef(Mutable) a &'<erased> mut A"],
);
}
@@ -485,8 +514,8 @@ fn main() {
}
"#,
expect![[r#"
- 129..225;49..54;149..155 ByRef(Shared) s_ref &'? &'? mut S
- 129..225;93..99;188..198 ByRef(Mut { kind: Default }) s_ref2 &'? mut &'? mut S"#]],
+ 129..225;49..54;158..163 ByRef(Immutable) s_ref &'<erased> &'? mut S
+ 129..225;93..99;201..207 ByRef(Mutable) s_ref2 &'<erased> mut &'? mut S"#]],
);
}
@@ -530,7 +559,7 @@ fn main() {
};
}
"#,
- expect!["220..257;174..175;245..250 ByRef(Shared) c.b.x &'? i32"],
+ expect!["220..257;174..175;245..250 ByRef(Immutable) c.b.x &'<erased> i32"],
);
}
@@ -549,8 +578,8 @@ fn f() {
}
"#,
expect![[r#"
- 44..113;17..18;92..93 ByRef(Shared) a &'? i32
- 73..106;17..18;92..93 ByRef(Shared) a &'? i32"#]],
+ 44..113;17..18;92..93 ByRef(Immutable) a &'<erased> i32
+ 73..106;17..18;92..93 ByRef(Immutable) a &'<erased> i32"#]],
);
}
@@ -568,6 +597,6 @@ fn f() {
};
}
"#,
- expect!["77..110;46..47;96..97 ByRef(Shared) b &'? i32"],
+ expect!["77..110;46..47;96..97 ByRef(Immutable) b &'<erased> i32"],
);
}