From f4799b8709439a53502ac45c8bc694047de26c38 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 25 Jan 2022 14:26:50 +0100 Subject: [PATCH 01/13] debuginfo: Make some helper functions in rustc_codegen_llvm::debuginfo::metadata more generally applicable. --- .../src/debuginfo/metadata.rs | 78 +++++++++++++------ 1 file changed, 54 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 1266b540aaeb1..416a087dcc884 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -351,14 +351,15 @@ impl<'ll, 'tcx> RecursiveTypeDescription<'ll, 'tcx> { // ... then create the member descriptions ... let member_descriptions = member_description_factory.create_member_descriptions(cx); + let type_params = compute_type_parameters(cx, unfinished_type); // ... and attach them to the stub to complete it. set_members_of_composite_type( cx, - unfinished_type, member_holding_stub, member_descriptions, None, + type_params, ); MetadataCreationResult::new(metadata_stub, true) } @@ -983,7 +984,17 @@ fn foreign_type_metadata<'ll, 'tcx>( debug!("foreign_type_metadata: {:?}", t); let name = compute_debuginfo_type_name(cx.tcx, t, false); - create_struct_stub(cx, t, &name, unique_type_id, NO_SCOPE_METADATA, DIFlags::FlagZero) + let (size, align) = cx.size_and_align_of(t); + create_struct_stub( + cx, + size, + align, + &name, + unique_type_id, + NO_SCOPE_METADATA, + DIFlags::FlagZero, + None, + ) } fn param_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { @@ -1299,14 +1310,17 @@ fn prepare_struct_metadata<'ll, 'tcx>( }; let containing_scope = get_namespace_for_item(cx, struct_def_id); + let (size, align) = cx.size_and_align_of(struct_type); let struct_metadata_stub = create_struct_stub( cx, - struct_type, + size, + align, &struct_name, unique_type_id, Some(containing_scope), DIFlags::FlagZero, + None, ); create_and_register_recursive_type_forward_declaration( @@ -1398,15 +1412,18 @@ fn prepare_tuple_metadata<'ll, 'tcx>( unique_type_id: UniqueTypeId, containing_scope: Option<&'ll DIScope>, ) -> RecursiveTypeDescription<'ll, 'tcx> { + let (size, align) = cx.size_and_align_of(tuple_type); let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false); let struct_stub = create_struct_stub( cx, - tuple_type, + size, + align, &tuple_name[..], unique_type_id, containing_scope, DIFlags::FlagZero, + None, ); create_and_register_recursive_type_forward_declaration( @@ -1581,13 +1598,14 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { describe_enum_variant(cx, self.layout, variant_info, self_metadata); let member_descriptions = member_description_factory.create_member_descriptions(cx); + let type_params = compute_type_parameters(cx, self.enum_type); set_members_of_composite_type( cx, - self.enum_type, variant_type_metadata, member_descriptions, Some(&self.common_members), + type_params, ); vec![MemberDescription { name: variant_info.variant_name(), @@ -1648,13 +1666,14 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { let member_descriptions = member_desc_factory.create_member_descriptions(cx); + let type_params = compute_type_parameters(cx, self.enum_type); set_members_of_composite_type( cx, - self.enum_type, variant_type_metadata, member_descriptions, Some(&self.common_members), + type_params, ); MemberDescription { @@ -1777,13 +1796,14 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { ); let member_descriptions = member_desc_factory.create_member_descriptions(cx); + let type_params = compute_type_parameters(cx, self.enum_type); set_members_of_composite_type( cx, - self.enum_type, variant_type_metadata, member_descriptions, Some(&self.common_members), + type_params, ); let (size, align) = @@ -1823,13 +1843,14 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { let member_descriptions = member_desc_factory.create_member_descriptions(cx); + let type_params = compute_type_parameters(cx, self.enum_type); set_members_of_composite_type( cx, - self.enum_type, variant_type_metadata, member_descriptions, Some(&self.common_members), + type_params, ); let niche_value = calculate_niche_value(i); @@ -1965,13 +1986,18 @@ fn describe_enum_variant<'ll, 'tcx>( .type_map .borrow_mut() .get_unique_type_id_of_enum_variant(cx, layout.ty, variant_name); + + let (size, align) = cx.size_and_align_of(layout.ty); + create_struct_stub( cx, - layout.ty, + size, + align, variant_name, unique_type_id, Some(containing_scope), DIFlags::FlagZero, + None, ) }); @@ -2308,22 +2334,27 @@ fn composite_type_metadata<'ll, 'tcx>( member_descriptions: Vec>, containing_scope: Option<&'ll DIScope>, ) -> &'ll DICompositeType { + let (size, align) = cx.size_and_align_of(composite_type); + // Create the (empty) struct metadata node ... let composite_type_metadata = create_struct_stub( cx, - composite_type, + size, + align, composite_type_name, composite_type_unique_id, containing_scope, DIFlags::FlagZero, + None, ); + // ... and immediately create and add the member descriptions. set_members_of_composite_type( cx, - composite_type, composite_type_metadata, member_descriptions, None, + compute_type_parameters(cx, composite_type), ); composite_type_metadata @@ -2331,10 +2362,10 @@ fn composite_type_metadata<'ll, 'tcx>( fn set_members_of_composite_type<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, - composite_type: Ty<'tcx>, composite_type_metadata: &'ll DICompositeType, member_descriptions: Vec>, common_members: Option<&Vec>>, + type_params: &'ll DIArray, ) { // In some rare cases LLVM metadata uniquing would lead to an existing type // description being used instead of a new one created in @@ -2361,13 +2392,12 @@ fn set_members_of_composite_type<'ll, 'tcx>( member_metadata.extend(other_members.iter()); } - let type_params = compute_type_parameters(cx, composite_type); unsafe { - let type_array = create_DIArray(DIB(cx), &member_metadata); + let field_array = create_DIArray(DIB(cx), &member_metadata); llvm::LLVMRustDICompositeTypeReplaceArrays( DIB(cx), composite_type_metadata, - Some(type_array), + Some(field_array), Some(type_params), ); } @@ -2420,14 +2450,14 @@ fn compute_type_parameters<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) - /// with `set_members_of_composite_type()`. fn create_struct_stub<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, - struct_type: Ty<'tcx>, - struct_type_name: &str, + size: Size, + align: Align, + type_name: &str, unique_type_id: UniqueTypeId, containing_scope: Option<&'ll DIScope>, flags: DIFlags, + vtable_holder: Option<&'ll DIType>, ) -> &'ll DICompositeType { - let (struct_size, struct_align) = cx.size_and_align_of(struct_type); - let type_map = debug_context(cx).type_map.borrow(); let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id); @@ -2440,17 +2470,17 @@ fn create_struct_stub<'ll, 'tcx>( llvm::LLVMRustDIBuilderCreateStructType( DIB(cx), containing_scope, - struct_type_name.as_ptr().cast(), - struct_type_name.len(), + type_name.as_ptr().cast(), + type_name.len(), unknown_file_metadata(cx), UNKNOWN_LINE_NUMBER, - struct_size.bits(), - struct_align.bits() as u32, + size.bits(), + align.bits() as u32, flags, None, empty_array, 0, - None, + vtable_holder, unique_type_id.as_ptr().cast(), unique_type_id.len(), ) From fc7f419a63e4c98a928729d0ad59c426ccb84963 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 25 Jan 2022 14:34:34 +0100 Subject: [PATCH 02/13] debuginfo: Bring back DW_AT_containing_type for vtables after it has accidentally been removed in https://github.com/rust-lang/rust/pull/89597. Also describe vtables as structs with a field for each entry. --- .../src/debuginfo/metadata.rs | 101 ++++++++++++++++-- .../src/debuginfo/type_names.rs | 21 +++- src/test/codegen/debug-vtable.rs | 35 +++++- .../debuginfo-generic-closure-env-names.rs | 40 ++++--- 4 files changed, 158 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 416a087dcc884..c367e6ed670ea 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -21,6 +21,7 @@ use crate::value::Value; use cstr::cstr; use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo; +use rustc_codegen_ssa::debuginfo::type_names::VTableNameKind; use rustc_codegen_ssa::traits::*; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; @@ -276,6 +277,12 @@ impl<'ll, 'tcx> TypeMap<'ll, 'tcx> { ) -> String { format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id)) } + + /// Gets the `UniqueTypeId` for the type of a vtable. + fn get_unique_type_id_of_vtable_type(&mut self, vtable_type_name: &str) -> UniqueTypeId { + let interner_key = self.unique_id_interner.intern(vtable_type_name); + interner_key + } } /// A description of some recursive type. It can either be already finished (as @@ -2586,6 +2593,14 @@ pub fn create_global_var_metadata<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, g } /// Generates LLVM debuginfo for a vtable. +/// +/// The vtable type looks like a struct with a field for each function pointer and super-trait +/// pointer it contains (plus the `size` and `align` fields). +/// +/// Except for `size`, `align`, and `drop_in_place`, the field names don't try to mirror +/// the name of the method they implement. This can be implemented in the future once there +/// is a proper disambiguation scheme for dealing with methods from different traits that have +/// the same name. fn vtable_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>, @@ -2602,16 +2617,79 @@ fn vtable_type_metadata<'ll, 'tcx>( COMMON_VTABLE_ENTRIES }; - // FIXME: We describe the vtable as an array of *const () pointers. The length of the array is - // correct - but we could create a more accurate description, e.g. by describing it - // as a struct where each field has a name that corresponds to the name of the method - // it points to. - // However, this is not entirely straightforward because there might be multiple - // methods with the same name if the vtable is for multiple traits. So for now we keep - // things simple instead of adding some ad-hoc disambiguation scheme. - let vtable_type = tcx.mk_array(tcx.mk_imm_ptr(tcx.types.unit), vtable_entries.len() as u64); + // All function pointers are described as opaque pointers. This could be improved in the future + // by describing them as actual function pointers. + let void_pointer_ty = tcx.mk_imm_ptr(tcx.types.unit); + let void_pointer_type_debuginfo = type_metadata(cx, void_pointer_ty); + let usize_debuginfo = type_metadata(cx, tcx.types.usize); + let (pointer_size, pointer_align) = cx.size_and_align_of(void_pointer_ty); + // If `usize` is not pointer-sized and -aligned then the size and alignment computations + // for the vtable as a whole would be wrong. Let's make sure this holds even on weird + // platforms. + assert_eq!(cx.size_and_align_of(tcx.types.usize), (pointer_size, pointer_align)); + + let vtable_type_name = + compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::Type); + let unique_type_id = debug_context(cx) + .type_map + .borrow_mut() + .get_unique_type_id_of_vtable_type(&vtable_type_name); + let size = pointer_size * vtable_entries.len() as u64; + + // This gets mapped to a DW_AT_containing_type attribute which allows GDB to correlate + // the vtable to the type it is for. + let vtable_holder = type_metadata(cx, ty); + + let vtable_type_metadata = create_struct_stub( + cx, + size, + pointer_align, + &vtable_type_name, + unique_type_id, + NO_SCOPE_METADATA, + DIFlags::FlagArtificial, + Some(vtable_holder), + ); + + // Create a field for each entry in the vtable. + let fields: Vec<_> = vtable_entries + .iter() + .enumerate() + .filter_map(|(index, vtable_entry)| { + let (field_name, field_type) = match vtable_entry { + ty::VtblEntry::MetadataDropInPlace => { + ("drop_in_place".to_string(), void_pointer_type_debuginfo) + } + ty::VtblEntry::Method(_) => { + // Note: This code does not try to give a proper name to each method + // because their might be multiple methods with the same name + // (coming from different traits). + (format!("__method{}", index), void_pointer_type_debuginfo) + } + ty::VtblEntry::TraitVPtr(_) => { + (format!("__super_trait_ptr{}", index), void_pointer_type_debuginfo) + } + ty::VtblEntry::MetadataAlign => ("align".to_string(), usize_debuginfo), + ty::VtblEntry::MetadataSize => ("size".to_string(), usize_debuginfo), + ty::VtblEntry::Vacant => return None, + }; + + Some(MemberDescription { + name: field_name, + type_metadata: field_type, + offset: pointer_size * index as u64, + size: pointer_size, + align: pointer_align, + flags: DIFlags::FlagZero, + discriminant: None, + source_info: None, + }) + }) + .collect(); - type_metadata(cx, vtable_type) + let type_params = create_DIArray(DIB(cx), &[]); + set_members_of_composite_type(cx, vtable_type_metadata, fields, None, type_params); + vtable_type_metadata } /// Creates debug information for the given vtable, which is for the @@ -2633,11 +2711,12 @@ pub fn create_vtable_metadata<'ll, 'tcx>( return; } - let vtable_name = compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref); + let vtable_name = + compute_debuginfo_vtable_name(cx.tcx, ty, poly_trait_ref, VTableNameKind::GlobalVariable); let vtable_type = vtable_type_metadata(cx, ty, poly_trait_ref); + let linkage_name = ""; unsafe { - let linkage_name = ""; llvm::LLVMRustDIBuilderCreateStaticVariable( DIB(cx), NO_SCOPE_METADATA, diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 831c34d8f1f60..c1a378d74b285 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -469,7 +469,14 @@ fn push_debuginfo_type_name<'tcx>( } } -/// Computes a name for the global variable storing a vtable. +pub enum VTableNameKind { + // Is the name for const/static holding the vtable? + GlobalVariable, + // Is the name for the type of the vtable? + Type, +} + +/// Computes a name for the global variable storing a vtable (or the type of that global variable). /// /// The name is of the form: /// @@ -478,10 +485,15 @@ fn push_debuginfo_type_name<'tcx>( /// or, when generating C++-like names: /// /// `impl$::vtable$` +/// +/// If `kind` is `VTableNameKind::Type` then the last component is `{vtable_ty}` instead of just +/// `{vtable}`, so that the type and the corresponding global variable get assigned different +/// names. pub fn compute_debuginfo_vtable_name<'tcx>( tcx: TyCtxt<'tcx>, t: Ty<'tcx>, trait_ref: Option>, + kind: VTableNameKind, ) -> String { let cpp_like_debuginfo = cpp_like_debuginfo(tcx); @@ -514,7 +526,12 @@ pub fn compute_debuginfo_vtable_name<'tcx>( push_close_angle_bracket(cpp_like_debuginfo, &mut vtable_name); - let suffix = if cpp_like_debuginfo { "::vtable$" } else { "::{vtable}" }; + let suffix = match (cpp_like_debuginfo, kind) { + (true, VTableNameKind::GlobalVariable) => "::vtable$", + (false, VTableNameKind::GlobalVariable) => "::{vtable}", + (true, VTableNameKind::Type) => "::vtable_type$", + (false, VTableNameKind::Type) => "::{vtable_type}", + }; vtable_name.reserve_exact(suffix.len()); vtable_name.push_str(suffix); diff --git a/src/test/codegen/debug-vtable.rs b/src/test/codegen/debug-vtable.rs index 35fd275fd2897..b9cb4f93d07d8 100644 --- a/src/test/codegen/debug-vtable.rs +++ b/src/test/codegen/debug-vtable.rs @@ -9,19 +9,41 @@ // compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0 // ignore-tidy-linelength +// NONMSVC: ![[USIZE:[0-9]+]] = !DIBasicType(name: "usize" +// MSVC: ![[USIZE:[0-9]+]] = !DIDerivedType(tag: DW_TAG_typedef, name: "usize" +// NONMSVC: ![[PTR:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const ()" +// MSVC: ![[PTR:[0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, name: "ptr_const$ >" + // NONMSVC: !DIGlobalVariable(name: "::{vtable}" // MSVC: !DIGlobalVariable(name: "impl$::vtable$" -// NONMSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const ()", -// MSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "ptr_const$ >", -// CHECK: !DISubrange(count: 5 + +// NONMSVC: ![[VTABLE_TY0:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", {{.*}} size: {{320|160}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}} vtableHolder: ![[FOO_TYPE:[0-9]+]], +// MSVC: ![[VTABLE_TY0:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$::vtable_type$", {{.*}} size: {{320|160}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}} vtableHolder: ![[FOO_TYPE:[0-9]+]], +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "drop_in_place", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "size", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{64|32}}) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}}) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__method3", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}, offset: {{192|96}}) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__method4", scope: ![[VTABLE_TY0]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}, offset: {{256|128}}) +// CHECK: ![[FOO_TYPE]] = !DICompositeType(tag: DW_TAG_structure_type, name: "Foo", // NONMSVC: !DIGlobalVariable(name: ">::{vtable}" // MSVC: !DIGlobalVariable(name: "impl$ >::vtable$" -// CHECK: !DISubrange(count: 4 + +// NONMSVC: ![[VTABLE_TY1:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: ">::{vtable_type}", {{.*}}, size: {{256|128}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]], +// MSVC: ![[VTABLE_TY1:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$ >::vtable_type$", {{.*}}, size: {{256|128}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]], +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "drop_in_place", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "size", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{64|32}}) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}}) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "__method3", scope: ![[VTABLE_TY1]], {{.*}} baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}, offset: {{192|96}}) // NONMSVC: !DIGlobalVariable(name: "::{vtable}" // MSVC: !DIGlobalVariable(name: "impl$::vtable$" -// CHECK: !DISubrange(count: 3 + +// NONMSVC: ![[VTABLE_TY2:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "::{vtable_type}", {{.*}}, size: {{192|96}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]], +// MSVC: ![[VTABLE_TY2:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$::vtable_type$", {{.*}}, size: {{192|96}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}}, vtableHolder: ![[FOO_TYPE]], +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "drop_in_place", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[PTR]], size: {{64|32}}, align: {{64|32}}) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "size", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{64|32}}) +// CHECK: !DIDerivedType(tag: DW_TAG_member, name: "align", scope: ![[VTABLE_TY2]], {{.*}}, baseType: ![[USIZE]], size: {{64|32}}, align: {{64|32}}, offset: {{128|64}}) // NONMSVC: !DIGlobalVariable(name: ">)>>::{vtable}" // MSVC: !DIGlobalVariable(name: "impl$,assoc$ > > > > >, {{.*}}, {{.*}}, Some> > > >::vtable$" @@ -34,6 +56,9 @@ #![crate_type = "lib"] +// Force emission for debuginfo for usize and *const() early.. +pub static mut XYZ: Option<(usize, *const ())> = None; + pub struct Foo; pub trait SomeTrait { diff --git a/src/test/codegen/debuginfo-generic-closure-env-names.rs b/src/test/codegen/debuginfo-generic-closure-env-names.rs index 6e5ac95126130..ad59f740b567f 100644 --- a/src/test/codegen/debuginfo-generic-closure-env-names.rs +++ b/src/test/codegen/debuginfo-generic-closure-env-names.rs @@ -17,35 +17,34 @@ // compile-flags: -Cdebuginfo=2 --edition 2021 -Copt-level=0 -Csymbol-mangling-version=v0 - -// CHECK: [[non_generic_closure_NAMESPACE:!.*]] = !DINamespace(name: "non_generic_closure" -// CHECK: [[function_containing_closure_NAMESPACE:!.*]] = !DINamespace(name: "function_containing_closure" -// CHECK: [[generic_async_function_NAMESPACE:!.*]] = !DINamespace(name: "generic_async_function" -// CHECK: [[generic_async_block_NAMESPACE:!.*]] = !DINamespace(name: "generic_async_block" - // non_generic_closure() -// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: [[non_generic_closure_NAMESPACE]] -// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: [[non_generic_closure_NAMESPACE]] +// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], +// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[non_generic_closure_NAMESPACE:[0-9]+]], +// CHECK: ![[non_generic_closure_NAMESPACE]] = !DINamespace(name: "non_generic_closure" + +// CHECK: ![[function_containing_closure_NAMESPACE:[0-9]+]] = !DINamespace(name: "function_containing_closure" +// CHECK: ![[generic_async_function_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_function" +// CHECK: ![[generic_async_block_NAMESPACE:[0-9]+]] = !DINamespace(name: "generic_async_block" // function_containing_closure() -// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: [[function_containing_closure_NAMESPACE]] -// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: [[function_containing_closure_NAMESPACE]] +// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[function_containing_closure_NAMESPACE]] +// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[function_containing_closure_NAMESPACE]] // generic_async_function() -// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[generic_async_function_NAMESPACE]] +// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: ![[generic_async_function_NAMESPACE]] // generic_async_function() -// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: [[generic_async_function_NAMESPACE]] +// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}", scope: ![[generic_async_function_NAMESPACE]] // generic_async_block() -// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}", scope: [[generic_async_block_NAMESPACE]] +// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}", scope: ![[generic_async_block_NAMESPACE]] // generic_async_block() -// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}", scope: [[generic_async_block_NAMESPACE]] +// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}", scope: ![[generic_async_block_NAMESPACE]] // function_containing_closure() -// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: [[function_containing_closure_NAMESPACE]] -// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: [[function_containing_closure_NAMESPACE]] +// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}", scope: ![[function_containing_closure_NAMESPACE]] +// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0", scope: ![[function_containing_closure_NAMESPACE]] #![crate_type = "lib"] @@ -54,15 +53,14 @@ use std::future::Future; pub struct Foo; pub fn non_generic_closure(x: Foo) -> Box Foo> { - // This static only exists to trigger generating the namespace debuginfo for - // `function_containing_closure` at a predictable, early point, which makes - // writing the FileCheck tests above simpler. - static _X: u8 = 0; return Box::new(move || x); } fn function_containing_closure(x: T) -> impl FnOnce() -> T { - static _X: u8 = 0; // Same as above + // This static only exists to trigger generating the namespace debuginfo for + // `function_containing_closure` at a predictable, early point, which makes + // writing the FileCheck tests above simpler. + static _X: u8 = 0; return move || x; } From 03733ca65a09a9b54b2c2a674e4145b165bd1cab Mon Sep 17 00:00:00 2001 From: cynecx Date: Mon, 22 Nov 2021 13:14:54 +0100 Subject: [PATCH 03/13] `#[used(linker)]` attribute (https://github.com/dtolnay/linkme/issues/41) --- compiler/rustc_codegen_gcc/src/consts.rs | 2 +- compiler/rustc_codegen_llvm/src/consts.rs | 9 +++++ compiler/rustc_feature/src/active.rs | 2 + compiler/rustc_feature/src/builtin_attrs.rs | 2 +- .../src/middle/codegen_fn_attrs.rs | 2 + compiler/rustc_passes/src/dead.rs | 5 ++- compiler/rustc_span/src/symbol.rs | 3 ++ compiler/rustc_typeck/src/collect.rs | 37 ++++++++++++++++++- 8 files changed, 58 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index ba4589bd81025..ddc2b88191bd0 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -144,7 +144,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> { // TODO(antoyo): set link section. } - if attrs.flags.contains(CodegenFnAttrFlags::USED) { + if attrs.flags.contains(CodegenFnAttrFlags::USED) || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { self.add_used_global(global.to_rvalue()); } } diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index d43c7c6065179..6707de933522b 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -522,6 +522,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { } if attrs.flags.contains(CodegenFnAttrFlags::USED) { + // `USED` and `USED_LINKER` can't be used together. + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); + // The semantics of #[used] in Rust only require the symbol to make it into the // object file. It is explicitly allowed for the linker to strip the symbol if it // is dead. As such, use llvm.compiler.used instead of llvm.used. @@ -530,6 +533,12 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> { // in some versions of the gold linker. self.add_compiler_used_global(g); } + if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { + // `USED` and `USED_LINKER` can't be used together. + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED)); + + self.add_used_global(g); + } } } diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index bfe2459dc8dc1..d958a14afabb9 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -533,6 +533,8 @@ declare_features! ( /// /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. (active, untagged_unions, "1.13.0", Some(55149), None), + /// Allows using the `#[used(retain)]` attribute. + (active, used_with_arg, "1.60.0", None, None), /// Allows `extern "wasm" fn` (active, wasm_abi, "1.53.0", Some(83788), None), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 3933746c319ec..739e545043842 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -324,7 +324,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(no_mangle, Normal, template!(Word), WarnFollowing), - ungated!(used, Normal, template!(Word), WarnFollowing), + ungated!(used, Normal, template!(Word, List: "used"), WarnFollowing), // Limits: ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index b054d21adaa13..54eb2dc9e2890 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -89,6 +89,8 @@ bitflags! { /// the MIR `InstrumentCoverage` pass and not added to the coverage map /// during codegen. const NO_COVERAGE = 1 << 15; + /// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function. + const USED_LINKER = 1 << 16; } } diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index e7e56711b33c5..dc3ce1afa3361 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -466,7 +466,10 @@ fn has_allow_dead_code_or_lang_attr(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { // #[used], #[no_mangle], #[export_name], etc also keeps the item alive // forcefully, e.g., for placing it in a specific section. - if cg_attrs.contains_extern_indicator() || cg_attrs.flags.contains(CodegenFnAttrFlags::USED) { + if cg_attrs.contains_extern_indicator() + || cg_attrs.flags.contains(CodegenFnAttrFlags::USED) + || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) + { return true; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 18627cd2c099d..4a1fd476b8c0a 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -449,6 +449,7 @@ symbols! { compare_exchange_weak, compile_error, compile_error_macro, + compiler, compiler_builtins, compiler_fence, concat, @@ -815,6 +816,7 @@ symbols! { link_ordinal, link_section, linkage, + linker, lint_reasons, literal, load, @@ -1458,6 +1460,7 @@ symbols! { use_extern_macros, use_nested_groups, used, + used_with_arg, usize, v1, va_arg, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index cf519a9ab3274..4a3c477021cf4 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2849,7 +2849,42 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs { } else if attr.has_name(sym::rustc_std_internal_symbol) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL; } else if attr.has_name(sym::used) { - codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; + let inner = attr.meta_item_list(); + match inner.as_deref() { + Some([item]) if item.has_name(sym::linker) => { + if !tcx.features().used_with_arg { + feature_err( + &tcx.sess.parse_sess, + sym::used_with_arg, + attr.span, + "`#[used(linker)]` is currently unstable", + ) + .emit(); + } + codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER; + } + Some([item]) if item.has_name(sym::compiler) => { + if !tcx.features().used_with_arg { + feature_err( + &tcx.sess.parse_sess, + sym::used_with_arg, + attr.span, + "`#[used(compiler)]` is currently unstable", + ) + .emit(); + } + codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED; + } + Some(_) => { + tcx.sess + .struct_span_err( + attr.span, + "expected `used`, `used(compiler)` or `used(linker)`", + ) + .emit(); + } + None => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED, + } } else if attr.has_name(sym::cmse_nonsecure_entry) { if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) { struct_span_err!( From e075586d4fd428374a788eecc391e23ec4a17b46 Mon Sep 17 00:00:00 2001 From: cynecx Date: Mon, 7 Feb 2022 01:21:23 +0100 Subject: [PATCH 04/13] add tests and fix comments --- compiler/rustc_feature/src/active.rs | 4 ++-- compiler/rustc_feature/src/builtin_attrs.rs | 2 +- src/test/codegen/used_with_arg.rs | 12 ++++++++++++ .../feature-gate-used_with_arg.rs | 7 +++++++ .../feature-gate-used_with_arg.stderr | 19 +++++++++++++++++++ 5 files changed, 41 insertions(+), 3 deletions(-) create mode 100644 src/test/codegen/used_with_arg.rs create mode 100644 src/test/ui/feature-gates/feature-gate-used_with_arg.rs create mode 100644 src/test/ui/feature-gates/feature-gate-used_with_arg.stderr diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index d958a14afabb9..0908e9d1ef905 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -533,8 +533,8 @@ declare_features! ( /// /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. (active, untagged_unions, "1.13.0", Some(55149), None), - /// Allows using the `#[used(retain)]` attribute. - (active, used_with_arg, "1.60.0", None, None), + /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute. + (active, used_with_arg, "1.60.0", Some(00000), None), /// Allows `extern "wasm" fn` (active, wasm_abi, "1.53.0", Some(83788), None), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 739e545043842..13b482cb469bd 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -324,7 +324,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding), ungated!(no_mangle, Normal, template!(Word), WarnFollowing), - ungated!(used, Normal, template!(Word, List: "used"), WarnFollowing), + ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing), // Limits: ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing), diff --git a/src/test/codegen/used_with_arg.rs b/src/test/codegen/used_with_arg.rs new file mode 100644 index 0000000000000..cd759b167c0df --- /dev/null +++ b/src/test/codegen/used_with_arg.rs @@ -0,0 +1,12 @@ +// compile-flags: -O + +#![crate_type = "lib"] +#![feature(used_with_arg)] + +// CHECK: @llvm.used = appending global [1 x i8*] +#[used(linker)] +static mut USED_LINKER: [usize; 1] = [0]; + +// CHECK-NEXT: @llvm.compiler.used = appending global [1 x i8*] +#[used(compiler)] +static mut USED_COMPILER: [usize; 1] = [0]; diff --git a/src/test/ui/feature-gates/feature-gate-used_with_arg.rs b/src/test/ui/feature-gates/feature-gate-used_with_arg.rs new file mode 100644 index 0000000000000..1c8f01bdef116 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-used_with_arg.rs @@ -0,0 +1,7 @@ +#[used(linker)] //~ ERROR `#[used(linker)]` is currently unstable +static mut USED_LINKER: [usize; 1] = [0]; + +#[used(compiler)] //~ ERROR `#[used(compiler)]` is currently unstable +static mut USED_COMPILER: [usize; 1] = [0]; + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr b/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr new file mode 100644 index 0000000000000..aaf4ceaf79537 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr @@ -0,0 +1,19 @@ +error[E0658]: `#[used(linker)]` is currently unstable + --> $DIR/feature-gate-used_with_arg.rs:1:1 + | +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + | + = help: add `#![feature(used_with_arg)]` to the crate attributes to enable + +error[E0658]: `#[used(compiler)]` is currently unstable + --> $DIR/feature-gate-used_with_arg.rs:4:1 + | +LL | #[used(compiler)] + | ^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(used_with_arg)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. From 475e4eeb6557af820ee2b48f213f178eca5e11ce Mon Sep 17 00:00:00 2001 From: Jeremy Banks <_@jeremy.ca> Date: Mon, 7 Feb 2022 23:40:17 +0000 Subject: [PATCH 05/13] Remove obsolete no-op #[main] attribute from compiler. --- compiler/rustc_feature/src/builtin_attrs.rs | 1 - src/test/ui/attributes/main-removed-1.rs | 2 ++ src/test/ui/attributes/main-removed-1.stderr | 10 ++++++++++ .../ui/attributes/main-removed-2/auxiliary/tokyo.rs | 12 ++++++++++++ src/test/ui/attributes/main-removed-2/main.rs | 11 +++++++++++ 5 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/attributes/main-removed-1.rs create mode 100644 src/test/ui/attributes/main-removed-1.stderr create mode 100644 src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs create mode 100644 src/test/ui/attributes/main-removed-2/main.rs diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index cb2562d09a525..b224c64ece7f6 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -339,7 +339,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ ), // Entry point: - ungated!(main, Normal, template!(Word), WarnFollowing), ungated!(start, Normal, template!(Word), WarnFollowing), ungated!(no_start, CrateLevel, template!(Word), WarnFollowing), ungated!(no_main, CrateLevel, template!(Word), WarnFollowing), diff --git a/src/test/ui/attributes/main-removed-1.rs b/src/test/ui/attributes/main-removed-1.rs new file mode 100644 index 0000000000000..0e887469d4466 --- /dev/null +++ b/src/test/ui/attributes/main-removed-1.rs @@ -0,0 +1,2 @@ +#[main] //~ ERROR cannot find attribute `main` in this scope +fn main() {} diff --git a/src/test/ui/attributes/main-removed-1.stderr b/src/test/ui/attributes/main-removed-1.stderr new file mode 100644 index 0000000000000..2422c5c3b6239 --- /dev/null +++ b/src/test/ui/attributes/main-removed-1.stderr @@ -0,0 +1,10 @@ +error: cannot find attribute `main` in this scope + --> $DIR/main-removed-1.rs:1:3 + | +LL | #[main] + | ^^^^ + | + = note: `main` is in scope, but it is a function, not an attribute + +error: aborting due to previous error + diff --git a/src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs b/src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs new file mode 100644 index 0000000000000..196b5be2dd086 --- /dev/null +++ b/src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs @@ -0,0 +1,12 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn main(_: TokenStream, input: TokenStream) -> TokenStream { + "fn main() { println!(\"Hello Tokyo!\"); }".parse().unwrap() +} diff --git a/src/test/ui/attributes/main-removed-2/main.rs b/src/test/ui/attributes/main-removed-2/main.rs new file mode 100644 index 0000000000000..e8fecf825fa83 --- /dev/null +++ b/src/test/ui/attributes/main-removed-2/main.rs @@ -0,0 +1,11 @@ +// run-pass +// aux-build:tokyo.rs +// compile-flags:--extern tokyo +// edition:2021 + +use tokyo::main; + +#[main] +fn main() { + panic!("the #[main] macro should replace this with non-panicking code") +} From ed21805aee9ad1abed5dc5157ac568e95fd84afb Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 8 Feb 2022 15:31:09 +0100 Subject: [PATCH 06/13] debuginfo: Bring back DW_AT_containing_type for vtables -- address review comments --- compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | 4 +++- compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index c367e6ed670ea..da997dd98792f 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -2662,11 +2662,13 @@ fn vtable_type_metadata<'ll, 'tcx>( } ty::VtblEntry::Method(_) => { // Note: This code does not try to give a proper name to each method - // because their might be multiple methods with the same name + // because there might be multiple methods with the same name // (coming from different traits). (format!("__method{}", index), void_pointer_type_debuginfo) } ty::VtblEntry::TraitVPtr(_) => { + // Note: In the future we could try to set the type of this pointer + // to the type that we generate for the corresponding vtable. (format!("__super_trait_ptr{}", index), void_pointer_type_debuginfo) } ty::VtblEntry::MetadataAlign => ("align".to_string(), usize_debuginfo), diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index c1a378d74b285..3cb19c0eec624 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -470,7 +470,7 @@ fn push_debuginfo_type_name<'tcx>( } pub enum VTableNameKind { - // Is the name for const/static holding the vtable? + // Is the name for the const/static holding the vtable? GlobalVariable, // Is the name for the type of the vtable? Type, From 78064549bed873fbf324982edcdadf9a89aa555f Mon Sep 17 00:00:00 2001 From: Jacob Hoffman-Andrews Date: Mon, 7 Feb 2022 22:36:51 -0800 Subject: [PATCH 07/13] rustdoc: fix spacing of non-toggled impl blocks We recently removed the "up here" arrows on item-infos, and adjusted vertical spacing so that even without the arrow, it would be visually clear which item the item-info belonged to. The new CSS styles for vertical spacing only applied to toggles, though. This missed non-toggled impl blocks - for instance, those without any methods, like https://doc.rust-lang.org/nightly/std/marker/trait.Send.html#implementors. The result was lists of implementors that were spaced too closely. This PR fixes the spacing by making it apply to non-toggled impl blocks as well. This also fixes an issue where item-infos were displayed too far below their items. That was a result of display: table on .item-info .stab. Changed that to display: inline-block. --- src/librustdoc/html/static/css/rustdoc.css | 5 +++-- src/test/rustdoc-gui/implementors.goml | 4 ++++ src/test/rustdoc-gui/item-info-width.goml | 2 +- src/test/rustdoc-gui/src/test_docs/Cargo.toml | 4 ++++ src/test/rustdoc-gui/src/test_docs/lib.rs | 11 +++++++++++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 6d94c70eadee6..bf2c6635a69c4 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1049,7 +1049,7 @@ body.blur > :not(#help) { } .item-info .stab { - display: table; + display: inline-block; } .stab { padding: 3px; @@ -2047,7 +2047,8 @@ details.rustdoc-toggle[open] > summary.hideme::after { } .method-toggle summary, -.implementors-toggle summary { +.implementors-toggle summary, +.impl { margin-bottom: 0.75em; } diff --git a/src/test/rustdoc-gui/implementors.goml b/src/test/rustdoc-gui/implementors.goml index c9042eb4813ab..6460a917e92d0 100644 --- a/src/test/rustdoc-gui/implementors.goml +++ b/src/test/rustdoc-gui/implementors.goml @@ -14,3 +14,7 @@ assert: ("#implementors-list .impl:nth-child(2) > a.anchor") assert-attribute: ("#implementors-list .impl:nth-child(2)", {"id": "impl-Whatever-1"}) assert-attribute: ("#implementors-list .impl:nth-child(2) > a.anchor", {"href": "#impl-Whatever-1"}) assert: "#implementors-list .impl:nth-child(2) > .code-header.in-band" + +goto: file://|DOC_PATH|/test_docs/struct.HasEmptyTraits.html +compare-elements-position-near-false: ("#impl-EmptyTrait1", "#impl-EmptyTrait2", {"y": 30}) +compare-elements-position-near: ("#impl-EmptyTrait3 h3", "#impl-EmptyTrait3 .item-info", {"y": 30}) diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml index 1c4cf4ddf87f3..7a32d9029103a 100644 --- a/src/test/rustdoc-gui/item-info-width.goml +++ b/src/test/rustdoc-gui/item-info-width.goml @@ -4,5 +4,5 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html size: (1100, 800) // We check that ".item-info" is bigger than its content. assert-css: (".item-info", {"width": "790px"}) -assert-css: (".item-info .stab", {"width": "341px"}) +assert-css: (".item-info .stab", {"width": "340px"}) assert-position: (".item-info .stab", {"x": 295}) diff --git a/src/test/rustdoc-gui/src/test_docs/Cargo.toml b/src/test/rustdoc-gui/src/test_docs/Cargo.toml index 5f527078e79a8..8be819b76e413 100644 --- a/src/test/rustdoc-gui/src/test_docs/Cargo.toml +++ b/src/test/rustdoc-gui/src/test_docs/Cargo.toml @@ -7,3 +7,7 @@ build = "build.rs" [lib] path = "lib.rs" + +[features] +default = ["some-feature"] +some-feature = [] diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index f75de949292a1..2068d1d6f39af 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -260,3 +260,14 @@ impl HeavilyDocumentedUnion { macro_rules! heavily_documented_macro { () => {}; } + +pub trait EmptyTrait1 {} +pub trait EmptyTrait2 {} +pub trait EmptyTrait3 {} + +pub struct HasEmptyTraits{} + +impl EmptyTrait1 for HasEmptyTraits {} +impl EmptyTrait2 for HasEmptyTraits {} +#[doc(cfg(feature = "some-feature"))] +impl EmptyTrait3 for HasEmptyTraits {} From 438826fd1a9a119d00992ede948cdd479431ecbb Mon Sep 17 00:00:00 2001 From: cynecx Date: Tue, 8 Feb 2022 23:51:17 +0100 Subject: [PATCH 08/13] add more tests and make used(linker/compiler) mutually exclusive --- compiler/rustc_passes/src/check_attr.rs | 34 +++++++++++++++++++++++++ compiler/rustc_typeck/src/collect.rs | 1 + src/test/codegen/used_with_arg.rs | 6 ++--- src/test/ui/used_with_arg.rs | 19 ++++++++++++++ src/test/ui/used_with_arg.stderr | 18 +++++++++++++ src/test/ui/used_with_multi_args.rs | 6 +++++ src/test/ui/used_with_multi_args.stderr | 8 ++++++ 7 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/used_with_arg.rs create mode 100644 src/test/ui/used_with_arg.stderr create mode 100644 src/test/ui/used_with_multi_args.rs create mode 100644 src/test/ui/used_with_multi_args.stderr diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ca511f7b814be..479a08e43c01a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1741,12 +1741,46 @@ impl CheckAttrVisitor<'_> { } fn check_used(&self, attrs: &[Attribute], target: Target) { + let mut used_linker_span = None; + let mut used_compiler_span = None; for attr in attrs { if attr.has_name(sym::used) && target != Target::Static { self.tcx .sess .span_err(attr.span, "attribute must be applied to a `static` variable"); } + let inner = attr.meta_item_list(); + match inner.as_deref() { + Some([item]) if item.has_name(sym::linker) => { + if used_linker_span.is_none() { + used_linker_span = Some(attr.span); + } + } + Some([item]) if item.has_name(sym::compiler) => { + if used_compiler_span.is_none() { + used_compiler_span = Some(attr.span); + } + } + Some(_) => { + // This error case is handled in rustc_typeck::collect. + } + None => { + // Default case (compiler) when arg isn't defined. + if used_compiler_span.is_none() { + used_compiler_span = Some(attr.span); + } + } + } + } + if let (Some(linker_span), Some(compiler_span)) = (used_linker_span, used_compiler_span) { + let spans = vec![linker_span, compiler_span]; + self.tcx + .sess + .struct_span_err( + spans, + "`used(compiler)` and `used(linker)` can't be used together", + ) + .emit(); } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 4a3c477021cf4..2a280ff97e96d 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength //! "Collection" is the process of determining the type and other external //! details of each item in Rust. Collection is specifically concerned //! with *inter-procedural* things -- for example, for a function diff --git a/src/test/codegen/used_with_arg.rs b/src/test/codegen/used_with_arg.rs index cd759b167c0df..5bff50a40d4e8 100644 --- a/src/test/codegen/used_with_arg.rs +++ b/src/test/codegen/used_with_arg.rs @@ -1,12 +1,10 @@ -// compile-flags: -O - #![crate_type = "lib"] #![feature(used_with_arg)] -// CHECK: @llvm.used = appending global [1 x i8*] +// CHECK: @llvm.used = appending global [1 x i8*]{{.*}}USED_LINKER #[used(linker)] static mut USED_LINKER: [usize; 1] = [0]; -// CHECK-NEXT: @llvm.compiler.used = appending global [1 x i8*] +// CHECK-NEXT: @llvm.compiler.used = appending global [1 x i8*]{{.*}}USED_COMPILER #[used(compiler)] static mut USED_COMPILER: [usize; 1] = [0]; diff --git a/src/test/ui/used_with_arg.rs b/src/test/ui/used_with_arg.rs new file mode 100644 index 0000000000000..ad80ff53f0ef0 --- /dev/null +++ b/src/test/ui/used_with_arg.rs @@ -0,0 +1,19 @@ +#![feature(used_with_arg)] + +#[used(linker)] +static mut USED_LINKER: [usize; 1] = [0]; + +#[used(compiler)] +static mut USED_COMPILER: [usize; 1] = [0]; + +#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together +#[used(linker)] +static mut USED_COMPILER_LINKER2: [usize; 1] = [0]; + +#[used(compiler)] //~ ERROR `used(compiler)` and `used(linker)` can't be used together +#[used(linker)] +#[used(compiler)] +#[used(linker)] +static mut USED_COMPILER_LINKER3: [usize; 1] = [0]; + +fn main() {} diff --git a/src/test/ui/used_with_arg.stderr b/src/test/ui/used_with_arg.stderr new file mode 100644 index 0000000000000..440e5c4a5a020 --- /dev/null +++ b/src/test/ui/used_with_arg.stderr @@ -0,0 +1,18 @@ +error: `used(compiler)` and `used(linker)` can't be used together + --> $DIR/used_with_arg.rs:9:1 + | +LL | #[used(compiler)] + | ^^^^^^^^^^^^^^^^^ +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + +error: `used(compiler)` and `used(linker)` can't be used together + --> $DIR/used_with_arg.rs:13:1 + | +LL | #[used(compiler)] + | ^^^^^^^^^^^^^^^^^ +LL | #[used(linker)] + | ^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/src/test/ui/used_with_multi_args.rs b/src/test/ui/used_with_multi_args.rs new file mode 100644 index 0000000000000..2e17fcfd7a493 --- /dev/null +++ b/src/test/ui/used_with_multi_args.rs @@ -0,0 +1,6 @@ +#![feature(used_with_arg)] + +#[used(compiler, linker)] //~ expected `used`, `used(compiler)` or `used(linker)` +static mut USED_COMPILER_LINKER: [usize; 1] = [0]; + +fn main() {} diff --git a/src/test/ui/used_with_multi_args.stderr b/src/test/ui/used_with_multi_args.stderr new file mode 100644 index 0000000000000..c93aafcfc7cce --- /dev/null +++ b/src/test/ui/used_with_multi_args.stderr @@ -0,0 +1,8 @@ +error: expected `used`, `used(compiler)` or `used(linker)` + --> $DIR/used_with_multi_args.rs:3:1 + | +LL | #[used(compiler, linker)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 933963e10ae8837965f44b7e9748ff135f6c57a5 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 9 Feb 2022 10:59:33 +0100 Subject: [PATCH 09/13] Add tracking issue --- compiler/rustc_feature/src/active.rs | 2 +- src/test/ui/feature-gates/feature-gate-used_with_arg.stderr | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 0908e9d1ef905..c652e54ffe7b8 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -534,7 +534,7 @@ declare_features! ( /// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0. (active, untagged_unions, "1.13.0", Some(55149), None), /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute. - (active, used_with_arg, "1.60.0", Some(00000), None), + (active, used_with_arg, "1.60.0", Some(93798), None), /// Allows `extern "wasm" fn` (active, wasm_abi, "1.53.0", Some(83788), None), // !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! diff --git a/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr b/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr index aaf4ceaf79537..d115bf4e365a7 100644 --- a/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr +++ b/src/test/ui/feature-gates/feature-gate-used_with_arg.stderr @@ -4,6 +4,7 @@ error[E0658]: `#[used(linker)]` is currently unstable LL | #[used(linker)] | ^^^^^^^^^^^^^^^ | + = note: see issue #93798 for more information = help: add `#![feature(used_with_arg)]` to the crate attributes to enable error[E0658]: `#[used(compiler)]` is currently unstable @@ -12,6 +13,7 @@ error[E0658]: `#[used(compiler)]` is currently unstable LL | #[used(compiler)] | ^^^^^^^^^^^^^^^^^ | + = note: see issue #93798 for more information = help: add `#![feature(used_with_arg)]` to the crate attributes to enable error: aborting due to 2 previous errors From 170593313a6ac2206107ec52a0d3bb9cc873a97c Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 9 Feb 2022 11:00:39 +0100 Subject: [PATCH 10/13] Move tests into attributes directory to pacify tidy --- src/test/ui/{ => attributes}/used_with_arg.rs | 0 src/test/ui/{ => attributes}/used_with_arg.stderr | 0 src/test/ui/{ => attributes}/used_with_multi_args.rs | 0 src/test/ui/{ => attributes}/used_with_multi_args.stderr | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/test/ui/{ => attributes}/used_with_arg.rs (100%) rename src/test/ui/{ => attributes}/used_with_arg.stderr (100%) rename src/test/ui/{ => attributes}/used_with_multi_args.rs (100%) rename src/test/ui/{ => attributes}/used_with_multi_args.stderr (100%) diff --git a/src/test/ui/used_with_arg.rs b/src/test/ui/attributes/used_with_arg.rs similarity index 100% rename from src/test/ui/used_with_arg.rs rename to src/test/ui/attributes/used_with_arg.rs diff --git a/src/test/ui/used_with_arg.stderr b/src/test/ui/attributes/used_with_arg.stderr similarity index 100% rename from src/test/ui/used_with_arg.stderr rename to src/test/ui/attributes/used_with_arg.stderr diff --git a/src/test/ui/used_with_multi_args.rs b/src/test/ui/attributes/used_with_multi_args.rs similarity index 100% rename from src/test/ui/used_with_multi_args.rs rename to src/test/ui/attributes/used_with_multi_args.rs diff --git a/src/test/ui/used_with_multi_args.stderr b/src/test/ui/attributes/used_with_multi_args.stderr similarity index 100% rename from src/test/ui/used_with_multi_args.stderr rename to src/test/ui/attributes/used_with_multi_args.stderr From 3d3318b4068cdc0a35e7d18aa91b3dd35ea27c86 Mon Sep 17 00:00:00 2001 From: Titus Date: Wed, 9 Feb 2022 11:26:10 +0100 Subject: [PATCH 11/13] Fix typo in `std::fmt` docs --- library/alloc/src/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index b4d16d74db488..aeb7554f8e914 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -74,7 +74,7 @@ //! identifier '=' expression //! ``` //! -//! For example, the following [`format!`] expressions all use named argument: +//! For example, the following [`format!`] expressions all use named arguments: //! //! ``` //! format!("{argument}", argument = "test"); // => "test" From f43e3a86a7286057a748c731b732200e2ccde466 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 1 Dec 2021 18:50:46 -0800 Subject: [PATCH 12/13] Allow substitutions in `rustc_on_unimplemented` predicate --- compiler/rustc_span/src/symbol.rs | 3 ++ .../src/traits/on_unimplemented.rs | 48 ++++++++++++++----- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 70fad4911f9c7..ef0a1792d58af 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -668,6 +668,7 @@ symbols! { fill, finish, flags, + float, float_to_int_unchecked, floorf32, floorf64, @@ -771,6 +772,8 @@ symbols! { inline_const_pat, inout, instruction_set, + integer_: "integer", + integral, intel, into_future, into_iter, diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 6b20476b95594..bdf677a63b632 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -62,6 +62,10 @@ impl<'tcx> OnUnimplementedDirective { let mut errored = false; let mut item_iter = items.iter(); + let parse_value = |value_str| { + OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some) + }; + let condition = if is_root { None } else { @@ -86,7 +90,14 @@ impl<'tcx> OnUnimplementedDirective { None, ) })?; - attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |_| true); + attr::eval_condition(cond, &tcx.sess.parse_sess, Some(tcx.features()), &mut |item| { + if let Some(symbol) = item.value_str() { + if parse_value(symbol).is_err() { + errored = true; + } + } + true + }); Some(cond.clone()) }; @@ -97,10 +108,6 @@ impl<'tcx> OnUnimplementedDirective { let mut subcommands = vec![]; let mut append_const_msg = None; - let parse_value = |value_str| { - OnUnimplementedFormatString::try_parse(tcx, trait_def_id, value_str, span).map(Some) - }; - for item in item_iter { if item.has_name(sym::message) && message.is_none() { if let Some(message_) = item.value_str() { @@ -221,6 +228,9 @@ impl<'tcx> OnUnimplementedDirective { let mut append_const_msg = None; info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options); + let options_map: FxHashMap = + options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); + for command in self.subcommands.iter().chain(Some(self)).rev() { if let Some(ref condition) = command.condition { if !attr::eval_condition( @@ -229,7 +239,11 @@ impl<'tcx> OnUnimplementedDirective { Some(tcx.features()), &mut |c| { c.ident().map_or(false, |ident| { - options.contains(&(ident.name, c.value_str().map(|s| s.to_string()))) + let value = c.value_str().map(|s| { + OnUnimplementedFormatString(s).format(tcx, trait_ref, &options_map) + }); + + options.contains(&(ident.name, value)) }) }, ) { @@ -257,13 +271,11 @@ impl<'tcx> OnUnimplementedDirective { append_const_msg = command.append_const_msg.clone(); } - let options: FxHashMap = - options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect(); OnUnimplementedNote { - label: label.map(|l| l.format(tcx, trait_ref, &options)), - message: message.map(|m| m.format(tcx, trait_ref, &options)), - note: note.map(|n| n.format(tcx, trait_ref, &options)), - enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options)), + label: label.map(|l| l.format(tcx, trait_ref, &options_map)), + message: message.map(|m| m.format(tcx, trait_ref, &options_map)), + note: note.map(|n| n.format(tcx, trait_ref, &options_map)), + enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options_map)), append_const_msg, } } @@ -306,6 +318,12 @@ impl<'tcx> OnUnimplementedFormatString { Position::ArgumentNamed(s) if s == sym::from_desugaring => (), // `{ItemContext}` is allowed Position::ArgumentNamed(s) if s == sym::ItemContext => (), + // `{integral}` and `{integer}` and `{float}` are allowed + Position::ArgumentNamed(s) + if s == sym::integral || s == sym::integer_ || s == sym::float => + { + () + } // So is `{A}` if A is a type parameter Position::ArgumentNamed(s) => { match generics.params.iter().find(|param| param.name == s) { @@ -385,6 +403,12 @@ impl<'tcx> OnUnimplementedFormatString { &empty_string } else if s == sym::ItemContext { &item_context + } else if s == sym::integral { + "{integral}" + } else if s == sym::integer_ { + "{integer}" + } else if s == sym::float { + "{float}" } else { bug!( "broken on_unimplemented {:?} for {:?}: \ From fea0015f9320f59c46821957a01f688f79a02546 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 1 Dec 2021 18:51:27 -0800 Subject: [PATCH 13/13] Suggest collecting into `Vec<_>` when collecting into `[_]` --- library/core/src/iter/traits/collect.rs | 26 +++++++++++++++++++ src/test/ui/iterators/collect-into-slice.rs | 15 +++++++++++ .../ui/iterators/collect-into-slice.stderr | 26 +++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 src/test/ui/iterators/collect-into-slice.rs create mode 100644 src/test/ui/iterators/collect-into-slice.stderr diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs index fc14620a2df84..637d7bc44885e 100644 --- a/library/core/src/iter/traits/collect.rs +++ b/library/core/src/iter/traits/collect.rs @@ -81,6 +81,32 @@ /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_on_unimplemented( + on( + _Self = "[{A}]", + message = "a value of type `{Self}` cannot be built since `{Self}` has no definite size", + label = "try explicitly collecting into a `Vec<{A}>`", + ), + on( + all( + A = "{integer}", + any( + _Self = "[i8]", + _Self = "[i16]", + _Self = "[i32]", + _Self = "[i64]", + _Self = "[i128]", + _Self = "[isize]", + _Self = "[u8]", + _Self = "[u16]", + _Self = "[u32]", + _Self = "[u64]", + _Self = "[u128]", + _Self = "[usize]" + ) + ), + message = "a value of type `{Self}` cannot be built since `{Self}` has no definite size", + label = "try explicitly collecting into a `Vec<{A}>`", + ), message = "a value of type `{Self}` cannot be built from an iterator \ over elements of type `{A}`", label = "value of type `{Self}` cannot be built from `std::iter::Iterator`" diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs new file mode 100644 index 0000000000000..905752dec7478 --- /dev/null +++ b/src/test/ui/iterators/collect-into-slice.rs @@ -0,0 +1,15 @@ +fn process_slice(data: &[i32]) { + //~^ NOTE required by a bound in this + todo!() +} + +fn main() { + let some_generated_vec = (0..10).collect(); + //~^ ERROR the size for values of type `[i32]` cannot be known at compilation time + //~| ERROR a value of type `[i32]` cannot be built since `[i32]` has no definite size + //~| NOTE try explicitly collecting into a `Vec<{integer}>` + //~| NOTE required by a bound in `collect` + //~| NOTE all local variables must have a statically known size + //~| NOTE doesn't have a size known at compile-time + process_slice(&some_generated_vec); +} diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr new file mode 100644 index 0000000000000..521f239451d2f --- /dev/null +++ b/src/test/ui/iterators/collect-into-slice.stderr @@ -0,0 +1,26 @@ +error[E0277]: the size for values of type `[i32]` cannot be known at compilation time + --> $DIR/collect-into-slice.rs:7:9 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[i32]` + = note: all local variables must have a statically known size + = help: unsized locals are gated as an unstable feature + +error[E0277]: a value of type `[i32]` cannot be built since `[i32]` has no definite size + --> $DIR/collect-into-slice.rs:7:38 + | +LL | let some_generated_vec = (0..10).collect(); + | ^^^^^^^ try explicitly collecting into a `Vec<{integer}>` + | + = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]` +note: required by a bound in `collect` + --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL + | +LL | fn collect>(self) -> B + | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`.