Auto merge of #93836 - matthiaskrgr:rollup-d1ssiwl, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #91443 (Better suggestions when user tries to collect into an unsized `[_]`) - #91504 (`#[used(linker)]` attribute) - #93503 (debuginfo: Fix DW_AT_containing_type vtable debuginfo regression) - #93753 (Complete removal of #[main] attribute from compiler) - #93799 (Fix typo in `std::fmt` docs) - #93813 (Make a few cleanup MIR passes public) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
5d6ee0db96
30 changed files with 544 additions and 84 deletions
|
@ -144,7 +144,7 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
|
||||||
// TODO(antoyo): set link section.
|
// 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());
|
self.add_used_global(global.to_rvalue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -522,6 +522,9 @@ impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if attrs.flags.contains(CodegenFnAttrFlags::USED) {
|
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
|
// 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
|
// 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.
|
// 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.
|
// in some versions of the gold linker.
|
||||||
self.add_compiler_used_global(g);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ use crate::value::Value;
|
||||||
|
|
||||||
use cstr::cstr;
|
use cstr::cstr;
|
||||||
use rustc_codegen_ssa::debuginfo::type_names::cpp_like_debuginfo;
|
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_codegen_ssa::traits::*;
|
||||||
use rustc_data_structures::fingerprint::Fingerprint;
|
use rustc_data_structures::fingerprint::Fingerprint;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
|
@ -276,6 +277,12 @@ impl<'ll, 'tcx> TypeMap<'ll, 'tcx> {
|
||||||
) -> String {
|
) -> String {
|
||||||
format!("{}_variant_part", self.get_unique_type_id_as_string(enum_type_id))
|
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
|
/// A description of some recursive type. It can either be already finished (as
|
||||||
|
@ -351,14 +358,15 @@ impl<'ll, 'tcx> RecursiveTypeDescription<'ll, 'tcx> {
|
||||||
|
|
||||||
// ... then create the member descriptions ...
|
// ... then create the member descriptions ...
|
||||||
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
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.
|
// ... and attach them to the stub to complete it.
|
||||||
set_members_of_composite_type(
|
set_members_of_composite_type(
|
||||||
cx,
|
cx,
|
||||||
unfinished_type,
|
|
||||||
member_holding_stub,
|
member_holding_stub,
|
||||||
member_descriptions,
|
member_descriptions,
|
||||||
None,
|
None,
|
||||||
|
type_params,
|
||||||
);
|
);
|
||||||
MetadataCreationResult::new(metadata_stub, true)
|
MetadataCreationResult::new(metadata_stub, true)
|
||||||
}
|
}
|
||||||
|
@ -983,7 +991,17 @@ fn foreign_type_metadata<'ll, 'tcx>(
|
||||||
debug!("foreign_type_metadata: {:?}", t);
|
debug!("foreign_type_metadata: {:?}", t);
|
||||||
|
|
||||||
let name = compute_debuginfo_type_name(cx.tcx, t, false);
|
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 {
|
fn param_type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType {
|
||||||
|
@ -1299,14 +1317,17 @@ fn prepare_struct_metadata<'ll, 'tcx>(
|
||||||
};
|
};
|
||||||
|
|
||||||
let containing_scope = get_namespace_for_item(cx, struct_def_id);
|
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(
|
let struct_metadata_stub = create_struct_stub(
|
||||||
cx,
|
cx,
|
||||||
struct_type,
|
size,
|
||||||
|
align,
|
||||||
&struct_name,
|
&struct_name,
|
||||||
unique_type_id,
|
unique_type_id,
|
||||||
Some(containing_scope),
|
Some(containing_scope),
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
create_and_register_recursive_type_forward_declaration(
|
create_and_register_recursive_type_forward_declaration(
|
||||||
|
@ -1398,15 +1419,18 @@ fn prepare_tuple_metadata<'ll, 'tcx>(
|
||||||
unique_type_id: UniqueTypeId,
|
unique_type_id: UniqueTypeId,
|
||||||
containing_scope: Option<&'ll DIScope>,
|
containing_scope: Option<&'ll DIScope>,
|
||||||
) -> RecursiveTypeDescription<'ll, 'tcx> {
|
) -> 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 tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false);
|
||||||
|
|
||||||
let struct_stub = create_struct_stub(
|
let struct_stub = create_struct_stub(
|
||||||
cx,
|
cx,
|
||||||
tuple_type,
|
size,
|
||||||
|
align,
|
||||||
&tuple_name[..],
|
&tuple_name[..],
|
||||||
unique_type_id,
|
unique_type_id,
|
||||||
containing_scope,
|
containing_scope,
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
create_and_register_recursive_type_forward_declaration(
|
create_and_register_recursive_type_forward_declaration(
|
||||||
|
@ -1581,13 +1605,14 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
describe_enum_variant(cx, self.layout, variant_info, self_metadata);
|
describe_enum_variant(cx, self.layout, variant_info, self_metadata);
|
||||||
|
|
||||||
let member_descriptions = member_description_factory.create_member_descriptions(cx);
|
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(
|
set_members_of_composite_type(
|
||||||
cx,
|
cx,
|
||||||
self.enum_type,
|
|
||||||
variant_type_metadata,
|
variant_type_metadata,
|
||||||
member_descriptions,
|
member_descriptions,
|
||||||
Some(&self.common_members),
|
Some(&self.common_members),
|
||||||
|
type_params,
|
||||||
);
|
);
|
||||||
vec![MemberDescription {
|
vec![MemberDescription {
|
||||||
name: variant_info.variant_name(),
|
name: variant_info.variant_name(),
|
||||||
|
@ -1648,13 +1673,14 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
|
|
||||||
let member_descriptions =
|
let member_descriptions =
|
||||||
member_desc_factory.create_member_descriptions(cx);
|
member_desc_factory.create_member_descriptions(cx);
|
||||||
|
let type_params = compute_type_parameters(cx, self.enum_type);
|
||||||
|
|
||||||
set_members_of_composite_type(
|
set_members_of_composite_type(
|
||||||
cx,
|
cx,
|
||||||
self.enum_type,
|
|
||||||
variant_type_metadata,
|
variant_type_metadata,
|
||||||
member_descriptions,
|
member_descriptions,
|
||||||
Some(&self.common_members),
|
Some(&self.common_members),
|
||||||
|
type_params,
|
||||||
);
|
);
|
||||||
|
|
||||||
MemberDescription {
|
MemberDescription {
|
||||||
|
@ -1777,13 +1803,14 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
);
|
);
|
||||||
|
|
||||||
let member_descriptions = member_desc_factory.create_member_descriptions(cx);
|
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(
|
set_members_of_composite_type(
|
||||||
cx,
|
cx,
|
||||||
self.enum_type,
|
|
||||||
variant_type_metadata,
|
variant_type_metadata,
|
||||||
member_descriptions,
|
member_descriptions,
|
||||||
Some(&self.common_members),
|
Some(&self.common_members),
|
||||||
|
type_params,
|
||||||
);
|
);
|
||||||
|
|
||||||
let (size, align) =
|
let (size, align) =
|
||||||
|
@ -1823,13 +1850,14 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> {
|
||||||
|
|
||||||
let member_descriptions =
|
let member_descriptions =
|
||||||
member_desc_factory.create_member_descriptions(cx);
|
member_desc_factory.create_member_descriptions(cx);
|
||||||
|
let type_params = compute_type_parameters(cx, self.enum_type);
|
||||||
|
|
||||||
set_members_of_composite_type(
|
set_members_of_composite_type(
|
||||||
cx,
|
cx,
|
||||||
self.enum_type,
|
|
||||||
variant_type_metadata,
|
variant_type_metadata,
|
||||||
member_descriptions,
|
member_descriptions,
|
||||||
Some(&self.common_members),
|
Some(&self.common_members),
|
||||||
|
type_params,
|
||||||
);
|
);
|
||||||
|
|
||||||
let niche_value = calculate_niche_value(i);
|
let niche_value = calculate_niche_value(i);
|
||||||
|
@ -1965,13 +1993,18 @@ fn describe_enum_variant<'ll, 'tcx>(
|
||||||
.type_map
|
.type_map
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.get_unique_type_id_of_enum_variant(cx, layout.ty, variant_name);
|
.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(
|
create_struct_stub(
|
||||||
cx,
|
cx,
|
||||||
layout.ty,
|
size,
|
||||||
|
align,
|
||||||
variant_name,
|
variant_name,
|
||||||
unique_type_id,
|
unique_type_id,
|
||||||
Some(containing_scope),
|
Some(containing_scope),
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
|
None,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2308,22 +2341,27 @@ fn composite_type_metadata<'ll, 'tcx>(
|
||||||
member_descriptions: Vec<MemberDescription<'ll>>,
|
member_descriptions: Vec<MemberDescription<'ll>>,
|
||||||
containing_scope: Option<&'ll DIScope>,
|
containing_scope: Option<&'ll DIScope>,
|
||||||
) -> &'ll DICompositeType {
|
) -> &'ll DICompositeType {
|
||||||
|
let (size, align) = cx.size_and_align_of(composite_type);
|
||||||
|
|
||||||
// Create the (empty) struct metadata node ...
|
// Create the (empty) struct metadata node ...
|
||||||
let composite_type_metadata = create_struct_stub(
|
let composite_type_metadata = create_struct_stub(
|
||||||
cx,
|
cx,
|
||||||
composite_type,
|
size,
|
||||||
|
align,
|
||||||
composite_type_name,
|
composite_type_name,
|
||||||
composite_type_unique_id,
|
composite_type_unique_id,
|
||||||
containing_scope,
|
containing_scope,
|
||||||
DIFlags::FlagZero,
|
DIFlags::FlagZero,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
// ... and immediately create and add the member descriptions.
|
// ... and immediately create and add the member descriptions.
|
||||||
set_members_of_composite_type(
|
set_members_of_composite_type(
|
||||||
cx,
|
cx,
|
||||||
composite_type,
|
|
||||||
composite_type_metadata,
|
composite_type_metadata,
|
||||||
member_descriptions,
|
member_descriptions,
|
||||||
None,
|
None,
|
||||||
|
compute_type_parameters(cx, composite_type),
|
||||||
);
|
);
|
||||||
|
|
||||||
composite_type_metadata
|
composite_type_metadata
|
||||||
|
@ -2331,10 +2369,10 @@ fn composite_type_metadata<'ll, 'tcx>(
|
||||||
|
|
||||||
fn set_members_of_composite_type<'ll, 'tcx>(
|
fn set_members_of_composite_type<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
composite_type: Ty<'tcx>,
|
|
||||||
composite_type_metadata: &'ll DICompositeType,
|
composite_type_metadata: &'ll DICompositeType,
|
||||||
member_descriptions: Vec<MemberDescription<'ll>>,
|
member_descriptions: Vec<MemberDescription<'ll>>,
|
||||||
common_members: Option<&Vec<Option<&'ll DIType>>>,
|
common_members: Option<&Vec<Option<&'ll DIType>>>,
|
||||||
|
type_params: &'ll DIArray,
|
||||||
) {
|
) {
|
||||||
// In some rare cases LLVM metadata uniquing would lead to an existing type
|
// In some rare cases LLVM metadata uniquing would lead to an existing type
|
||||||
// description being used instead of a new one created in
|
// description being used instead of a new one created in
|
||||||
|
@ -2361,13 +2399,12 @@ fn set_members_of_composite_type<'ll, 'tcx>(
|
||||||
member_metadata.extend(other_members.iter());
|
member_metadata.extend(other_members.iter());
|
||||||
}
|
}
|
||||||
|
|
||||||
let type_params = compute_type_parameters(cx, composite_type);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let type_array = create_DIArray(DIB(cx), &member_metadata);
|
let field_array = create_DIArray(DIB(cx), &member_metadata);
|
||||||
llvm::LLVMRustDICompositeTypeReplaceArrays(
|
llvm::LLVMRustDICompositeTypeReplaceArrays(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
composite_type_metadata,
|
composite_type_metadata,
|
||||||
Some(type_array),
|
Some(field_array),
|
||||||
Some(type_params),
|
Some(type_params),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2420,14 +2457,14 @@ fn compute_type_parameters<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -
|
||||||
/// with `set_members_of_composite_type()`.
|
/// with `set_members_of_composite_type()`.
|
||||||
fn create_struct_stub<'ll, 'tcx>(
|
fn create_struct_stub<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
struct_type: Ty<'tcx>,
|
size: Size,
|
||||||
struct_type_name: &str,
|
align: Align,
|
||||||
|
type_name: &str,
|
||||||
unique_type_id: UniqueTypeId,
|
unique_type_id: UniqueTypeId,
|
||||||
containing_scope: Option<&'ll DIScope>,
|
containing_scope: Option<&'ll DIScope>,
|
||||||
flags: DIFlags,
|
flags: DIFlags,
|
||||||
|
vtable_holder: Option<&'ll DIType>,
|
||||||
) -> &'ll DICompositeType {
|
) -> &'ll DICompositeType {
|
||||||
let (struct_size, struct_align) = cx.size_and_align_of(struct_type);
|
|
||||||
|
|
||||||
let type_map = debug_context(cx).type_map.borrow();
|
let type_map = debug_context(cx).type_map.borrow();
|
||||||
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
let unique_type_id = type_map.get_unique_type_id_as_string(unique_type_id);
|
||||||
|
|
||||||
|
@ -2440,17 +2477,17 @@ fn create_struct_stub<'ll, 'tcx>(
|
||||||
llvm::LLVMRustDIBuilderCreateStructType(
|
llvm::LLVMRustDIBuilderCreateStructType(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
containing_scope,
|
containing_scope,
|
||||||
struct_type_name.as_ptr().cast(),
|
type_name.as_ptr().cast(),
|
||||||
struct_type_name.len(),
|
type_name.len(),
|
||||||
unknown_file_metadata(cx),
|
unknown_file_metadata(cx),
|
||||||
UNKNOWN_LINE_NUMBER,
|
UNKNOWN_LINE_NUMBER,
|
||||||
struct_size.bits(),
|
size.bits(),
|
||||||
struct_align.bits() as u32,
|
align.bits() as u32,
|
||||||
flags,
|
flags,
|
||||||
None,
|
None,
|
||||||
empty_array,
|
empty_array,
|
||||||
0,
|
0,
|
||||||
None,
|
vtable_holder,
|
||||||
unique_type_id.as_ptr().cast(),
|
unique_type_id.as_ptr().cast(),
|
||||||
unique_type_id.len(),
|
unique_type_id.len(),
|
||||||
)
|
)
|
||||||
|
@ -2556,6 +2593,14 @@ pub fn create_global_var_metadata<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, g
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generates LLVM debuginfo for a vtable.
|
/// 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>(
|
fn vtable_type_metadata<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
|
@ -2572,16 +2617,81 @@ fn vtable_type_metadata<'ll, 'tcx>(
|
||||||
COMMON_VTABLE_ENTRIES
|
COMMON_VTABLE_ENTRIES
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: We describe the vtable as an array of *const () pointers. The length of the array is
|
// All function pointers are described as opaque pointers. This could be improved in the future
|
||||||
// correct - but we could create a more accurate description, e.g. by describing it
|
// by describing them as actual function pointers.
|
||||||
// as a struct where each field has a name that corresponds to the name of the method
|
let void_pointer_ty = tcx.mk_imm_ptr(tcx.types.unit);
|
||||||
// it points to.
|
let void_pointer_type_debuginfo = type_metadata(cx, void_pointer_ty);
|
||||||
// However, this is not entirely straightforward because there might be multiple
|
let usize_debuginfo = type_metadata(cx, tcx.types.usize);
|
||||||
// methods with the same name if the vtable is for multiple traits. So for now we keep
|
let (pointer_size, pointer_align) = cx.size_and_align_of(void_pointer_ty);
|
||||||
// things simple instead of adding some ad-hoc disambiguation scheme.
|
// If `usize` is not pointer-sized and -aligned then the size and alignment computations
|
||||||
let vtable_type = tcx.mk_array(tcx.mk_imm_ptr(tcx.types.unit), vtable_entries.len() as u64);
|
// 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));
|
||||||
|
|
||||||
type_metadata(cx, vtable_type)
|
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 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),
|
||||||
|
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();
|
||||||
|
|
||||||
|
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
|
/// Creates debug information for the given vtable, which is for the
|
||||||
|
@ -2603,11 +2713,12 @@ pub fn create_vtable_metadata<'ll, 'tcx>(
|
||||||
return;
|
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 vtable_type = vtable_type_metadata(cx, ty, poly_trait_ref);
|
||||||
|
let linkage_name = "";
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let linkage_name = "";
|
|
||||||
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
llvm::LLVMRustDIBuilderCreateStaticVariable(
|
||||||
DIB(cx),
|
DIB(cx),
|
||||||
NO_SCOPE_METADATA,
|
NO_SCOPE_METADATA,
|
||||||
|
|
|
@ -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 the 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:
|
/// The name is of the form:
|
||||||
///
|
///
|
||||||
|
@ -478,10 +485,15 @@ fn push_debuginfo_type_name<'tcx>(
|
||||||
/// or, when generating C++-like names:
|
/// or, when generating C++-like names:
|
||||||
///
|
///
|
||||||
/// `impl$<path::to::SomeType, path::to::SomeTrait>::vtable$`
|
/// `impl$<path::to::SomeType, path::to::SomeTrait>::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>(
|
pub fn compute_debuginfo_vtable_name<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
t: Ty<'tcx>,
|
t: Ty<'tcx>,
|
||||||
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
trait_ref: Option<ty::PolyExistentialTraitRef<'tcx>>,
|
||||||
|
kind: VTableNameKind,
|
||||||
) -> String {
|
) -> String {
|
||||||
let cpp_like_debuginfo = cpp_like_debuginfo(tcx);
|
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);
|
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.reserve_exact(suffix.len());
|
||||||
vtable_name.push_str(suffix);
|
vtable_name.push_str(suffix);
|
||||||
|
|
|
@ -531,6 +531,8 @@ declare_features! (
|
||||||
///
|
///
|
||||||
/// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0.
|
/// NOTE: A limited form of `union U { ... }` was accepted in 1.19.0.
|
||||||
(active, untagged_unions, "1.13.0", Some(55149), None),
|
(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(93798), None),
|
||||||
/// Allows `extern "wasm" fn`
|
/// Allows `extern "wasm" fn`
|
||||||
(active, wasm_abi, "1.53.0", Some(83788), None),
|
(active, wasm_abi, "1.53.0", Some(83788), None),
|
||||||
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
// !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!! !!!!
|
||||||
|
|
|
@ -324,7 +324,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
ungated!(export_name, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||||
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
ungated!(link_section, Normal, template!(NameValueStr: "name"), FutureWarnPreceding),
|
||||||
ungated!(no_mangle, Normal, template!(Word), WarnFollowing),
|
ungated!(no_mangle, Normal, template!(Word), WarnFollowing),
|
||||||
ungated!(used, Normal, template!(Word), WarnFollowing),
|
ungated!(used, Normal, template!(Word, List: "compiler|linker"), WarnFollowing),
|
||||||
|
|
||||||
// Limits:
|
// Limits:
|
||||||
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
|
ungated!(recursion_limit, CrateLevel, template!(NameValueStr: "N"), FutureWarnFollowing),
|
||||||
|
@ -339,7 +339,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
|
||||||
),
|
),
|
||||||
|
|
||||||
// Entry point:
|
// Entry point:
|
||||||
ungated!(main, Normal, template!(Word), WarnFollowing),
|
|
||||||
ungated!(start, Normal, template!(Word), WarnFollowing),
|
ungated!(start, Normal, template!(Word), WarnFollowing),
|
||||||
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing),
|
ungated!(no_start, CrateLevel, template!(Word), WarnFollowing),
|
||||||
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing),
|
ungated!(no_main, CrateLevel, template!(Word), WarnFollowing),
|
||||||
|
|
|
@ -89,6 +89,8 @@ bitflags! {
|
||||||
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
|
/// the MIR `InstrumentCoverage` pass and not added to the coverage map
|
||||||
/// during codegen.
|
/// during codegen.
|
||||||
const NO_COVERAGE = 1 << 15;
|
const NO_COVERAGE = 1 << 15;
|
||||||
|
/// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function.
|
||||||
|
const USED_LINKER = 1 << 16;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,8 @@ mod add_retag;
|
||||||
mod check_const_item_mutation;
|
mod check_const_item_mutation;
|
||||||
mod check_packed_ref;
|
mod check_packed_ref;
|
||||||
pub mod check_unsafety;
|
pub mod check_unsafety;
|
||||||
mod cleanup_post_borrowck;
|
// This pass is public to allow external drivers to perform MIR cleanup
|
||||||
|
pub mod cleanup_post_borrowck;
|
||||||
mod const_debuginfo;
|
mod const_debuginfo;
|
||||||
mod const_goto;
|
mod const_goto;
|
||||||
mod const_prop;
|
mod const_prop;
|
||||||
|
@ -65,7 +66,8 @@ mod match_branches;
|
||||||
mod multiple_return_terminators;
|
mod multiple_return_terminators;
|
||||||
mod normalize_array_len;
|
mod normalize_array_len;
|
||||||
mod nrvo;
|
mod nrvo;
|
||||||
mod remove_false_edges;
|
// This pass is public to allow external drivers to perform MIR cleanup
|
||||||
|
pub mod remove_false_edges;
|
||||||
mod remove_noop_landing_pads;
|
mod remove_noop_landing_pads;
|
||||||
mod remove_storage_markers;
|
mod remove_storage_markers;
|
||||||
mod remove_uninit_drops;
|
mod remove_uninit_drops;
|
||||||
|
@ -75,7 +77,8 @@ mod required_consts;
|
||||||
mod reveal_all;
|
mod reveal_all;
|
||||||
mod separate_const_switch;
|
mod separate_const_switch;
|
||||||
mod shim;
|
mod shim;
|
||||||
mod simplify;
|
// This pass is public to allow external drivers to perform MIR cleanup
|
||||||
|
pub mod simplify;
|
||||||
mod simplify_branches;
|
mod simplify_branches;
|
||||||
mod simplify_comparison_integral;
|
mod simplify_comparison_integral;
|
||||||
mod simplify_try;
|
mod simplify_try;
|
||||||
|
|
|
@ -1741,12 +1741,46 @@ impl CheckAttrVisitor<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_used(&self, attrs: &[Attribute], target: Target) {
|
fn check_used(&self, attrs: &[Attribute], target: Target) {
|
||||||
|
let mut used_linker_span = None;
|
||||||
|
let mut used_compiler_span = None;
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
if attr.has_name(sym::used) && target != Target::Static {
|
if attr.has_name(sym::used) && target != Target::Static {
|
||||||
self.tcx
|
self.tcx
|
||||||
.sess
|
.sess
|
||||||
.span_err(attr.span, "attribute must be applied to a `static` variable");
|
.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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
|
||||||
// forcefully, e.g., for placing it in a specific section.
|
// 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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -449,6 +449,7 @@ symbols! {
|
||||||
compare_exchange_weak,
|
compare_exchange_weak,
|
||||||
compile_error,
|
compile_error,
|
||||||
compile_error_macro,
|
compile_error_macro,
|
||||||
|
compiler,
|
||||||
compiler_builtins,
|
compiler_builtins,
|
||||||
compiler_fence,
|
compiler_fence,
|
||||||
concat,
|
concat,
|
||||||
|
@ -668,6 +669,7 @@ symbols! {
|
||||||
fill,
|
fill,
|
||||||
finish,
|
finish,
|
||||||
flags,
|
flags,
|
||||||
|
float,
|
||||||
float_to_int_unchecked,
|
float_to_int_unchecked,
|
||||||
floorf32,
|
floorf32,
|
||||||
floorf64,
|
floorf64,
|
||||||
|
@ -771,6 +773,8 @@ symbols! {
|
||||||
inline_const_pat,
|
inline_const_pat,
|
||||||
inout,
|
inout,
|
||||||
instruction_set,
|
instruction_set,
|
||||||
|
integer_: "integer",
|
||||||
|
integral,
|
||||||
intel,
|
intel,
|
||||||
into_future,
|
into_future,
|
||||||
into_iter,
|
into_iter,
|
||||||
|
@ -815,6 +819,7 @@ symbols! {
|
||||||
link_ordinal,
|
link_ordinal,
|
||||||
link_section,
|
link_section,
|
||||||
linkage,
|
linkage,
|
||||||
|
linker,
|
||||||
lint_reasons,
|
lint_reasons,
|
||||||
literal,
|
literal,
|
||||||
load,
|
load,
|
||||||
|
@ -1463,6 +1468,7 @@ symbols! {
|
||||||
use_extern_macros,
|
use_extern_macros,
|
||||||
use_nested_groups,
|
use_nested_groups,
|
||||||
used,
|
used,
|
||||||
|
used_with_arg,
|
||||||
usize,
|
usize,
|
||||||
v1,
|
v1,
|
||||||
va_arg,
|
va_arg,
|
||||||
|
|
|
@ -62,6 +62,10 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
let mut errored = false;
|
let mut errored = false;
|
||||||
let mut item_iter = items.iter();
|
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 {
|
let condition = if is_root {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -86,7 +90,14 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
None,
|
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())
|
Some(cond.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -97,10 +108,6 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
let mut subcommands = vec![];
|
let mut subcommands = vec![];
|
||||||
let mut append_const_msg = None;
|
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 {
|
for item in item_iter {
|
||||||
if item.has_name(sym::message) && message.is_none() {
|
if item.has_name(sym::message) && message.is_none() {
|
||||||
if let Some(message_) = item.value_str() {
|
if let Some(message_) = item.value_str() {
|
||||||
|
@ -221,6 +228,9 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
let mut append_const_msg = None;
|
let mut append_const_msg = None;
|
||||||
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
|
info!("evaluate({:?}, trait_ref={:?}, options={:?})", self, trait_ref, options);
|
||||||
|
|
||||||
|
let options_map: FxHashMap<Symbol, String> =
|
||||||
|
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() {
|
for command in self.subcommands.iter().chain(Some(self)).rev() {
|
||||||
if let Some(ref condition) = command.condition {
|
if let Some(ref condition) = command.condition {
|
||||||
if !attr::eval_condition(
|
if !attr::eval_condition(
|
||||||
|
@ -229,7 +239,11 @@ impl<'tcx> OnUnimplementedDirective {
|
||||||
Some(tcx.features()),
|
Some(tcx.features()),
|
||||||
&mut |c| {
|
&mut |c| {
|
||||||
c.ident().map_or(false, |ident| {
|
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();
|
append_const_msg = command.append_const_msg.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
let options: FxHashMap<Symbol, String> =
|
|
||||||
options.iter().filter_map(|(k, v)| v.as_ref().map(|v| (*k, v.to_owned()))).collect();
|
|
||||||
OnUnimplementedNote {
|
OnUnimplementedNote {
|
||||||
label: label.map(|l| l.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)),
|
message: message.map(|m| m.format(tcx, trait_ref, &options_map)),
|
||||||
note: note.map(|n| n.format(tcx, trait_ref, &options)),
|
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)),
|
enclosing_scope: enclosing_scope.map(|e_s| e_s.format(tcx, trait_ref, &options_map)),
|
||||||
append_const_msg,
|
append_const_msg,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -306,6 +318,12 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||||
Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
|
Position::ArgumentNamed(s) if s == sym::from_desugaring => (),
|
||||||
// `{ItemContext}` is allowed
|
// `{ItemContext}` is allowed
|
||||||
Position::ArgumentNamed(s) if s == sym::ItemContext => (),
|
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
|
// So is `{A}` if A is a type parameter
|
||||||
Position::ArgumentNamed(s) => {
|
Position::ArgumentNamed(s) => {
|
||||||
match generics.params.iter().find(|param| param.name == s) {
|
match generics.params.iter().find(|param| param.name == s) {
|
||||||
|
@ -385,6 +403,12 @@ impl<'tcx> OnUnimplementedFormatString {
|
||||||
&empty_string
|
&empty_string
|
||||||
} else if s == sym::ItemContext {
|
} else if s == sym::ItemContext {
|
||||||
&item_context
|
&item_context
|
||||||
|
} else if s == sym::integral {
|
||||||
|
"{integral}"
|
||||||
|
} else if s == sym::integer_ {
|
||||||
|
"{integer}"
|
||||||
|
} else if s == sym::float {
|
||||||
|
"{float}"
|
||||||
} else {
|
} else {
|
||||||
bug!(
|
bug!(
|
||||||
"broken on_unimplemented {:?} for {:?}: \
|
"broken on_unimplemented {:?} for {:?}: \
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// ignore-tidy-filelength
|
||||||
//! "Collection" is the process of determining the type and other external
|
//! "Collection" is the process of determining the type and other external
|
||||||
//! details of each item in Rust. Collection is specifically concerned
|
//! details of each item in Rust. Collection is specifically concerned
|
||||||
//! with *inter-procedural* things -- for example, for a function
|
//! with *inter-procedural* things -- for example, for a function
|
||||||
|
@ -2856,7 +2857,42 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, id: DefId) -> CodegenFnAttrs {
|
||||||
} else if attr.has_name(sym::rustc_std_internal_symbol) {
|
} else if attr.has_name(sym::rustc_std_internal_symbol) {
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL;
|
||||||
} else if attr.has_name(sym::used) {
|
} else if attr.has_name(sym::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;
|
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) {
|
} else if attr.has_name(sym::cmse_nonsecure_entry) {
|
||||||
if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) {
|
if !matches!(tcx.fn_sig(id).abi(), abi::Abi::C { .. }) {
|
||||||
struct_span_err!(
|
struct_span_err!(
|
||||||
|
|
|
@ -74,7 +74,7 @@
|
||||||
//! identifier '=' expression
|
//! 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"
|
//! format!("{argument}", argument = "test"); // => "test"
|
||||||
|
|
|
@ -81,6 +81,32 @@
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[rustc_on_unimplemented(
|
#[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 \
|
message = "a value of type `{Self}` cannot be built from an iterator \
|
||||||
over elements of type `{A}`",
|
over elements of type `{A}`",
|
||||||
label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
|
label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
|
||||||
|
|
|
@ -9,19 +9,41 @@
|
||||||
// compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0
|
// compile-flags: -Cdebuginfo=2 -Copt-level=0 -Csymbol-mangling-version=v0
|
||||||
// ignore-tidy-linelength
|
// 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$<tuple$<> >"
|
||||||
|
|
||||||
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTrait>::{vtable}"
|
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTrait>::{vtable}"
|
||||||
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTrait>::vtable$"
|
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTrait>::vtable$"
|
||||||
// NONMSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "*const ()",
|
|
||||||
// MSVC: !DIDerivedType(tag: DW_TAG_pointer_type, name: "ptr_const$<tuple$<> >",
|
// NONMSVC: ![[VTABLE_TY0:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "<debug_vtable::Foo as debug_vtable::SomeTrait>::{vtable_type}", {{.*}} size: {{320|160}}, align: {{64|32}}, flags: DIFlagArtificial, {{.*}} vtableHolder: ![[FOO_TYPE:[0-9]+]],
|
||||||
// CHECK: !DISubrange(count: 5
|
// MSVC: ![[VTABLE_TY0:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "impl$<debug_vtable::Foo, debug_vtable::SomeTrait>::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: "<debug_vtable::Foo as debug_vtable::SomeTraitWithGenerics<u64, i8>>::{vtable}"
|
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as debug_vtable::SomeTraitWithGenerics<u64, i8>>::{vtable}"
|
||||||
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTraitWithGenerics<u64,i8> >::vtable$"
|
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, debug_vtable::SomeTraitWithGenerics<u64,i8> >::vtable$"
|
||||||
// CHECK: !DISubrange(count: 4
|
|
||||||
|
// NONMSVC: ![[VTABLE_TY1:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "<debug_vtable::Foo as debug_vtable::SomeTraitWithGenerics<u64, i8>>::{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$<debug_vtable::Foo, debug_vtable::SomeTraitWithGenerics<u64,i8> >::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: "<debug_vtable::Foo as _>::{vtable}"
|
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::Foo as _>::{vtable}"
|
||||||
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, _>::vtable$"
|
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::Foo, _>::vtable$"
|
||||||
// CHECK: !DISubrange(count: 3
|
|
||||||
|
// NONMSVC: ![[VTABLE_TY2:[0-9]+]] = !DICompositeType(tag: DW_TAG_structure_type, name: "<debug_vtable::Foo as _>::{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$<debug_vtable::Foo, _>::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: "<debug_vtable::bar::{closure_env#0} as core::ops::function::FnOnce<(core::option::Option<&dyn core::ops::function::Fn<(), Output=()>>)>>::{vtable}"
|
// NONMSVC: !DIGlobalVariable(name: "<debug_vtable::bar::{closure_env#0} as core::ops::function::FnOnce<(core::option::Option<&dyn core::ops::function::Fn<(), Output=()>>)>>::{vtable}"
|
||||||
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::bar::closure_env$0, core::ops::function::FnOnce<tuple$<enum$<core::option::Option<ref$<dyn$<core::ops::function::Fn<tuple$<>,assoc$<Output,tuple$<> > > > > >, {{.*}}, {{.*}}, Some> > > >::vtable$"
|
// MSVC: !DIGlobalVariable(name: "impl$<debug_vtable::bar::closure_env$0, core::ops::function::FnOnce<tuple$<enum$<core::option::Option<ref$<dyn$<core::ops::function::Fn<tuple$<>,assoc$<Output,tuple$<> > > > > >, {{.*}}, {{.*}}, Some> > > >::vtable$"
|
||||||
|
@ -34,6 +56,9 @@
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
|
||||||
|
// Force emission for debuginfo for usize and *const() early..
|
||||||
|
pub static mut XYZ: Option<(usize, *const ())> = None;
|
||||||
|
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
pub trait SomeTrait {
|
pub trait SomeTrait {
|
||||||
|
|
|
@ -17,35 +17,34 @@
|
||||||
|
|
||||||
// compile-flags: -Cdebuginfo=2 --edition 2021 -Copt-level=0 -Csymbol-mangling-version=v0
|
// 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()
|
// non_generic_closure()
|
||||||
// NONMSVC: !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]]
|
// 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<u32>()
|
// function_containing_closure<u32>()
|
||||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<u32>", scope: [[function_containing_closure_NAMESPACE]]
|
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<u32>", scope: ![[function_containing_closure_NAMESPACE]]
|
||||||
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<u32>", scope: [[function_containing_closure_NAMESPACE]]
|
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<u32>", scope: ![[function_containing_closure_NAMESPACE]]
|
||||||
|
|
||||||
// generic_async_function<Foo>()
|
// generic_async_function<Foo>()
|
||||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: [[generic_async_function_NAMESPACE]]
|
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_function_NAMESPACE]]
|
||||||
|
|
||||||
// generic_async_function<u32>()
|
// generic_async_function<u32>()
|
||||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<u32>", scope: [[generic_async_function_NAMESPACE]]
|
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_fn_env#0}<u32>", scope: ![[generic_async_function_NAMESPACE]]
|
||||||
|
|
||||||
// generic_async_block<Foo>()
|
// generic_async_block<Foo>()
|
||||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: [[generic_async_block_NAMESPACE]]
|
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[generic_async_block_NAMESPACE]]
|
||||||
|
|
||||||
// generic_async_block<u32>()
|
// generic_async_block<u32>()
|
||||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<u32>", scope: [[generic_async_block_NAMESPACE]]
|
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{async_block_env#0}<u32>", scope: ![[generic_async_block_NAMESPACE]]
|
||||||
|
|
||||||
// function_containing_closure<Foo>()
|
// function_containing_closure<Foo>()
|
||||||
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: [[function_containing_closure_NAMESPACE]]
|
// NONMSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "{closure_env#0}<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
|
||||||
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<debuginfo_generic_closure_env_names::Foo>", scope: [[function_containing_closure_NAMESPACE]]
|
// MSVC: !DICompositeType(tag: DW_TAG_structure_type, name: "closure_env$0<debuginfo_generic_closure_env_names::Foo>", scope: ![[function_containing_closure_NAMESPACE]]
|
||||||
|
|
||||||
|
|
||||||
#![crate_type = "lib"]
|
#![crate_type = "lib"]
|
||||||
|
@ -54,15 +53,14 @@ use std::future::Future;
|
||||||
pub struct Foo;
|
pub struct Foo;
|
||||||
|
|
||||||
pub fn non_generic_closure(x: Foo) -> Box<dyn FnOnce() -> Foo> {
|
pub fn non_generic_closure(x: Foo) -> Box<dyn FnOnce() -> 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);
|
return Box::new(move || x);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn function_containing_closure<T: 'static>(x: T) -> impl FnOnce() -> T {
|
fn function_containing_closure<T: 'static>(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;
|
return move || x;
|
||||||
}
|
}
|
||||||
|
|
10
src/test/codegen/used_with_arg.rs
Normal file
10
src/test/codegen/used_with_arg.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
#![crate_type = "lib"]
|
||||||
|
#![feature(used_with_arg)]
|
||||||
|
|
||||||
|
// 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*]{{.*}}USED_COMPILER
|
||||||
|
#[used(compiler)]
|
||||||
|
static mut USED_COMPILER: [usize; 1] = [0];
|
2
src/test/ui/attributes/main-removed-1.rs
Normal file
2
src/test/ui/attributes/main-removed-1.rs
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#[main] //~ ERROR cannot find attribute `main` in this scope
|
||||||
|
fn main() {}
|
10
src/test/ui/attributes/main-removed-1.stderr
Normal file
10
src/test/ui/attributes/main-removed-1.stderr
Normal file
|
@ -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
|
||||||
|
|
12
src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs
Normal file
12
src/test/ui/attributes/main-removed-2/auxiliary/tokyo.rs
Normal file
|
@ -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()
|
||||||
|
}
|
11
src/test/ui/attributes/main-removed-2/main.rs
Normal file
11
src/test/ui/attributes/main-removed-2/main.rs
Normal file
|
@ -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")
|
||||||
|
}
|
19
src/test/ui/attributes/used_with_arg.rs
Normal file
19
src/test/ui/attributes/used_with_arg.rs
Normal file
|
@ -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() {}
|
18
src/test/ui/attributes/used_with_arg.stderr
Normal file
18
src/test/ui/attributes/used_with_arg.stderr
Normal file
|
@ -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
|
||||||
|
|
6
src/test/ui/attributes/used_with_multi_args.rs
Normal file
6
src/test/ui/attributes/used_with_multi_args.rs
Normal file
|
@ -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() {}
|
8
src/test/ui/attributes/used_with_multi_args.stderr
Normal file
8
src/test/ui/attributes/used_with_multi_args.stderr
Normal file
|
@ -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
|
||||||
|
|
7
src/test/ui/feature-gates/feature-gate-used_with_arg.rs
Normal file
7
src/test/ui/feature-gates/feature-gate-used_with_arg.rs
Normal file
|
@ -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() {}
|
21
src/test/ui/feature-gates/feature-gate-used_with_arg.stderr
Normal file
21
src/test/ui/feature-gates/feature-gate-used_with_arg.stderr
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
error[E0658]: `#[used(linker)]` is currently unstable
|
||||||
|
--> $DIR/feature-gate-used_with_arg.rs:1:1
|
||||||
|
|
|
||||||
|
LL | #[used(linker)]
|
||||||
|
| ^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #93798 <https://github.com/rust-lang/rust/issues/93798> for more information
|
||||||
|
= 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)]
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: see issue #93798 <https://github.com/rust-lang/rust/issues/93798> for more information
|
||||||
|
= 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`.
|
15
src/test/ui/iterators/collect-into-slice.rs
Normal file
15
src/test/ui/iterators/collect-into-slice.rs
Normal file
|
@ -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);
|
||||||
|
}
|
26
src/test/ui/iterators/collect-into-slice.stderr
Normal file
26
src/test/ui/iterators/collect-into-slice.stderr
Normal file
|
@ -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<B: FromIterator<Self::Item>>(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`.
|
Loading…
Add table
Reference in a new issue