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.rs | 247 |
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"], ); } |