From b9a1e693a77b626aade2cc95f549b4b6e6029097 Mon Sep 17 00:00:00 2001 From: Johannes Schilling Date: Wed, 21 Apr 2021 14:09:15 +0200 Subject: [PATCH 01/11] Make AssertKind::fmt_assert_args public --- compiler/rustc_middle/src/mir/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 998868211401f..291ac0118a6cf 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1340,7 +1340,7 @@ impl AssertKind { } /// Format the message arguments for the `assert(cond, msg..)` terminator in MIR printing. - fn fmt_assert_args(&self, f: &mut W) -> fmt::Result + pub fn fmt_assert_args(&self, f: &mut W) -> fmt::Result where O: Debug, { From 060deec4b1e94be6fbc640a027c1a935d970e33e Mon Sep 17 00:00:00 2001 From: lrh2000 Date: Fri, 30 Apr 2021 16:14:42 +0800 Subject: [PATCH 02/11] Move outer fields of enums into variant parts in debuginfo All fields except the discriminant (including `outer_fields`) should be put into structures inside the variant part, which gives an equivalent layout but offers us much better integration with debuggers. --- .../src/debuginfo/metadata.rs | 31 ++++++++++++++++--- src/test/debuginfo/generator-objects.rs | 16 +++++----- src/test/debuginfo/issue-57822.rs | 4 +-- 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index e6fa852155b51..800133b5f0fac 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -309,6 +309,7 @@ impl RecursiveTypeDescription<'ll, 'tcx> { unfinished_type, member_holding_stub, member_descriptions, + None, ); MetadataCreationResult::new(metadata_stub, true) } @@ -1459,6 +1460,7 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> { layout: TyAndLayout<'tcx>, tag_type_metadata: Option<&'ll DIType>, containing_scope: &'ll DIScope, + common_members: Vec>, span: Span, } @@ -1523,6 +1525,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { self.enum_type, variant_type_metadata, member_descriptions, + Some(&self.common_members), ); vec![MemberDescription { name: if fallback { String::new() } else { variant_info.variant_name() }, @@ -1572,6 +1575,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { self.enum_type, variant_type_metadata, member_descriptions, + Some(&self.common_members), ); MemberDescription { @@ -1621,6 +1625,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { self.enum_type, variant_type_metadata, variant_member_descriptions, + Some(&self.common_members), ); // Encode the information about the null variant in the union @@ -1695,6 +1700,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { self.enum_type, variant_type_metadata, member_descriptions, + Some(&self.common_members), ); let niche_value = if i == dataful_variant { @@ -2102,6 +2108,7 @@ fn prepare_enum_metadata( layout, tag_type_metadata: discriminant_type_metadata, containing_scope, + common_members: vec![], span, }), ); @@ -2171,7 +2178,7 @@ fn prepare_enum_metadata( } }; - let mut outer_fields = match layout.variants { + let outer_fields = match layout.variants { Variants::Single { .. } => vec![], Variants::Multiple { .. } => { let tuple_mdf = TupleMemberDescriptionFactory { @@ -2210,11 +2217,14 @@ fn prepare_enum_metadata( variant_part_unique_type_id_str.len(), ) }; - outer_fields.push(Some(variant_part)); let struct_wrapper = { // The variant part must be wrapped in a struct according to DWARF. - let type_array = create_DIArray(DIB(cx), &outer_fields); + // All fields except the discriminant (including `outer_fields`) + // should be put into structures inside the variant part, which gives + // an equivalent layout but offers us much better integration with + // debuggers. + let type_array = create_DIArray(DIB(cx), &[Some(variant_part)]); let type_map = debug_context(cx).type_map.borrow(); let unique_type_id_str = type_map.get_unique_type_id_as_string(unique_type_id); @@ -2251,6 +2261,7 @@ fn prepare_enum_metadata( layout, tag_type_metadata: None, containing_scope, + common_members: outer_fields, span, }), ) @@ -2283,7 +2294,13 @@ fn composite_type_metadata( DIFlags::FlagZero, ); // ... and immediately create and add the member descriptions. - set_members_of_composite_type(cx, composite_type, composite_type_metadata, member_descriptions); + set_members_of_composite_type( + cx, + composite_type, + composite_type_metadata, + member_descriptions, + None, + ); composite_type_metadata } @@ -2293,6 +2310,7 @@ fn set_members_of_composite_type( composite_type: Ty<'tcx>, composite_type_metadata: &'ll DICompositeType, member_descriptions: Vec>, + common_members: Option<&Vec>>, ) { // In some rare cases LLVM metadata uniquing would lead to an existing type // description being used instead of a new one created in @@ -2311,10 +2329,13 @@ fn set_members_of_composite_type( } } - let member_metadata: Vec<_> = member_descriptions + let mut member_metadata: Vec<_> = member_descriptions .into_iter() .map(|desc| Some(desc.into_metadata(cx, composite_type_metadata))) .collect(); + if let Some(other_members) = common_members { + member_metadata.extend(other_members.iter()); + } let type_params = compute_type_parameters(cx, composite_type); unsafe { diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs index b65471011fd2a..3437b295e6e9c 100644 --- a/src/test/debuginfo/generator-objects.rs +++ b/src/test/debuginfo/generator-objects.rs @@ -7,31 +7,31 @@ // gdb-command:run // gdb-command:print b -// gdb-check:$1 = generator_objects::main::generator-0 {__0: 0x[...], <>: {__state: 0, 0: generator_objects::main::generator-0::Unresumed, 1: generator_objects::main::generator-0::Returned, 2: generator_objects::main::generator-0::Panicked, 3: generator_objects::main::generator-0::Suspend0 {[...]}, 4: generator_objects::main::generator-0::Suspend1 {[...]}}} +// gdb-check:$1 = // gdb-command:continue // gdb-command:print b -// gdb-check:$2 = generator_objects::main::generator-0 {__0: 0x[...], <>: {__state: 3, 0: generator_objects::main::generator-0::Unresumed, 1: generator_objects::main::generator-0::Returned, 2: generator_objects::main::generator-0::Panicked, 3: generator_objects::main::generator-0::Suspend0 {c: 6, d: 7}, 4: generator_objects::main::generator-0::Suspend1 {[...]}}} +// gdb-check:$2 = // gdb-command:continue // gdb-command:print b -// gdb-check:$3 = generator_objects::main::generator-0 {__0: 0x[...], <>: {__state: 4, 0: generator_objects::main::generator-0::Unresumed, 1: generator_objects::main::generator-0::Returned, 2: generator_objects::main::generator-0::Panicked, 3: generator_objects::main::generator-0::Suspend0 {[...]}, 4: generator_objects::main::generator-0::Suspend1 {c: 7, d: 8}}} +// gdb-check:$3 = // gdb-command:continue // gdb-command:print b -// gdb-check:$4 = generator_objects::main::generator-0 {__0: 0x[...], <>: {__state: 1, 0: generator_objects::main::generator-0::Unresumed, 1: generator_objects::main::generator-0::Returned, 2: generator_objects::main::generator-0::Panicked, 3: generator_objects::main::generator-0::Suspend0 {[...]}, 4: generator_objects::main::generator-0::Suspend1 {[...]}}} +// gdb-check:$4 = // === LLDB TESTS ================================================================================== // lldb-command:run // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $0 = { 0 = 0x[...] } +// lldbg-check:(generator_objects::main::generator-0) $0 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $1 = { 0 = 0x[...] } +// lldbg-check:(generator_objects::main::generator-0) $1 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $2 = { 0 = 0x[...] } +// lldbg-check:(generator_objects::main::generator-0) $2 = // lldb-command:continue // lldb-command:print b -// lldbg-check:(generator_objects::main::generator-0) $3 = { 0 = 0x[...] } +// lldbg-check:(generator_objects::main::generator-0) $3 = #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] #![omit_gdb_pretty_printer_section] diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs index a68e4c0a5565b..3a9eaecd5e75e 100644 --- a/src/test/debuginfo/issue-57822.rs +++ b/src/test/debuginfo/issue-57822.rs @@ -14,7 +14,7 @@ // gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure-0 (1)) // gdb-command:print b -// gdb-check:$2 = issue_57822::main::generator-3 {__0: issue_57822::main::generator-2 {__0: 2, <>: {[...]}}, <>: {[...]}} +// gdb-check:$2 = // === LLDB TESTS ================================================================================== @@ -24,7 +24,7 @@ // lldbg-check:(issue_57822::main::closure-1) $0 = { 0 = { 0 = 1 } } // lldb-command:print b -// lldbg-check:(issue_57822::main::generator-3) $1 = { 0 = { 0 = 2 } } +// lldbg-check:(issue_57822::main::generator-3) $1 = #![feature(omit_gdb_pretty_printer_section, generators, generator_trait)] #![omit_gdb_pretty_printer_section] From 5bf989ece9e29941f2c517a39289a60bfb8595c0 Mon Sep 17 00:00:00 2001 From: lrh2000 Date: Fri, 30 Apr 2021 20:02:53 +0800 Subject: [PATCH 03/11] Remove artificial flag from generator variants - Literally, variants are not artificial. We have `yield` statements, upvars and inner variables in the source code. - Functionally, we don't want debuggers to suppress the variants. It contains the state of the generator, which is useful when debugging. So they shouldn't be marked artificial. - Debuggers may use artificial flags to find the active variant. In this case, marking variants artificial will make debuggers not work properly. Fixes #79009. --- .../src/debuginfo/metadata.rs | 33 +++++-------------- src/test/codegen/async-fn-debug-msvc.rs | 24 +++++++++----- src/test/codegen/async-fn-debug.rs | 29 +++++++++------- src/test/codegen/generator-debug-msvc.rs | 24 +++++++++----- src/test/codegen/generator-debug.rs | 29 +++++++++------- src/test/debuginfo/generator-objects.rs | 12 ++++--- src/test/debuginfo/issue-57822.rs | 2 +- 7 files changed, 83 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 800133b5f0fac..280d9a4d37021 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -1495,10 +1495,6 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { } else { type_metadata(cx, self.enum_type, self.span) }; - let flags = match self.enum_type.kind() { - ty::Generator(..) => DIFlags::FlagArtificial, - _ => DIFlags::FlagZero, - }; match self.layout.variants { Variants::Single { index } => { @@ -1533,7 +1529,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: self.layout.size, align: self.layout.align.abi, - flags, + flags: DIFlags::FlagZero, discriminant: None, source_info: variant_info.source_info(cx), }] @@ -1588,7 +1584,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: self.layout.size, align: self.layout.align.abi, - flags, + flags: DIFlags::FlagZero, discriminant: Some( self.layout.ty.discriminant_for_variant(cx.tcx, i).unwrap().val as u64, @@ -1672,7 +1668,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: variant.size, align: variant.align.abi, - flags, + flags: DIFlags::FlagZero, discriminant: None, source_info: variant_info.source_info(cx), }] @@ -1723,7 +1719,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { offset: Size::ZERO, size: self.layout.size, align: self.layout.align.abi, - flags, + flags: DIFlags::FlagZero, discriminant: niche_value, source_info: variant_info.source_info(cx), } @@ -1855,13 +1851,6 @@ impl<'tcx> VariantInfo<'_, 'tcx> { } None } - - fn is_artificial(&self) -> bool { - match self { - VariantInfo::Generator { .. } => true, - VariantInfo::Adt(..) => false, - } - } } /// Returns a tuple of (1) `type_metadata_stub` of the variant, (2) a @@ -1887,8 +1876,7 @@ fn describe_enum_variant( &variant_name, unique_type_id, Some(containing_scope), - // FIXME(tmandry): This doesn't seem to have any effect. - if variant.is_artificial() { DIFlags::FlagArtificial } else { DIFlags::FlagZero }, + DIFlags::FlagZero, ) }); @@ -1951,11 +1939,6 @@ fn prepare_enum_metadata( ) -> RecursiveTypeDescription<'ll, 'tcx> { let tcx = cx.tcx; let enum_name = compute_debuginfo_type_name(tcx, enum_type, false); - // FIXME(tmandry): This doesn't seem to have any effect. - let enum_flags = match enum_type.kind() { - ty::Generator(..) => DIFlags::FlagArtificial, - _ => DIFlags::FlagZero, - }; let containing_scope = get_namespace_for_item(cx, enum_def_id); // FIXME: This should emit actual file metadata for the enum, but we @@ -2088,7 +2071,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, layout.size.bits(), layout.align.abi.bits() as u32, - enum_flags, + DIFlags::FlagZero, None, 0, // RuntimeLang unique_type_id_str.as_ptr().cast(), @@ -2210,7 +2193,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, layout.size.bits(), layout.align.abi.bits() as u32, - enum_flags, + DIFlags::FlagZero, discriminator_metadata, empty_array, variant_part_unique_type_id_str.as_ptr().cast(), @@ -2239,7 +2222,7 @@ fn prepare_enum_metadata( UNKNOWN_LINE_NUMBER, layout.size.bits(), layout.align.abi.bits() as u32, - enum_flags, + DIFlags::FlagZero, None, type_array, 0, diff --git a/src/test/codegen/async-fn-debug-msvc.rs b/src/test/codegen/async-fn-debug-msvc.rs index 2b8c0dfc229a3..f2641404aae21 100644 --- a/src/test/codegen/async-fn-debug-msvc.rs +++ b/src/test/codegen/async-fn-debug-msvc.rs @@ -1,7 +1,7 @@ // Verify debuginfo for generators: // - Each variant points to the file and line of its yield point -// - The generator types and variants are marked artificial -// - Captured vars from the source are not marked artificial +// - The discriminants are marked artificial +// - Other fields are not marked artificial // // // compile-flags: -C debuginfo=2 --edition=2018 @@ -17,26 +17,32 @@ async fn async_fn_test() { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[ASYNC_FN]], {{.*}}flags: DIFlagArtificial +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[ASYNC_FN]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 15, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 15, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 12, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 14, // CHECK-SAME: baseType: [[VARIANT:![0-9]*]] -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[ASYNC_FN]], -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]], // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] diff --git a/src/test/codegen/async-fn-debug.rs b/src/test/codegen/async-fn-debug.rs index e9b774b48c3e7..7de115f7e9194 100644 --- a/src/test/codegen/async-fn-debug.rs +++ b/src/test/codegen/async-fn-debug.rs @@ -1,7 +1,7 @@ // Verify debuginfo for async fn: // - Each variant points to the file and line of its yield point -// - The generator types and variants are marked artificial -// - Captured vars from the source are not marked artificial +// - The discriminants are marked artificial +// - Other fields are not marked artificial // // // compile-flags: -C debuginfo=2 --edition=2018 @@ -17,29 +17,36 @@ async fn async_fn_test() { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[ASYNC_FN:!.*]] = !DINamespace(name: "async_fn_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN]], {{.*}}flags: DIFlagArtificial +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[ASYNC_FN]] // CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[ASYNC_FN]], -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE:![0-9]*]], line: 11, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE]], line: 15, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE]], line: 15, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE]], line: 12, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE]], line: 14, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) diff --git a/src/test/codegen/generator-debug-msvc.rs b/src/test/codegen/generator-debug-msvc.rs index 4f8a320ee9b17..44be71f3b9b80 100644 --- a/src/test/codegen/generator-debug-msvc.rs +++ b/src/test/codegen/generator-debug-msvc.rs @@ -1,7 +1,7 @@ // Verify debuginfo for generators: // - Each variant points to the file and line of its yield point -// - The generator types and variants are marked artificial -// - Captured vars from the source are not marked artificial +// - The discriminants are marked artificial +// - Other fields are not marked artificial // // // compile-flags: -C debuginfo=2 @@ -21,26 +21,32 @@ fn generator_test() -> impl Generator { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]], {{.*}}flags: DIFlagArtificial +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_union_type, name: "generator-0", scope: [[GEN_FN]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // For brevity, we only check the struct name and members of the last variant. // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 18, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 18, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 15, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, scope: [[GEN]], // CHECK-SAME: file: [[FILE]], line: 17, // CHECK-SAME: baseType: [[VARIANT:![0-9]*]] -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN_FN]], -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "RUST$ENUM$DISR", scope: [[S1]], // CHECK-SAME: flags: DIFlagArtificial // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] diff --git a/src/test/codegen/generator-debug.rs b/src/test/codegen/generator-debug.rs index 86ac6db702ab9..8b87a2f064604 100644 --- a/src/test/codegen/generator-debug.rs +++ b/src/test/codegen/generator-debug.rs @@ -1,7 +1,7 @@ // Verify debuginfo for generators: // - Each variant points to the file and line of its yield point -// - The generator types and variants are marked artificial -// - Captured vars from the source are not marked artificial +// - The discriminants are marked artificial +// - Other fields are not marked artificial // // // compile-flags: -C debuginfo=2 --edition=2018 @@ -21,29 +21,36 @@ fn generator_test() -> impl Generator { // FIXME: No way to reliably check the filename. // CHECK-DAG: [[GEN_FN:!.*]] = !DINamespace(name: "generator_test" -// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[GEN_FN]], {{.*}}flags: DIFlagArtificial +// CHECK-DAG: [[GEN:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "generator-0", scope: [[GEN_FN]] // CHECK: [[VARIANT:!.*]] = !DICompositeType(tag: DW_TAG_variant_part, scope: [[GEN_FN]], -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: discriminator: [[DISC:![0-9]*]] // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "0", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE:![0-9]*]], line: 14, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "Unresumed", scope: [[GEN]], -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "1", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE]], line: 18, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "2", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE]], line: 18, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "3", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE]], line: 15, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "4", scope: [[VARIANT]], // CHECK-SAME: file: [[FILE]], line: 17, -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: [[S1:!.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Suspend1", scope: [[GEN]], -// CHECK-SAME: flags: DIFlagArtificial +// CHECK-NOT: flags: DIFlagArtificial +// CHECK-SAME: ) // CHECK: {{!.*}} = !DIDerivedType(tag: DW_TAG_member, name: "s", scope: [[S1]] // CHECK-NOT: flags: DIFlagArtificial // CHECK-SAME: ) diff --git a/src/test/debuginfo/generator-objects.rs b/src/test/debuginfo/generator-objects.rs index 3437b295e6e9c..1beed1c835d97 100644 --- a/src/test/debuginfo/generator-objects.rs +++ b/src/test/debuginfo/generator-objects.rs @@ -1,22 +1,26 @@ // Require a gdb that can read DW_TAG_variant_part. // min-gdb-version: 8.2 +// LLDB without native Rust support cannot read DW_TAG_variant_part, +// so it prints nothing for generators. But those tests are kept to +// ensure that LLDB won't crash at least (like #57822). + // compile-flags:-g // === GDB TESTS =================================================================================== // gdb-command:run // gdb-command:print b -// gdb-check:$1 = +// gdb-check:$1 = generator_objects::main::generator-0::Unresumed(0x[...]) // gdb-command:continue // gdb-command:print b -// gdb-check:$2 = +// gdb-check:$2 = generator_objects::main::generator-0::Suspend0{c: 6, d: 7, __0: 0x[...]} // gdb-command:continue // gdb-command:print b -// gdb-check:$3 = +// gdb-check:$3 = generator_objects::main::generator-0::Suspend1{c: 7, d: 8, __0: 0x[...]} // gdb-command:continue // gdb-command:print b -// gdb-check:$4 = +// gdb-check:$4 = generator_objects::main::generator-0::Returned(0x[...]) // === LLDB TESTS ================================================================================== diff --git a/src/test/debuginfo/issue-57822.rs b/src/test/debuginfo/issue-57822.rs index 3a9eaecd5e75e..6b2b12edda5d7 100644 --- a/src/test/debuginfo/issue-57822.rs +++ b/src/test/debuginfo/issue-57822.rs @@ -14,7 +14,7 @@ // gdb-check:$1 = issue_57822::main::closure-1 (issue_57822::main::closure-0 (1)) // gdb-command:print b -// gdb-check:$2 = +// gdb-check:$2 = issue_57822::main::generator-3::Unresumed(issue_57822::main::generator-2::Unresumed(2)) // === LLDB TESTS ================================================================================== From 49e67c393d4706f05f256d87551ea60dc40f20ee Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Fri, 30 Apr 2021 13:04:43 -0700 Subject: [PATCH 04/11] Update compiler-builtins to 0.1.41 to get fix for outlined atomics This should fix linking of other C code (and soon Rust-generated code) on aarch64 musl. --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a55ef7b61436e..f7075cafb5e2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -666,9 +666,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.39" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3748f82c7d366a0b4950257d19db685d4958d2fa27c6d164a3f069fec42b748b" +checksum = "68448b4c6cee41f17bef42cbdad2fde55d05b91a6116c3a517e5389fb742758d" dependencies = [ "cc", "rustc-std-workspace-core", From 649bf22df56c18b28d41978990071b513094345d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timoth=C3=A9e=20Delabrouille?= Date: Sat, 1 May 2021 15:33:49 +0200 Subject: [PATCH 05/11] compute where_outer on demand, remove it from Module --- src/librustdoc/clean/mod.rs | 5 +++-- src/librustdoc/doctree.rs | 13 ++++++++----- src/librustdoc/visit_ast.rs | 11 +++-------- 3 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 6563f398edb6f..12f03d00a657f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -100,12 +100,13 @@ impl Clean for doctree::Module<'_> { // determine if we should display the inner contents or // the outer `mod` item for the source code. let span = Span::from_rustc_span({ + let where_outer = self.where_outer(cx.tcx); let sm = cx.sess().source_map(); - let outer = sm.lookup_char_pos(self.where_outer.lo()); + let outer = sm.lookup_char_pos(where_outer.lo()); let inner = sm.lookup_char_pos(self.where_inner.lo()); if outer.file.start_pos == inner.file.start_pos { // mod foo { ... } - self.where_outer + where_outer } else { // mod foo; (and a separate SourceFile for the contents) self.where_inner diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index d3f4353a58b7b..eadac89f79ef2 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -1,12 +1,12 @@ //! This module is used to store stuff from Rust's AST in a more convenient //! manner (and with prettier names) before cleaning. +use rustc_middle::ty::TyCtxt; use rustc_span::{self, Span, Symbol}; use rustc_hir as hir; crate struct Module<'hir> { crate name: Symbol, - crate where_outer: Span, crate where_inner: Span, crate mods: Vec>, crate id: hir::HirId, @@ -17,16 +17,19 @@ crate struct Module<'hir> { } impl Module<'hir> { - crate fn new(name: Symbol) -> Module<'hir> { + crate fn new(name: Symbol, id: hir::HirId, where_inner: Span) -> Module<'hir> { Module { name, - id: hir::CRATE_HIR_ID, - where_outer: rustc_span::DUMMY_SP, - where_inner: rustc_span::DUMMY_SP, + id, + where_inner, mods: Vec::new(), items: Vec::new(), foreigns: Vec::new(), macros: Vec::new(), } } + + crate fn where_outer(&self, tcx: TyCtxt<'_>) -> Span { + tcx.hir().span(self.id) + } } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c9071eea78b79..ab9a112380ec4 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -8,9 +8,9 @@ use rustc_hir::def_id::DefId; use rustc_hir::Node; use rustc_middle::middle::privacy::AccessLevel; use rustc_middle::ty::TyCtxt; +use rustc_span; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Symbol}; -use rustc_span::{self, Span}; use std::mem; @@ -73,7 +73,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { crate fn visit(mut self, krate: &'tcx hir::Crate<'_>) -> Module<'tcx> { let span = krate.item.inner; let mut top_level_module = self.visit_mod_contents( - span, &Spanned { span, node: hir::VisibilityKind::Public }, hir::CRATE_HIR_ID, &krate.item, @@ -129,16 +128,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { fn visit_mod_contents( &mut self, - span: Span, vis: &hir::Visibility<'_>, id: hir::HirId, m: &'tcx hir::Mod<'tcx>, name: Symbol, ) -> Module<'tcx> { - let mut om = Module::new(name); - om.where_outer = span; - om.where_inner = m.inner; - om.id = id; + let mut om = Module::new(name, id, m.inner); // Keep track of if there were any private modules in the path. let orig_inside_public_path = self.inside_public_path; self.inside_public_path &= vis.node.is_pub(); @@ -312,7 +307,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { om.items.push((item, renamed)) } hir::ItemKind::Mod(ref m) => { - om.mods.push(self.visit_mod_contents(item.span, &item.vis, item.hir_id(), m, name)); + om.mods.push(self.visit_mod_contents(&item.vis, item.hir_id(), m, name)); } hir::ItemKind::Fn(..) | hir::ItemKind::ExternCrate(..) From 08c4fbcea7c3aebdee6ed2fb6c436385f2d60e3c Mon Sep 17 00:00:00 2001 From: Chris Pardy Date: Wed, 17 Mar 2021 02:51:27 -0400 Subject: [PATCH 06/11] Closure capture borrow diagnostics for disjoint captures --- compiler/rustc_middle/src/mir/mod.rs | 11 ++ compiler/rustc_middle/src/ty/closure.rs | 20 ++++ .../diagnostics/conflict_errors.rs | 48 +++++--- .../diagnostics/explain_borrow.rs | 71 ++++++++--- .../src/borrow_check/diagnostics/mod.rs | 113 ++++++++++++------ .../borrow_check/diagnostics/move_errors.rs | 11 +- .../diagnostics/mutability_errors.rs | 3 +- .../borrow_check/diagnostics/region_errors.rs | 1 + compiler/rustc_mir/src/borrow_check/mod.rs | 6 +- compiler/rustc_typeck/src/expr_use_visitor.rs | 4 +- ...async-borrowck-escaping-block-error.stderr | 6 +- .../borrowck-closures-mut-and-imm.stderr | 8 +- .../borrowck-closures-mut-of-imm.stderr | 4 +- .../borrowck-closures-mut-of-mut.stderr | 4 +- .../borrowck-closures-slice-patterns.stderr | 8 +- .../borrowck-closures-two-mut-fail.stderr | 4 +- .../borrowck/borrowck-closures-two-mut.stderr | 4 +- .../borrowck/borrowck-closures-unique.stderr | 2 +- .../borrowck-closures-use-after-free.stderr | 2 +- .../borrowck-insert-during-each.stderr | 4 +- .../borrowck-loan-blocks-move-cc.stderr | 4 +- .../ui/borrowck/borrowck-loan-rcvr.stderr | 2 +- .../borrowck/borrowck-move-by-capture.stderr | 8 +- ...rowck-move-moved-value-into-closure.stderr | 4 +- ...27282-mutate-before-diverging-arm-2.stderr | 2 +- ...sue-27282-reborrow-ref-mut-in-guard.stderr | 2 +- .../diagnostics/borrowck/borrowck-1.rs | 20 ++++ .../diagnostics/borrowck/borrowck-1.stderr | 28 +++++ .../diagnostics/borrowck/borrowck-2.rs | 20 ++++ .../diagnostics/borrowck/borrowck-2.stderr | 28 +++++ .../diagnostics/borrowck/borrowck-3.rs | 19 +++ .../diagnostics/borrowck/borrowck-3.stderr | 27 +++++ .../diagnostics/borrowck/borrowck-4.rs | 21 ++++ .../diagnostics/borrowck/borrowck-4.stderr | 31 +++++ .../borrowck/borrowck-closures-mut-and-imm.rs | 26 ++++ .../borrowck-closures-mut-and-imm.stderr | 30 +++++ .../diagnostics/box.stderr | 6 +- .../diagnostics/cant-mutate-imm-borrow.stderr | 2 +- .../diagnostics/cant-mutate-imm.rs | 4 +- .../diagnostics/cant-mutate-imm.stderr | 4 +- .../diagnostics/multilevel-path.stderr | 2 +- .../diagnostics/mut_ref.stderr | 4 +- .../simple-struct-min-capture.stderr | 4 +- src/test/ui/error-codes/E0504.stderr | 2 +- .../yield-while-ref-reborrowed.stderr | 2 +- src/test/ui/issues/issue-11192.stderr | 2 +- ...27282-mutate-before-diverging-arm-1.stderr | 2 +- ...27282-mutate-before-diverging-arm-3.stderr | 2 +- src/test/ui/issues/issue-61623.stderr | 2 +- src/test/ui/issues/issue-6801.stderr | 2 +- src/test/ui/nll/closure-access-spans.stderr | 4 +- src/test/ui/nll/closure-borrow-spans.stderr | 12 +- src/test/ui/nll/closure-captures.stderr | 12 +- src/test/ui/nll/closure-use-spans.stderr | 4 +- src/test/ui/nll/closures-in-loops.stderr | 2 +- src/test/ui/nll/issue-51268.stderr | 2 +- 56 files changed, 531 insertions(+), 151 deletions(-) create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs create mode 100644 src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e22c0b40d5a53..7c28779ef0b73 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -683,6 +683,15 @@ impl BorrowKind { BorrowKind::Mut { allow_two_phase_borrow } => allow_two_phase_borrow, } } + + pub fn describe_mutability(&self) -> String { + match *self { + BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => { + "immutable".to_string() + } + BorrowKind::Mut { .. } => "mutable".to_string(), + } + } } /////////////////////////////////////////////////////////////////////////// @@ -2369,6 +2378,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; let mut struct_fmt = fmt.debug_struct(&name); + // FIXME: This should be a list of capture names/places if let Some(upvars) = tcx.upvars_mentioned(def_id) { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); @@ -2388,6 +2398,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { let name = format!("[generator@{:?}]", tcx.hir().span(hir_id)); let mut struct_fmt = fmt.debug_struct(&name); + // FIXME: This should be a list of capture names/places if let Some(upvars) = tcx.upvars_mentioned(def_id) { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 887a5831cd720..7790369af7fef 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -151,6 +151,10 @@ pub struct CapturedPlace<'tcx> { } impl CapturedPlace<'tcx> { + pub fn to_string(&self, tcx: TyCtxt<'tcx>) -> String { + place_to_string_for_capture(tcx, &self.place) + } + /// Returns the hir-id of the root variable for the captured place. /// e.g., if `a.b.c` was captured, would return the hir-id for `a`. pub fn get_root_variable(&self) -> hir::HirId { @@ -168,6 +172,22 @@ impl CapturedPlace<'tcx> { } } + /// Return span pointing to use that resulted in selecting the captured path + pub fn get_path_span(&self, tcx: TyCtxt<'tcx>) -> Span { + if let Some(path_expr_id) = self.info.path_expr_id { + tcx.hir().span(path_expr_id) + } else if let Some(capture_kind_expr_id) = self.info.capture_kind_expr_id { + tcx.hir().span(capture_kind_expr_id) + } else { + // Fallback on upvars mentioned if neither path or capture expr id is captured + + // Safe to unwrap since we know this place is captured by the closure, therefore the closure must have upvars. + tcx.upvars_mentioned(self.get_closure_local_def_id()).unwrap() + [&self.get_root_variable()] + .span + } + } + /// Return span pointing to use that resulted in selecting the current capture kind pub fn get_capture_kind_span(&self, tcx: TyCtxt<'tcx>) -> Span { if let Some(capture_kind_expr_id) = self.info.capture_kind_expr_id { diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs index 9f19a474ca38b..30e0b293ffb2f 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs @@ -99,7 +99,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); err.span_label(span, format!("use of possibly-uninitialized {}", item_msg)); - use_spans.var_span_label( + use_spans.var_span_label_path_only( &mut err, format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), ); @@ -255,6 +255,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { partially_str, move_spans.describe() ), + "moved", ); } } @@ -304,7 +305,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - use_spans.var_span_label( + use_spans.var_span_label_path_only( &mut err, format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), ); @@ -434,13 +435,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); err.span_label(span, format!("move out of {} occurs here", value_msg)); - borrow_spans.var_span_label( + borrow_spans.var_span_label_path_only( &mut err, format!("borrow occurs due to use{}", borrow_spans.describe()), ); - move_spans - .var_span_label(&mut err, format!("move occurs due to use{}", move_spans.describe())); + move_spans.var_span_label( + &mut err, + format!("move occurs due to use{}", move_spans.describe()), + "moved", + ); self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( @@ -468,6 +472,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let use_spans = self.move_spans(place.as_ref(), location); let span = use_spans.var_or_use(); + // If the attempted use is in a closure then we do not care about the path span of the place we are currently trying to use + // we call `var_span_label` on `borrow_spans` to annotate if the existing borrow was in a closure let mut err = self.cannot_use_when_mutably_borrowed( span, &self.describe_any_place(place.as_ref()), @@ -475,11 +481,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - borrow_spans.var_span_label(&mut err, { - let place = &borrow.borrowed_place; - let desc_place = self.describe_any_place(place.as_ref()); - format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe()) - }); + borrow_spans.var_span_label( + &mut err, + { + let place = &borrow.borrowed_place; + let desc_place = self.describe_any_place(place.as_ref()); + format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe()) + }, + "mutable", + ); self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( @@ -591,6 +601,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { desc_place, borrow_spans.describe(), ), + "immutable", ); return err; @@ -667,7 +678,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if issued_spans == borrow_spans { borrow_spans.var_span_label( &mut err, - format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe()), + format!("borrows occur due to use of {}{}", desc_place, borrow_spans.describe(),), + gen_borrow_kind.describe_mutability(), ); } else { let borrow_place = &issued_borrow.borrowed_place; @@ -679,6 +691,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_place_desc, issued_spans.describe(), ), + issued_borrow.kind.describe_mutability(), ); borrow_spans.var_span_label( @@ -688,6 +701,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { desc_place, borrow_spans.describe(), ), + gen_borrow_kind.describe_mutability(), ); } @@ -847,7 +861,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap(); let borrow_spans = self.retrieve_borrow_spans(borrow); - let borrow_span = borrow_spans.var_or_use(); + let borrow_span = borrow_spans.var_or_use_path_span(); assert!(root_place.projection.is_empty()); let proper_span = self.body.local_decls[root_place.local].source_info.span; @@ -987,7 +1001,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location, name, borrow, drop_span, borrow_spans ); - let borrow_span = borrow_spans.var_or_use(); + let borrow_span = borrow_spans.var_or_use_path_span(); if let BorrowExplanation::MustBeValidFor { category, span, @@ -1575,6 +1589,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { loan_spans.var_span_label( &mut err, format!("borrow occurs due to use{}", loan_spans.describe()), + loan.kind.describe_mutability(), ); err.buffer(&mut self.errors_buffer); @@ -1585,8 +1600,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place); - loan_spans - .var_span_label(&mut err, format!("borrow occurs due to use{}", loan_spans.describe())); + loan_spans.var_span_label( + &mut err, + format!("borrow occurs due to use{}", loan_spans.describe()), + loan.kind.describe_mutability(), + ); self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic( self.infcx.tcx, diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs index 2a388b8a72bb0..3ebf23c99a904 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs @@ -24,8 +24,8 @@ use super::{find_use, RegionName, UseSpans}; #[derive(Debug)] pub(in crate::borrow_check) enum BorrowExplanation { - UsedLater(LaterUseKind, Span), - UsedLaterInLoop(LaterUseKind, Span), + UsedLater(LaterUseKind, Span, Option), + UsedLaterInLoop(LaterUseKind, Span, Option), UsedLaterWhenDropped { drop_loc: Location, dropped_local: Local, @@ -67,7 +67,7 @@ impl BorrowExplanation { borrow_span: Option, ) { match *self { - BorrowExplanation::UsedLater(later_use_kind, var_or_use_span) => { + BorrowExplanation::UsedLater(later_use_kind, var_or_use_span, path_span) => { let message = match later_use_kind { LaterUseKind::TraitCapture => "captured here by trait object", LaterUseKind::ClosureCapture => "captured here by closure", @@ -75,14 +75,31 @@ impl BorrowExplanation { LaterUseKind::FakeLetRead => "stored here", LaterUseKind::Other => "used here", }; - if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) { - err.span_label( - var_or_use_span, - format!("{}borrow later {}", borrow_desc, message), - ); + // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same + if path_span.map_or(true, |path_span| path_span == var_or_use_span) { + if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) { + err.span_label( + var_or_use_span, + format!("{}borrow later {}", borrow_desc, message), + ); + } + } else { + // path_span must be `Some` as otherwise the if condition is true + let path_span = path_span.unwrap(); + // path_span is only present in the case of closure capture + assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture)); + if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) { + let path_label = "used here by closure"; + let capture_kind_label = message; + err.span_label( + var_or_use_span, + format!("{}borrow later {}", borrow_desc, capture_kind_label), + ); + err.span_label(path_span, path_label); + } } } - BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span) => { + BorrowExplanation::UsedLaterInLoop(later_use_kind, var_or_use_span, path_span) => { let message = match later_use_kind { LaterUseKind::TraitCapture => { "borrow captured here by trait object, in later iteration of loop" @@ -94,7 +111,24 @@ impl BorrowExplanation { LaterUseKind::FakeLetRead => "borrow later stored here", LaterUseKind::Other => "borrow used here, in later iteration of loop", }; - err.span_label(var_or_use_span, format!("{}{}", borrow_desc, message)); + // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same + if path_span.map_or(true, |path_span| path_span == var_or_use_span) { + err.span_label(var_or_use_span, format!("{}{}", borrow_desc, message)); + } else { + // path_span must be `Some` as otherwise the if condition is true + let path_span = path_span.unwrap(); + // path_span is only present in the case of closure capture + assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture)); + if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) { + let path_label = "used here by closure"; + let capture_kind_label = message; + err.span_label( + var_or_use_span, + format!("{}borrow later {}", borrow_desc, capture_kind_label), + ); + err.span_label(path_span, path_label); + } + } } BorrowExplanation::UsedLaterWhenDropped { drop_loc, @@ -311,13 +345,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let borrow_location = location; if self.is_use_in_later_iteration_of_loop(borrow_location, location) { let later_use = self.later_use_kind(borrow, spans, location); - BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1) + BorrowExplanation::UsedLaterInLoop(later_use.0, later_use.1, later_use.2) } else { // Check if the location represents a `FakeRead`, and adapt the error // message to the `FakeReadCause` it is from: in particular, // the ones inserted in optimized `let var = ` patterns. let later_use = self.later_use_kind(borrow, spans, location); - BorrowExplanation::UsedLater(later_use.0, later_use.1) + BorrowExplanation::UsedLater(later_use.0, later_use.1, later_use.2) } } @@ -498,16 +532,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } /// Determine how the borrow was later used. + /// First span returned points to the location of the conflicting use + /// Second span if `Some` is returned in the case of closures and points + /// to the use of the path fn later_use_kind( &self, borrow: &BorrowData<'tcx>, use_spans: UseSpans<'tcx>, location: Location, - ) -> (LaterUseKind, Span) { + ) -> (LaterUseKind, Span, Option) { match use_spans { - UseSpans::ClosureUse { var_span, .. } => { + UseSpans::ClosureUse { capture_kind_span, path_span, .. } => { // Used in a closure. - (LaterUseKind::ClosureCapture, var_span) + (LaterUseKind::ClosureCapture, capture_kind_span, Some(path_span)) } UseSpans::PatUse(span) | UseSpans::OtherUse(span) @@ -542,7 +579,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } }; - return (LaterUseKind::Call, function_span); + return (LaterUseKind::Call, function_span, None); } else { LaterUseKind::Other } @@ -550,7 +587,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { LaterUseKind::Other }; - (kind, span) + (kind, span, None) } } } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs index aa9f18d999628..3a80bc3d18138 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs @@ -18,7 +18,6 @@ use rustc_span::{ Span, }; use rustc_target::abi::VariantIdx; -use std::iter; use super::borrow_set::BorrowData; use super::MirBorrowckCtxt; @@ -216,11 +215,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { PlaceRef { local, projection: [proj_base @ .., elem] } => { match elem { ProjectionElem::Deref => { - // FIXME(project-rfc_2229#36): print capture precisely here. let upvar_field_projection = self.is_upvar_field_projection(place); if let Some(field) = upvar_field_projection { let var_index = field.index(); - let name = self.upvars[var_index].name.to_string(); + let name = self.upvars[var_index].place.to_string(self.infcx.tcx); if self.upvars[var_index].by_ref { buf.push_str(&name); } else { @@ -265,7 +263,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let upvar_field_projection = self.is_upvar_field_projection(place); if let Some(field) = upvar_field_projection { let var_index = field.index(); - let name = self.upvars[var_index].name.to_string(); + let name = self.upvars[var_index].place.to_string(self.infcx.tcx); buf.push_str(&name); } else { let field_name = self @@ -550,8 +548,12 @@ pub(super) enum UseSpans<'tcx> { /// The span of the args of the closure, including the `move` keyword if /// it's present. args_span: Span, - /// The span of the first use of the captured variable inside the closure. - var_span: Span, + /// The span of the use resulting in capture kind + /// Check `ty::CaptureInfo` for more details + capture_kind_span: Span, + /// The span of the use resulting in the captured path + /// Check `ty::CaptureInfo` for more details + path_span: Span, }, /// The access is caused by using a variable as the receiver of a method /// that takes 'self' @@ -606,9 +608,21 @@ impl UseSpans<'_> { } } + pub(super) fn var_or_use_path_span(self) -> Span { + match self { + UseSpans::ClosureUse { path_span: span, .. } + | UseSpans::PatUse(span) + | UseSpans::OtherUse(span) => span, + UseSpans::FnSelfUse { + fn_call_span, kind: FnSelfUseKind::DerefCoercion { .. }, .. + } => fn_call_span, + UseSpans::FnSelfUse { var_span, .. } => var_span, + } + } + pub(super) fn var_or_use(self) -> Span { match self { - UseSpans::ClosureUse { var_span: span, .. } + UseSpans::ClosureUse { capture_kind_span: span, .. } | UseSpans::PatUse(span) | UseSpans::OtherUse(span) => span, UseSpans::FnSelfUse { @@ -636,14 +650,35 @@ impl UseSpans<'_> { } } + // Add a span label to the use of the captured variable, if it exists. + // only adds label to the `path_span` + pub(super) fn var_span_label_path_only( + self, + err: &mut DiagnosticBuilder<'_>, + message: impl Into, + ) { + if let UseSpans::ClosureUse { path_span, .. } = self { + err.span_label(path_span, message); + } + } + // Add a span label to the use of the captured variable, if it exists. pub(super) fn var_span_label( self, err: &mut DiagnosticBuilder<'_>, message: impl Into, + kind_desc: impl Into, ) { - if let UseSpans::ClosureUse { var_span, .. } = self { - err.span_label(var_span, message); + if let UseSpans::ClosureUse { capture_kind_span, path_span, .. } = self { + if capture_kind_span == path_span { + err.span_label(capture_kind_span, message); + } else { + let capture_kind_label = + format!("capture is {} because of use here", kind_desc.into()); + let path_label = message; + err.span_label(capture_kind_span, capture_kind_label); + err.span_label(path_span, path_label); + } } } @@ -791,10 +826,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { box AggregateKind::Closure(def_id, _) | box AggregateKind::Generator(def_id, _, _) => { debug!("move_spans: def_id={:?} places={:?}", def_id, places); - if let Some((args_span, generator_kind, var_span)) = + if let Some((args_span, generator_kind, capture_kind_span, path_span)) = self.closure_span(*def_id, moved_place, places) { - return ClosureUse { generator_kind, args_span, var_span }; + return ClosureUse { + generator_kind, + args_span, + capture_kind_span, + path_span, + }; } } _ => {} @@ -809,10 +849,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | FakeReadCause::ForLet(Some(closure_def_id)) => { debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place); let places = &[Operand::Move(*place)]; - if let Some((args_span, generator_kind, var_span)) = + if let Some((args_span, generator_kind, capture_kind_span, path_span)) = self.closure_span(closure_def_id, moved_place, places) { - return ClosureUse { generator_kind, args_span, var_span }; + return ClosureUse { + generator_kind, + args_span, + capture_kind_span, + path_span, + }; } } _ => {} @@ -972,10 +1017,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "borrow_spans: def_id={:?} is_generator={:?} places={:?}", def_id, is_generator, places ); - if let Some((args_span, generator_kind, var_span)) = + if let Some((args_span, generator_kind, capture_kind_span, path_span)) = self.closure_span(*def_id, Place::from(target).as_ref(), places) { - return ClosureUse { generator_kind, args_span, var_span }; + return ClosureUse { generator_kind, args_span, capture_kind_span, path_span }; } else { return OtherUse(use_span); } @@ -989,13 +1034,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { OtherUse(use_span) } - /// Finds the span of a captured variable within a closure or generator. + /// Finds the spans of a captured place within a closure or generator. + /// The first span is the location of the use resulting in the capture kind of the capture + /// The second span is the location the use resulting in the captured path of the capture fn closure_span( &self, def_id: DefId, target_place: PlaceRef<'tcx>, places: &[Operand<'tcx>], - ) -> Option<(Span, Option, Span)> { + ) -> Option<(Span, Option, Span, Span)> { debug!( "closure_span: def_id={:?} target_place={:?} places={:?}", def_id, target_place, places @@ -1005,13 +1052,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let expr = &self.infcx.tcx.hir().expect_expr(hir_id).kind; debug!("closure_span: hir_id={:?} expr={:?}", hir_id, expr); if let hir::ExprKind::Closure(.., body_id, args_span, _) = expr { - for (captured_place, place) in iter::zip( - self.infcx.tcx.typeck(def_id.expect_local()).closure_min_captures_flattened(def_id), - places, - ) { - let upvar_hir_id = captured_place.get_root_variable(); - //FIXME(project-rfc-2229#8): Use better span from captured_place - let span = self.infcx.tcx.upvars_mentioned(local_did)?[&upvar_hir_id].span; + for (captured_place, place) in self + .infcx + .tcx + .typeck(def_id.expect_local()) + .closure_min_captures_flattened(def_id) + .zip(places) + { match place { Operand::Copy(place) | Operand::Move(place) if target_place == place.as_ref() => @@ -1020,18 +1067,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let body = self.infcx.tcx.hir().body(*body_id); let generator_kind = body.generator_kind(); - // If we have a more specific span available, point to that. - // We do this even though this span might be part of a borrow error - // message rather than a move error message. Our goal is to point - // to a span that shows why the upvar is used in the closure, - // so a move-related span is as good as any (and potentially better, - // if the overall error is due to a move of the upvar). - - let usage_span = match captured_place.info.capture_kind { - ty::UpvarCapture::ByValue(Some(span)) => span, - _ => span, - }; - return Some((*args_span, generator_kind, usage_span)); + return Some(( + *args_span, + generator_kind, + captured_place.get_capture_kind_span(self.infcx.tcx), + captured_place.get_path_span(self.infcx.tcx), + )); } _ => {} } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs index fb7694b7d88e9..3f87d9c7ac948 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/move_errors.rs @@ -345,10 +345,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; let upvar = &self.upvars[upvar_field.unwrap().index()]; - // FIXME(project-rfc-2229#8): Improve borrow-check diagnostics in case of precise - // capture. let upvar_hir_id = upvar.place.get_root_variable(); - let upvar_name = upvar.name; + let upvar_name = upvar.place.to_string(self.infcx.tcx); let upvar_span = self.infcx.tcx.hir().span(upvar_hir_id); let place_name = self.describe_any_place(move_place.as_ref()); @@ -478,8 +476,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.note_type_does_not_implement_copy(err, &place_desc, place_ty, Some(span), ""); use_spans.args_span_label(err, format!("move out of {} occurs here", place_desc)); - use_spans - .var_span_label(err, format!("move occurs due to use{}", use_spans.describe())); + use_spans.var_span_label( + err, + format!("move occurs due to use{}", use_spans.describe()), + "moved", + ); } } } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs index d1fb999e518ca..88122777d2e67 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mutability_errors.rs @@ -85,7 +85,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if self.is_upvar_field_projection(access_place.as_ref()).is_some() { reason = ", as it is not declared as mutable".to_string(); } else { - let name = self.upvars[upvar_index.index()].name; + let name = self.upvars[upvar_index.index()].place.to_string(self.infcx.tcx); reason = format!(", as `{}` is not declared as mutable", name); } } @@ -195,6 +195,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { "mutable borrow occurs due to use of {} in closure", self.describe_any_place(access_place.as_ref()), ), + "mutable", ); borrow_span } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs index 058986593a41b..c3f781c0e9e30 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs @@ -385,6 +385,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label(*span, message); + // FIXME: This should store a captured_place not a hir id if let ReturnConstraint::ClosureUpvar(upvar) = kind { let def_id = match self.regioncx.universal_regions().defining_ty { DefiningTy::Closure(def_id, _) => def_id, diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 2d1d83b1655aa..4c35be39a3d33 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -74,9 +74,6 @@ crate use region_infer::RegionInferenceContext; // FIXME(eddyb) perhaps move this somewhere more centrally. #[derive(Debug)] crate struct Upvar<'tcx> { - // FIXME(project-rfc_2229#36): print capture precisely here. - name: Symbol, - place: CapturedPlace<'tcx>, /// If true, the capture is behind a reference. @@ -159,13 +156,12 @@ fn do_mir_borrowck<'a, 'tcx>( let upvars: Vec<_> = tables .closure_min_captures_flattened(def.did.to_def_id()) .map(|captured_place| { - let var_hir_id = captured_place.get_root_variable(); let capture = captured_place.info.capture_kind; let by_ref = match capture { ty::UpvarCapture::ByValue(_) => false, ty::UpvarCapture::ByRef(..) => true, }; - Upvar { name: tcx.hir().name(var_hir_id), place: captured_place.clone(), by_ref } + Upvar { place: captured_place.clone(), by_ref } }) .collect(); diff --git a/compiler/rustc_typeck/src/expr_use_visitor.rs b/compiler/rustc_typeck/src/expr_use_visitor.rs index 532ee00daf8a0..f174941279484 100644 --- a/compiler/rustc_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_typeck/src/expr_use_visitor.rs @@ -763,7 +763,9 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { PlaceBase::Local(*var_hir_id) }; let place_with_id = PlaceWithHirId::new( - capture_info.path_expr_id.unwrap_or(closure_expr.hir_id), + capture_info.path_expr_id.unwrap_or( + capture_info.capture_kind_expr_id.unwrap_or(closure_expr.hir_id), + ), place.base_ty, place_base, place.projections.clone(), diff --git a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr index 193026541d073..599d0e1355790 100644 --- a/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr +++ b/src/test/ui/async-await/async-borrowck-escaping-block-error.stderr @@ -21,9 +21,9 @@ error[E0373]: async block may outlive the current function, but it borrows `x`, --> $DIR/async-borrowck-escaping-block-error.rs:11:11 | LL | async { *x } - | ^^^-^^ - | | | - | | `x` is borrowed here + | ^^--^^ + | | | + | | `x` is borrowed here | may outlive borrowed value `x` | note: async block is returned here diff --git a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr index edeb21c16d3c8..fadcd11a592aa 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr +++ b/src/test/ui/borrowck/borrowck-closures-mut-and-imm.stderr @@ -73,7 +73,7 @@ error[E0506]: cannot assign to `*x` because it is borrowed --> $DIR/borrowck-closures-mut-and-imm.rs:57:5 | LL | let c1 = || get(&*x); - | -- - borrow occurs due to use in closure + | -- -- borrow occurs due to use in closure | | | borrow of `*x` occurs here LL | *x = 5; @@ -86,7 +86,7 @@ error[E0506]: cannot assign to `*x.f` because it is borrowed --> $DIR/borrowck-closures-mut-and-imm.rs:69:5 | LL | let c1 = || get(&*x.f); - | -- - borrow occurs due to use in closure + | -- ---- borrow occurs due to use in closure | | | borrow of `*x.f` occurs here LL | *x.f = 5; @@ -99,11 +99,11 @@ error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immuta --> $DIR/borrowck-closures-mut-and-imm.rs:81:14 | LL | let c1 = || get(&*x.f); - | -- - first borrow occurs due to use of `x` in closure + | -- ---- first borrow occurs due to use of `x` in closure | | | immutable borrow occurs here LL | let c2 = || *x.f = 5; - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ ---- second borrow occurs due to use of `x` in closure | | | mutable borrow occurs here LL | diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr index 784b903a5896a..537ec9895e106 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr +++ b/src/test/ui/borrowck/borrowck-closures-mut-of-imm.stderr @@ -14,12 +14,12 @@ error[E0524]: two closures require unique access to `x` at the same time --> $DIR/borrowck-closures-mut-of-imm.rs:11:18 | LL | let mut c1 = || set(&mut *x); - | -- - first borrow occurs due to use of `x` in closure + | -- -- first borrow occurs due to use of `x` in closure | | | first closure is constructed here LL | LL | let mut c2 = || set(&mut *x); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ -- second borrow occurs due to use of `x` in closure | | | second closure is constructed here ... diff --git a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr index 471173e595f47..e5ee5a401050a 100644 --- a/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr +++ b/src/test/ui/borrowck/borrowck-closures-mut-of-mut.stderr @@ -2,11 +2,11 @@ error[E0524]: two closures require unique access to `x` at the same time --> $DIR/borrowck-closures-mut-of-mut.rs:14:18 | LL | let mut c1 = || set(&mut *x); - | -- - first borrow occurs due to use of `x` in closure + | -- -- first borrow occurs due to use of `x` in closure | | | first closure is constructed here LL | let mut c2 = || set(&mut *x); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ -- second borrow occurs due to use of `x` in closure | | | second closure is constructed here LL | diff --git a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr index 9e1e47a92412a..411d85b8e0562 100644 --- a/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr +++ b/src/test/ui/borrowck/borrowck-closures-slice-patterns.stderr @@ -45,7 +45,7 @@ error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immut LL | let f = || { | -- immutable borrow occurs here LL | let [ref y, ref z @ ..] = *x; - | - first borrow occurs due to use of `x` in closure + | -- first borrow occurs due to use of `x` in closure LL | }; LL | let r = &mut *x; | ^^^^^^^ mutable borrow occurs here @@ -59,7 +59,7 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires u LL | let mut f = || { | -- closure construction occurs here LL | let [ref mut y, ref mut z @ ..] = *x; - | - first borrow occurs due to use of `x` in closure + | -- first borrow occurs due to use of `x` in closure LL | }; LL | let r = &x; | ^^ second borrow occurs here @@ -86,7 +86,7 @@ error[E0502]: cannot borrow `*x` as mutable because it is also borrowed as immut LL | let f = || { | -- immutable borrow occurs here LL | if let [ref y, ref z @ ..] = *x {} - | - first borrow occurs due to use of `x` in closure + | -- first borrow occurs due to use of `x` in closure LL | }; LL | let r = &mut *x; | ^^^^^^^ mutable borrow occurs here @@ -100,7 +100,7 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires u LL | let mut f = || { | -- closure construction occurs here LL | if let [ref mut y, ref mut z @ ..] = *x {} - | - first borrow occurs due to use of `x` in closure + | -- first borrow occurs due to use of `x` in closure LL | }; LL | let r = &x; | ^^ second borrow occurs here diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr index 07f477d17868f..fe8e7a29e2486 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr +++ b/src/test/ui/borrowck/borrowck-closures-two-mut-fail.stderr @@ -59,11 +59,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/borrowck-closures-two-mut-fail.rs:53:24 | LL | let c1 = to_fn_mut(|| set(&mut *x.f)); - | -- - first borrow occurs due to use of `x` in closure + | -- ---- first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut *x.f)); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ ---- second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here LL | diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr index bffb11640744c..21e329f432939 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr +++ b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr @@ -59,11 +59,11 @@ error[E0499]: cannot borrow `x` as mutable more than once at a time --> $DIR/borrowck-closures-two-mut.rs:49:24 | LL | let c1 = to_fn_mut(|| set(&mut *x.f)); - | -- - first borrow occurs due to use of `x` in closure + | -- ---- first borrow occurs due to use of `x` in closure | | | first mutable borrow occurs here LL | let c2 = to_fn_mut(|| set(&mut *x.f)); - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ ---- second borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here LL | diff --git a/src/test/ui/borrowck/borrowck-closures-unique.stderr b/src/test/ui/borrowck/borrowck-closures-unique.stderr index 64c2f419ffa65..23d3cc0e76ff7 100644 --- a/src/test/ui/borrowck/borrowck-closures-unique.stderr +++ b/src/test/ui/borrowck/borrowck-closures-unique.stderr @@ -20,7 +20,7 @@ LL | let c1 = || get(x); | | | borrow occurs here LL | let c2 = || { get(x); set(x); }; - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ - second borrow occurs due to use of `x` in closure | | | closure construction occurs here LL | c1; diff --git a/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr b/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr index f22b7da811949..a6dbcf36077a7 100644 --- a/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr +++ b/src/test/ui/borrowck/borrowck-closures-use-after-free.stderr @@ -4,7 +4,7 @@ error[E0502]: cannot borrow `*ptr` as immutable because it is also borrowed as m LL | let mut test = |foo: &Foo| { | ----------- mutable borrow occurs here LL | ptr = box Foo { x: ptr.x + 1 }; - | --- first borrow occurs due to use of `ptr` in closure + | --- first borrow occurs due to use of `ptr` in closure LL | }; LL | test(&*ptr); | ---- ^^^^^ immutable borrow occurs here diff --git a/src/test/ui/borrowck/borrowck-insert-during-each.stderr b/src/test/ui/borrowck/borrowck-insert-during-each.stderr index 796390c093b10..a1ac45795fae2 100644 --- a/src/test/ui/borrowck/borrowck-insert-during-each.stderr +++ b/src/test/ui/borrowck/borrowck-insert-during-each.stderr @@ -9,7 +9,7 @@ LL | | LL | | |a| { | | --- closure construction occurs here LL | | f.n.insert(*a); - | | - first borrow occurs due to use of `f` in closure + | | --- first borrow occurs due to use of `f` in closure LL | | }) | |__________^ second borrow occurs here @@ -24,7 +24,7 @@ LL | LL | |a| { | ^^^ closure construction occurs here LL | f.n.insert(*a); - | - second borrow occurs due to use of `f` in closure + | --- second borrow occurs due to use of `f` in closure error: aborting due to 2 previous errors diff --git a/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr index 2acbcd94f8bbf..ac25502ad053c 100644 --- a/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr +++ b/src/test/ui/borrowck/borrowck-loan-blocks-move-cc.stderr @@ -7,7 +7,7 @@ LL | thread::spawn(move|| { | ^^^^^^ move out of `v` occurs here LL | LL | println!("v={}", *v); - | - move occurs due to use in closure + | -- move occurs due to use in closure LL | }); LL | w.use_ref(); | - borrow later used here @@ -21,7 +21,7 @@ LL | thread::spawn(move|| { | ^^^^^^ move out of `v` occurs here LL | LL | println!("v={}", *v); - | - move occurs due to use in closure + | -- move occurs due to use in closure LL | }); LL | w.use_ref(); | - borrow later used here diff --git a/src/test/ui/borrowck/borrowck-loan-rcvr.stderr b/src/test/ui/borrowck/borrowck-loan-rcvr.stderr index ec3edc80323f5..489ec7d04ed1d 100644 --- a/src/test/ui/borrowck/borrowck-loan-rcvr.stderr +++ b/src/test/ui/borrowck/borrowck-loan-rcvr.stderr @@ -7,7 +7,7 @@ LL | p.blockm(|| { | | immutable borrow later used by call | immutable borrow occurs here LL | p.x = 10; - | - second borrow occurs due to use of `p` in closure + | --- second borrow occurs due to use of `p` in closure error[E0502]: cannot borrow `p` as immutable because it is also borrowed as mutable --> $DIR/borrowck-loan-rcvr.rs:34:5 diff --git a/src/test/ui/borrowck/borrowck-move-by-capture.stderr b/src/test/ui/borrowck/borrowck-move-by-capture.stderr index 837bd08253b3b..628f206e0a896 100644 --- a/src/test/ui/borrowck/borrowck-move-by-capture.stderr +++ b/src/test/ui/borrowck/borrowck-move-by-capture.stderr @@ -5,10 +5,10 @@ LL | let bar: Box<_> = box 3; | --- captured outer variable LL | let _g = to_fn_mut(|| { LL | let _h = to_fn_once(move || -> isize { *bar }); - | ^^^^^^^^^^^^^^^^ --- - | | | - | | move occurs because `bar` has type `Box`, which does not implement the `Copy` trait - | | move occurs due to use in closure + | ^^^^^^^^^^^^^^^^ ---- + | | | + | | move occurs because `bar` has type `Box`, which does not implement the `Copy` trait + | | move occurs due to use in closure | move out of `bar` occurs here error: aborting due to previous error diff --git a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.stderr b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.stderr index 44f423c2bd936..1ac4999e6e11d 100644 --- a/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.stderr +++ b/src/test/ui/borrowck/borrowck-move-moved-value-into-closure.stderr @@ -5,11 +5,11 @@ LL | let t: Box<_> = box 3; | - move occurs because `t` has type `Box`, which does not implement the `Copy` trait LL | LL | call_f(move|| { *t + 1 }); - | ------ - variable moved due to use in closure + | ------ -- variable moved due to use in closure | | | value moved into closure here LL | call_f(move|| { *t + 1 }); - | ^^^^^^ - use occurs due to use in closure + | ^^^^^^ -- use occurs due to use in closure | | | value used here after move diff --git a/src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.stderr b/src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.stderr index f0a3151f4e12f..dd46308d14004 100644 --- a/src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.stderr +++ b/src/test/ui/borrowck/issue-27282-mutate-before-diverging-arm-2.stderr @@ -5,7 +5,7 @@ LL | match x { | - value is immutable in match guard ... LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ -- borrow occurs due to use of `x` in closure | | | cannot mutably borrow diff --git a/src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.stderr b/src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.stderr index f0264b56ea569..48433432de1bd 100644 --- a/src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.stderr +++ b/src/test/ui/borrowck/issue-27282-reborrow-ref-mut-in-guard.stderr @@ -2,7 +2,7 @@ error[E0596]: cannot borrow `r` as mutable, as it is immutable for the pattern g --> $DIR/issue-27282-reborrow-ref-mut-in-guard.rs:12:25 | LL | ref mut r if { (|| { let bar = &mut *r; **bar = false; })(); - | ^^ - mutable borrow occurs due to use of `r` in closure + | ^^ -- mutable borrow occurs due to use of `r` in closure | | | cannot borrow as mutable | diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs new file mode 100644 index 0000000000000..2f3358dcd8db7 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.rs @@ -0,0 +1,20 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +fn main() { + let mut p = Point {x: 1, y: 2 }; + + let y = &mut p.y; + let mut c = || { + //~^ ERROR cannot borrow `p` as mutable more than once at a time + let x = &mut p.x; + println!("{:?}", p); + }; + c(); + *y+=1; +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr new file mode 100644 index 0000000000000..e15067b264d63 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-1.stderr @@ -0,0 +1,28 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/borrowck-1.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error[E0499]: cannot borrow `p` as mutable more than once at a time + --> $DIR/borrowck-1.rs:13:17 + | +LL | let y = &mut p.y; + | -------- first mutable borrow occurs here +LL | let mut c = || { + | ^^ second mutable borrow occurs here +LL | +LL | let x = &mut p.x; + | --- capture is mutable because of use here +LL | println!("{:?}", p); + | - second borrow occurs due to use of `p` in closure +... +LL | *y+=1; + | ----- first borrow later used here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0499`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs new file mode 100644 index 0000000000000..06c6a87eb105d --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.rs @@ -0,0 +1,20 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +fn main() { + let mut p = Point {x: 1, y: 2 }; + + let y = &p.y; + let mut c = || { + //~^ ERROR cannot borrow `p` as mutable because it is also borrowed as immutable + println!("{:?}", p); + let x = &mut p.x; + }; + c(); + println!("{}", y); +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr new file mode 100644 index 0000000000000..a195b981eaadd --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-2.stderr @@ -0,0 +1,28 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/borrowck-2.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-2.rs:13:17 + | +LL | let y = &p.y; + | ---- immutable borrow occurs here +LL | let mut c = || { + | ^^ mutable borrow occurs here +LL | +LL | println!("{:?}", p); + | - second borrow occurs due to use of `p` in closure +LL | let x = &mut p.x; + | --- capture is mutable because of use here +... +LL | println!("{}", y); + | - immutable borrow later used here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs new file mode 100644 index 0000000000000..ba998f78c87ac --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.rs @@ -0,0 +1,19 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete + +#[derive(Debug)] +struct Point { + x: String, + y: String, +} +fn main() { + let mut c = { + let mut p = Point {x: "1".to_string(), y: "2".to_string() }; + || { + let x = &mut p.x; + println!("{:?}", p); + //~^ ERROR `p` does not live long enough + } + }; + c(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr new file mode 100644 index 0000000000000..b54c729a307c0 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-3.stderr @@ -0,0 +1,27 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/borrowck-3.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error[E0597]: `p` does not live long enough + --> $DIR/borrowck-3.rs:14:29 + | +LL | let mut c = { + | ----- borrow later stored here +LL | let mut p = Point {x: "1".to_string(), y: "2".to_string() }; +LL | || { + | -- value captured here +LL | let x = &mut p.x; +LL | println!("{:?}", p); + | ^ borrowed value does not live long enough +... +LL | }; + | - `p` dropped here while still borrowed + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0597`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs new file mode 100644 index 0000000000000..4fab0189c27f8 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.rs @@ -0,0 +1,21 @@ +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} +fn foo () -> impl FnMut()->() { + let mut p = Point {x: 1, y: 2 }; + let mut c = || { + //~^ ERROR closure may outlive the current function, but it borrows `p` + p.x+=5; + println!("{:?}", p); + }; + c +} +fn main() { + let c = foo(); + c(); +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr new file mode 100644 index 0000000000000..905fa3475edd8 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-4.stderr @@ -0,0 +1,31 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/borrowck-4.rs:1:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error[E0373]: closure may outlive the current function, but it borrows `p`, which is owned by the current function + --> $DIR/borrowck-4.rs:11:17 + | +LL | let mut c = || { + | ^^ may outlive borrowed value `p` +... +LL | println!("{:?}", p); + | - `p` is borrowed here + | +note: closure is returned here + --> $DIR/borrowck-4.rs:9:14 + | +LL | fn foo () -> impl FnMut()->() { + | ^^^^^^^^^^^^^^^^ +help: to force the closure to take ownership of `p` (and any other referenced variables), use the `move` keyword + | +LL | let mut c = move || { + | ^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0373`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs new file mode 100644 index 0000000000000..b23947ad5d1bf --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.rs @@ -0,0 +1,26 @@ +// Tests that two closures cannot simultaneously have mutable +// and immutable access to the variable. Issue #6801. + +#![feature(capture_disjoint_fields)] +//~^ WARNING: the feature `capture_disjoint_fields` is incomplete +#![feature(box_syntax)] + +#[derive(Debug)] +struct Point { + x: i32, + y: i32, +} + +fn a() { + let mut p = Point {x: 3, y:4}; + let c2 = || p.y * 5; + let c1 = || { + //~^ ERROR cannot borrow `p` as mutable because it is also borrowed as immutable + dbg!(&p); + p.x = 4; + }; + drop(c2); +} + +fn main() { +} diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr new file mode 100644 index 0000000000000..58975c6f46fe4 --- /dev/null +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/borrowck/borrowck-closures-mut-and-imm.stderr @@ -0,0 +1,30 @@ +warning: the feature `capture_disjoint_fields` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/borrowck-closures-mut-and-imm.rs:4:12 + | +LL | #![feature(capture_disjoint_fields)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53488 for more information + +error[E0502]: cannot borrow `p` as mutable because it is also borrowed as immutable + --> $DIR/borrowck-closures-mut-and-imm.rs:17:14 + | +LL | let c2 = || p.y * 5; + | -- --- first borrow occurs due to use of `p.y` in closure + | | + | immutable borrow occurs here +LL | let c1 = || { + | ^^ mutable borrow occurs here +LL | +LL | dbg!(&p); + | - second borrow occurs due to use of `p` in closure +LL | p.x = 4; + | --- capture is mutable because of use here +LL | }; +LL | drop(c2); + | -- immutable borrow later used here + +error: aborting due to previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0502`. diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr index 17a9332fb3e6c..174faa33c49ab 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/box.stderr @@ -13,7 +13,7 @@ error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed LL | let mut c = || { | -- borrow of `e.0.0.m.x` occurs here LL | e.0.0.m.x = format!("not-x"); - | - borrow occurs due to use in closure + | --------- borrow occurs due to use in closure ... LL | e.0.0.m.x = format!("not-x"); | ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here @@ -27,7 +27,7 @@ error[E0502]: cannot borrow `e.0.0.m.x` as immutable because it is also borrowed LL | let mut c = || { | -- mutable borrow occurs here LL | e.0.0.m.x = format!("not-x"); - | - first borrow occurs due to use of `e.0.0.m.x` in closure + | --------- first borrow occurs due to use of `e.0.0.m.x` in closure ... LL | println!("{}", e.0.0.m.x); | ^^^^^^^^^ immutable borrow occurs here @@ -41,7 +41,7 @@ error[E0506]: cannot assign to `e.0.0.m.x` because it is borrowed LL | let c = || { | -- borrow of `e.0.0.m.x` occurs here LL | println!("{}", e.0.0.m.x); - | - borrow occurs due to use in closure + | --------- borrow occurs due to use in closure ... LL | e.0.0.m.x = format!("not-x"); | ^^^^^^^^^ assignment to borrowed `e.0.0.m.x` occurs here diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr index 861bc44b78ded..39a11fb332725 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm-borrow.stderr @@ -14,7 +14,7 @@ LL | let mut c = || { | ^^ cannot borrow as mutable LL | LL | z.0.0.0 = format!("X1"); - | - mutable borrow occurs due to use of `z.0.0.0` in closure + | ------- mutable borrow occurs due to use of `z.0.0.0` in closure error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs index 997ecc7ddddf1..928c866726f71 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.rs @@ -11,7 +11,7 @@ fn mut_error_struct() { let mut c = || { z.0.0.0 = 20; - //~^ ERROR: cannot assign to `z`, as it is not declared as mutable + //~^ ERROR: cannot assign to `z.0.0.0`, as it is not declared as mutable }; c(); @@ -23,7 +23,7 @@ fn mut_error_box() { let mut c = || { bx.0 = 20; - //~^ ERROR: cannot assign to `bx`, as it is not declared as mutable + //~^ ERROR: cannot assign to `*bx.0`, as it is not declared as mutable }; c(); diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr index 5e15635ac6e1b..9fb8dd4a1c36e 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/cant-mutate-imm.stderr @@ -7,7 +7,7 @@ LL | #![feature(capture_disjoint_fields)] = note: `#[warn(incomplete_features)]` on by default = note: see issue #53488 for more information -error[E0594]: cannot assign to `z`, as it is not declared as mutable +error[E0594]: cannot assign to `z.0.0.0`, as it is not declared as mutable --> $DIR/cant-mutate-imm.rs:13:9 | LL | let z = (y, 10); @@ -16,7 +16,7 @@ LL | let z = (y, 10); LL | z.0.0.0 = 20; | ^^^^^^^^^^^^ cannot assign -error[E0594]: cannot assign to `bx`, as it is not declared as mutable +error[E0594]: cannot assign to `*bx.0`, as it is not declared as mutable --> $DIR/cant-mutate-imm.rs:25:9 | LL | let bx = Box::new(x); diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr index e5a396c4e98ae..a3d1f550557af 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/multilevel-path.stderr @@ -13,7 +13,7 @@ error[E0499]: cannot borrow `w.p.x` as mutable more than once at a time LL | let mut c = || { | -- first mutable borrow occurs here LL | w.p.x += 20; - | - first borrow occurs due to use of `w.p.x` in closure + | ----- first borrow occurs due to use of `w.p.x` in closure ... LL | let py = &mut w.p.x; | ^^^^^^^^^^ second mutable borrow occurs here diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr index 8cb2ed2235d55..831e486db82af 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/mut_ref.stderr @@ -17,7 +17,7 @@ LL | let c = || { | ^^ `ref_mref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable LL | LL | **ref_mref_x = y; - | ---------- mutable borrow occurs due to use of `**ref_mref_x` in closure + | ------------ mutable borrow occurs due to use of `**ref_mref_x` in closure error[E0596]: cannot borrow `**mref_ref_x` as mutable, as it is behind a `&` reference --> $DIR/mut_ref.rs:27:13 @@ -26,7 +26,7 @@ LL | let c = || { | ^^ cannot borrow as mutable LL | LL | **mref_ref_x = y; - | ---------- mutable borrow occurs due to use of `**mref_ref_x` in closure + | ------------ mutable borrow occurs due to use of `**mref_ref_x` in closure error: aborting due to 2 previous errors; 1 warning emitted diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr index 45a61cd98b101..f1748fda151c5 100644 --- a/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr +++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/simple-struct-min-capture.stderr @@ -13,7 +13,9 @@ error[E0502]: cannot borrow `p` as immutable because it is also borrowed as muta LL | let mut c = || { | -- mutable borrow occurs here LL | p.x += 10; - | - first borrow occurs due to use of `p` in closure + | --- capture is mutable because of use here +LL | println!("{:?}", p); + | - first borrow occurs due to use of `p` in closure ... LL | println!("{:?}", p); | ^ immutable borrow occurs here diff --git a/src/test/ui/error-codes/E0504.stderr b/src/test/ui/error-codes/E0504.stderr index 1f2a0407a3963..04811721aa521 100644 --- a/src/test/ui/error-codes/E0504.stderr +++ b/src/test/ui/error-codes/E0504.stderr @@ -7,7 +7,7 @@ LL | LL | let x = move || { | ^^^^^^^ move out of `fancy_num` occurs here LL | println!("child function: {}", fancy_num.num); - | --------- move occurs due to use in closure + | ------------- move occurs due to use in closure ... LL | println!("main function: {}", fancy_ref.num); | ------------- borrow later used here diff --git a/src/test/ui/generator/yield-while-ref-reborrowed.stderr b/src/test/ui/generator/yield-while-ref-reborrowed.stderr index fd885660d0927..68d785efcfe5d 100644 --- a/src/test/ui/generator/yield-while-ref-reborrowed.stderr +++ b/src/test/ui/generator/yield-while-ref-reborrowed.stderr @@ -4,7 +4,7 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires u LL | let mut b = || { | -- generator construction occurs here LL | let a = &mut *x; - | - first borrow occurs due to use of `x` in generator + | -- first borrow occurs due to use of `x` in generator ... LL | println!("{}", x); | ^ second borrow occurs here diff --git a/src/test/ui/issues/issue-11192.stderr b/src/test/ui/issues/issue-11192.stderr index dfe7b3f6b5f9c..2a9d913171c3e 100644 --- a/src/test/ui/issues/issue-11192.stderr +++ b/src/test/ui/issues/issue-11192.stderr @@ -5,7 +5,7 @@ LL | let mut test = |foo: &Foo| { | ----------- mutable borrow occurs here LL | println!("access {}", foo.x); LL | ptr = box Foo { x: ptr.x + 1 }; - | --- first borrow occurs due to use of `ptr` in closure + | --- first borrow occurs due to use of `ptr` in closure ... LL | test(&*ptr); | ---- ^^^^^ immutable borrow occurs here diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr index 188f0b25c3084..a1f973e0fdf5a 100644 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr +++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-1.stderr @@ -5,7 +5,7 @@ LL | match x { | - value is immutable in match guard ... LL | (|| { *x = None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ -- borrow occurs due to use of `x` in closure | | | cannot mutably borrow diff --git a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr index f46a42d750817..4a4a25790b985 100644 --- a/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr +++ b/src/test/ui/issues/issue-27282-mutate-before-diverging-arm-3.stderr @@ -5,7 +5,7 @@ LL | match **x { | --- value is immutable in match guard ... LL | (|| { *x = &None; drop(force_fn_once); })(); - | ^^ - borrow occurs due to use of `x` in closure + | ^^ -- borrow occurs due to use of `x` in closure | | | cannot mutably borrow diff --git a/src/test/ui/issues/issue-61623.stderr b/src/test/ui/issues/issue-61623.stderr index 883a1c441d6bb..901c75981768e 100644 --- a/src/test/ui/issues/issue-61623.stderr +++ b/src/test/ui/issues/issue-61623.stderr @@ -10,7 +10,7 @@ error[E0502]: cannot borrow `*x.1` as mutable because it is also borrowed as imm --> $DIR/issue-61623.rs:6:19 | LL | f2(|| x.0, f1(x.1)) - | -- -- - ^^^ mutable borrow occurs here + | -- -- --- ^^^ mutable borrow occurs here | | | | | | | first borrow occurs due to use of `x` in closure | | immutable borrow occurs here diff --git a/src/test/ui/issues/issue-6801.stderr b/src/test/ui/issues/issue-6801.stderr index dbb8e6530c053..48c6acd1f49e4 100644 --- a/src/test/ui/issues/issue-6801.stderr +++ b/src/test/ui/issues/issue-6801.stderr @@ -2,7 +2,7 @@ error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/issue-6801.rs:19:13 | LL | let sq = || { *x * *x }; - | -- - borrow occurs due to use in closure + | -- -- borrow occurs due to use in closure | | | borrow of `x` occurs here LL | diff --git a/src/test/ui/nll/closure-access-spans.stderr b/src/test/ui/nll/closure-access-spans.stderr index ccc043a189059..8eded8f28572e 100644 --- a/src/test/ui/nll/closure-access-spans.stderr +++ b/src/test/ui/nll/closure-access-spans.stderr @@ -28,7 +28,7 @@ error[E0500]: closure requires unique access to `x` but it is already borrowed LL | let r = &mut x; | ------ borrow occurs here LL | || *x = 2; - | ^^ - second borrow occurs due to use of `x` in closure + | ^^ -- second borrow occurs due to use of `x` in closure | | | closure construction occurs here LL | r.use_mut(); @@ -88,7 +88,7 @@ LL | fn closure_unique_capture_moved(x: &mut String) { LL | let r = x; | - value moved here LL | || *x = String::new(); - | ^^ - borrow occurs due to use in closure + | ^^ -- borrow occurs due to use in closure | | | value borrowed here after move diff --git a/src/test/ui/nll/closure-borrow-spans.stderr b/src/test/ui/nll/closure-borrow-spans.stderr index a3bcbbab3ec69..fffbee4d4a8e1 100644 --- a/src/test/ui/nll/closure-borrow-spans.stderr +++ b/src/test/ui/nll/closure-borrow-spans.stderr @@ -110,7 +110,7 @@ error[E0505]: cannot move out of `x` because it is borrowed --> $DIR/closure-borrow-spans.rs:65:13 | LL | let f = || *x = 0; - | -- - borrow occurs due to use in closure + | -- -- borrow occurs due to use in closure | | | borrow of `x` occurs here LL | let y = x; @@ -122,7 +122,7 @@ error[E0501]: cannot borrow `x` as immutable because previous closure requires u --> $DIR/closure-borrow-spans.rs:71:13 | LL | let f = || *x = 0; - | -- - first borrow occurs due to use of `x` in closure + | -- -- first borrow occurs due to use of `x` in closure | | | closure construction occurs here LL | let y = &x; @@ -134,7 +134,7 @@ error[E0501]: cannot borrow `x` as mutable because previous closure requires uni --> $DIR/closure-borrow-spans.rs:77:13 | LL | let f = || *x = 0; - | -- - first borrow occurs due to use of `x` in closure + | -- -- first borrow occurs due to use of `x` in closure | | | closure construction occurs here LL | let y = &mut x; @@ -143,10 +143,10 @@ LL | f.use_ref(); | - first borrow later used here error[E0597]: `x` does not live long enough - --> $DIR/closure-borrow-spans.rs:86:17 + --> $DIR/closure-borrow-spans.rs:86:16 | LL | f = || *x = 0; - | -- ^ borrowed value does not live long enough + | -- ^^ borrowed value does not live long enough | | | value captured here LL | } @@ -158,7 +158,7 @@ error[E0506]: cannot assign to `*x` because it is borrowed --> $DIR/closure-borrow-spans.rs:93:5 | LL | let f = || *x = 0; - | -- - borrow occurs due to use in closure + | -- -- borrow occurs due to use in closure | | | borrow of `*x` occurs here LL | *x = 1; diff --git a/src/test/ui/nll/closure-captures.stderr b/src/test/ui/nll/closure-captures.stderr index dd5f32ef4f581..a59e553315ae6 100644 --- a/src/test/ui/nll/closure-captures.stderr +++ b/src/test/ui/nll/closure-captures.stderr @@ -133,9 +133,9 @@ LL | fn_ref(|| { LL | | || | | ^^ cannot borrow as mutable LL | | *x = 1;}); - | |__________-_____- in this closure - | | - | mutable borrow occurs due to use of `x` in closure + | |_________--_____- in this closure + | | + | mutable borrow occurs due to use of `x` in closure error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:51:9 @@ -150,9 +150,9 @@ LL | fn_ref(move || { LL | | || | | ^^ cannot borrow as mutable LL | | *x = 1;}); - | |__________-_____- in this closure - | | - | mutable borrow occurs due to use of `x` in closure + | |_________--_____- in this closure + | | + | mutable borrow occurs due to use of `x` in closure error: aborting due to 12 previous errors diff --git a/src/test/ui/nll/closure-use-spans.stderr b/src/test/ui/nll/closure-use-spans.stderr index ec7e0f308557d..87162904ba6cd 100644 --- a/src/test/ui/nll/closure-use-spans.stderr +++ b/src/test/ui/nll/closure-use-spans.stderr @@ -6,7 +6,7 @@ LL | let y = &x; LL | x = 0; | ^^^^^ assignment to borrowed `x` occurs here LL | || *y; - | - borrow later captured here by closure + | -- borrow later captured here by closure error[E0506]: cannot assign to `x` because it is borrowed --> $DIR/closure-use-spans.rs:11:5 @@ -16,7 +16,7 @@ LL | let y = &mut x; LL | x = 0; | ^^^^^ assignment to borrowed `x` occurs here LL | || *y = 1; - | - borrow later captured here by closure + | -- borrow later captured here by closure error[E0506]: cannot assign to `x` because it is borrowed --> $DIR/closure-use-spans.rs:17:5 diff --git a/src/test/ui/nll/closures-in-loops.stderr b/src/test/ui/nll/closures-in-loops.stderr index 2f134f83ced19..2be0460df1fc6 100644 --- a/src/test/ui/nll/closures-in-loops.stderr +++ b/src/test/ui/nll/closures-in-loops.stderr @@ -21,7 +21,7 @@ error[E0524]: two closures require unique access to `x` at the same time --> $DIR/closures-in-loops.rs:20:16 | LL | v.push(|| *x = String::new()); - | ^^ - borrows occur due to use of `x` in closure + | ^^ -- borrows occur due to use of `x` in closure | | | closures are constructed here in different iterations of loop diff --git a/src/test/ui/nll/issue-51268.stderr b/src/test/ui/nll/issue-51268.stderr index e6dadc9f6ce3c..0483bda6379fd 100644 --- a/src/test/ui/nll/issue-51268.stderr +++ b/src/test/ui/nll/issue-51268.stderr @@ -8,7 +8,7 @@ LL | self.thing.bar(|| { | | LL | | LL | | &self.number; - | | ---- first borrow occurs due to use of `self` in closure + | | ----------- first borrow occurs due to use of `self` in closure LL | | }); | |__________^ mutable borrow occurs here From 25beade8dfc7943130be503a5e21ca8851d5992b Mon Sep 17 00:00:00 2001 From: ChrisPardy Date: Wed, 28 Apr 2021 21:31:49 -0400 Subject: [PATCH 07/11] Update compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs Co-authored-by: Niko Matsakis --- .../rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs index 3ebf23c99a904..0e12655114235 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs @@ -76,8 +76,8 @@ impl BorrowExplanation { LaterUseKind::Other => "used here", }; // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same - if path_span.map_or(true, |path_span| path_span == var_or_use_span) { - if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) { + if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) { + if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) { err.span_label( var_or_use_span, format!("{}borrow later {}", borrow_desc, message), From 20a1315cbbf38057898a7559376c872ef224a17b Mon Sep 17 00:00:00 2001 From: ChrisPardy Date: Wed, 28 Apr 2021 21:32:01 -0400 Subject: [PATCH 08/11] Update compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs Co-authored-by: Niko Matsakis --- .../rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs index 0e12655114235..49e59f6612fd2 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs @@ -112,7 +112,7 @@ impl BorrowExplanation { LaterUseKind::Other => "borrow used here, in later iteration of loop", }; // We can use `var_or_use_span` if either `path_span` is not present, or both spans are the same - if path_span.map_or(true, |path_span| path_span == var_or_use_span) { + if path_span.map(|path_span| path_span == var_or_use_span).unwrap_or(true) { err.span_label(var_or_use_span, format!("{}{}", borrow_desc, message)); } else { // path_span must be `Some` as otherwise the if condition is true From e612f7abfcab0789fe3acdd206643f726a6303c9 Mon Sep 17 00:00:00 2001 From: ChrisPardy Date: Wed, 28 Apr 2021 21:32:28 -0400 Subject: [PATCH 09/11] Update compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs Co-authored-by: Niko Matsakis --- .../rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs index 49e59f6612fd2..1b0cae51d585d 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/explain_borrow.rs @@ -119,7 +119,7 @@ impl BorrowExplanation { let path_span = path_span.unwrap(); // path_span is only present in the case of closure capture assert!(matches!(later_use_kind, LaterUseKind::ClosureCapture)); - if !borrow_span.map_or(false, |sp| sp.overlaps(var_or_use_span)) { + if borrow_span.map(|sp| !sp.overlaps(var_or_use_span)).unwrap_or(true) { let path_label = "used here by closure"; let capture_kind_label = message; err.span_label( From d19c46870fc31726b0e381d9c20efc95039f4052 Mon Sep 17 00:00:00 2001 From: Chris Pardy Date: Wed, 28 Apr 2021 21:53:59 -0400 Subject: [PATCH 10/11] add docstrings and add issue to FIXMEs --- compiler/rustc_middle/src/mir/mod.rs | 4 ++-- compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs | 2 ++ .../rustc_mir/src/borrow_check/diagnostics/region_errors.rs | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7c28779ef0b73..f9da80f1bf74e 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2378,7 +2378,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { }; let mut struct_fmt = fmt.debug_struct(&name); - // FIXME: This should be a list of capture names/places + // FIXME(project-rfc-2229#48): This should be a list of capture names/places if let Some(upvars) = tcx.upvars_mentioned(def_id) { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); @@ -2398,7 +2398,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { let name = format!("[generator@{:?}]", tcx.hir().span(hir_id)); let mut struct_fmt = fmt.debug_struct(&name); - // FIXME: This should be a list of capture names/places + // FIXME(project-rfc-2229#48): This should be a list of capture names/places if let Some(upvars) = tcx.upvars_mentioned(def_id) { for (&var_id, place) in iter::zip(upvars.keys(), places) { let var_name = tcx.hir().name(var_id); diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs index 3a80bc3d18138..1bb8c7ebe5afd 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/mod.rs @@ -608,6 +608,7 @@ impl UseSpans<'_> { } } + /// Returns the span of `self`, in the case of a `ClosureUse` returns the `path_span` pub(super) fn var_or_use_path_span(self) -> Span { match self { UseSpans::ClosureUse { path_span: span, .. } @@ -620,6 +621,7 @@ impl UseSpans<'_> { } } + /// Returns the span of `self`, in the case of a `ClosureUse` returns the `capture_kind_span` pub(super) fn var_or_use(self) -> Span { match self { UseSpans::ClosureUse { capture_kind_span: span, .. } diff --git a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs index c3f781c0e9e30..8665ef06126a1 100644 --- a/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs +++ b/compiler/rustc_mir/src/borrow_check/diagnostics/region_errors.rs @@ -385,7 +385,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label(*span, message); - // FIXME: This should store a captured_place not a hir id + // FIXME(project-rfc-2229#48): This should store a captured_place not a hir id if let ReturnConstraint::ClosureUpvar(upvar) = kind { let def_id = match self.regioncx.universal_regions().defining_ty { DefiningTy::Closure(def_id, _) => def_id, From 404cc33eda58cb8c9a8d8e691df5698f50e69a02 Mon Sep 17 00:00:00 2001 From: Chris Pardy Date: Sun, 2 May 2021 04:01:45 -0400 Subject: [PATCH 11/11] fix nll test stderr --- src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr b/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr index 4c271a3916a69..c16a6f8585b69 100644 --- a/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr +++ b/src/test/ui/regions/regions-addr-of-upvar-self.nll.stderr @@ -23,7 +23,7 @@ error[E0597]: `self` does not live long enough LL | let _f = || { | -- value captured here LL | let p: &'static mut usize = &mut self.food; - | ------------------ ^^^^ borrowed value does not live long enough + | ------------------ ^^^^^^^^^ borrowed value does not live long enough | | | type annotation requires that `self` is borrowed for `'static` ...