diff options
Diffstat (limited to 'compiler')
21 files changed, 236 insertions, 183 deletions
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index ddba43cd1f1..6afa649b6de 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -349,13 +349,6 @@ fn fat_lto( ); save_temp_bitcode(cgcx, &module, "lto.after-restriction"); } - - if cgcx.no_landing_pads { - unsafe { - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); - } - save_temp_bitcode(cgcx, &module, "lto.after-nounwind"); - } } Ok(LtoModuleCodegen::Fat { module: Some(module), _serialized_bitcode: serialized_bitcode }) @@ -770,16 +763,6 @@ pub unsafe fn optimize_thin_module( return Err(write::llvm_err(&diag_handler, msg)); } - // Like with "fat" LTO, get some better optimizations if landing pads - // are disabled by removing all landing pads. - if cgcx.no_landing_pads { - let _timer = cgcx - .prof - .generic_activity_with_arg("LLVM_thin_lto_remove_landing_pads", thin_module.name()); - llvm::LLVMRustMarkAllFunctionsNounwind(llmod); - save_temp_bitcode(cgcx, &module, "thin-lto-after-nounwind"); - } - // Up next comes the per-module local analyses that we do for Thin LTO. // Each of these functions is basically copied from the LLVM // implementation and then tailored to suit this implementation. Ideally diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 5c02e3d0fa7..3d5fd2f354e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -27,18 +27,18 @@ use rustc_fs_util::path_to_c_string; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_index::vec::{Idx, IndexVec}; +use rustc_middle::bug; use rustc_middle::mir::{self, GeneratorLayout}; use rustc_middle::ty::layout::{self, IntegerExt, LayoutOf, PrimitiveExt, TyAndLayout}; use rustc_middle::ty::subst::GenericArgKind; use rustc_middle::ty::{ self, AdtKind, GeneratorSubsts, Instance, ParamEnv, Ty, TyCtxt, COMMON_VTABLE_ENTRIES, }; -use rustc_middle::{bug, span_bug}; use rustc_query_system::ich::NodeIdHashingMode; use rustc_session::config::{self, DebugInfo}; use rustc_span::symbol::Symbol; use rustc_span::FileNameDisplayPreference; -use rustc_span::{self, SourceFile, SourceFileHash, Span}; +use rustc_span::{self, SourceFile, SourceFileHash}; use rustc_target::abi::{Abi, Align, HasDataLayout, Integer, TagEncoding}; use rustc_target::abi::{Int, Pointer, F32, F64}; use rustc_target::abi::{Primitive, Size, VariantIdx, Variants}; @@ -381,9 +381,8 @@ fn fixed_vec_metadata<'ll, 'tcx>( unique_type_id: UniqueTypeId, array_or_slice_type: Ty<'tcx>, element_type: Ty<'tcx>, - span: Span, ) -> MetadataCreationResult<'ll> { - let element_type_metadata = type_metadata(cx, element_type, span); + let element_type_metadata = type_metadata(cx, element_type); return_if_metadata_created_in_meantime!(cx, unique_type_id); @@ -416,11 +415,10 @@ fn vec_slice_metadata<'ll, 'tcx>( slice_ptr_type: Ty<'tcx>, element_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - span: Span, ) -> MetadataCreationResult<'ll> { let data_ptr_type = cx.tcx.mk_imm_ptr(element_type); - let data_ptr_metadata = type_metadata(cx, data_ptr_type, span); + let data_ptr_metadata = type_metadata(cx, data_ptr_type); return_if_metadata_created_in_meantime!(cx, unique_type_id); @@ -442,7 +440,7 @@ fn vec_slice_metadata<'ll, 'tcx>( }, MemberDescription { name: "length".to_owned(), - type_metadata: type_metadata(cx, cx.tcx.types.usize, span), + type_metadata: type_metadata(cx, cx.tcx.types.usize), offset: pointer_size, size: usize_size, align: usize_align, @@ -452,8 +450,6 @@ fn vec_slice_metadata<'ll, 'tcx>( }, ]; - let file_metadata = unknown_file_metadata(cx); - let metadata = composite_type_metadata( cx, slice_ptr_type, @@ -461,8 +457,6 @@ fn vec_slice_metadata<'ll, 'tcx>( unique_type_id, member_descriptions, NO_SCOPE_METADATA, - file_metadata, - span, ); MetadataCreationResult::new(metadata, false) } @@ -471,7 +465,6 @@ fn subroutine_type_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, unique_type_id: UniqueTypeId, signature: ty::PolyFnSig<'tcx>, - span: Span, ) -> MetadataCreationResult<'ll> { let signature = cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), signature); @@ -480,12 +473,12 @@ fn subroutine_type_metadata<'ll, 'tcx>( // return type match signature.output().kind() { ty::Tuple(tys) if tys.is_empty() => None, - _ => Some(type_metadata(cx, signature.output(), span)), + _ => Some(type_metadata(cx, signature.output())), }, ) .chain( // regular arguments - signature.inputs().iter().map(|argument_type| Some(type_metadata(cx, argument_type, span))), + signature.inputs().iter().map(|argument_type| Some(type_metadata(cx, argument_type))), ) .collect(); @@ -541,8 +534,6 @@ fn trait_pointer_metadata<'ll, 'tcx>( None => (NO_SCOPE_METADATA, compute_debuginfo_type_name(cx.tcx, trait_type, true)), }; - let file_metadata = unknown_file_metadata(cx); - let layout = cx.layout_of(cx.tcx.mk_mut_ptr(trait_type)); assert_eq!(abi::FAT_PTR_ADDR, 0); @@ -553,11 +544,7 @@ fn trait_pointer_metadata<'ll, 'tcx>( let member_descriptions = vec![ MemberDescription { name: "pointer".to_owned(), - type_metadata: type_metadata( - cx, - cx.tcx.mk_mut_ptr(cx.tcx.types.u8), - rustc_span::DUMMY_SP, - ), + type_metadata: type_metadata(cx, cx.tcx.mk_mut_ptr(cx.tcx.types.u8)), offset: layout.fields.offset(0), size: data_ptr_field.size, align: data_ptr_field.align.abi, @@ -567,7 +554,7 @@ fn trait_pointer_metadata<'ll, 'tcx>( }, MemberDescription { name: "vtable".to_owned(), - type_metadata: type_metadata(cx, vtable_field.ty, rustc_span::DUMMY_SP), + type_metadata: type_metadata(cx, vtable_field.ty), offset: layout.fields.offset(1), size: vtable_field.size, align: vtable_field.align.abi, @@ -584,16 +571,10 @@ fn trait_pointer_metadata<'ll, 'tcx>( unique_type_id, member_descriptions, containing_scope, - file_metadata, - rustc_span::DUMMY_SP, ) } -pub fn type_metadata<'ll, 'tcx>( - cx: &CodegenCx<'ll, 'tcx>, - t: Ty<'tcx>, - usage_site_span: Span, -) -> &'ll DIType { +pub fn type_metadata<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, t: Ty<'tcx>) -> &'ll DIType { // Get the unique type ID of this type. let unique_type_id = { let mut type_map = debug_context(cx).type_map.borrow_mut(); @@ -630,14 +611,14 @@ pub fn type_metadata<'ll, 'tcx>( debug!("type_metadata: {:?}", t); let ptr_metadata = |ty: Ty<'tcx>| match *ty.kind() { - ty::Slice(typ) => Ok(vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)), - ty::Str => Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id, usage_site_span)), + ty::Slice(typ) => Ok(vec_slice_metadata(cx, t, typ, unique_type_id)), + ty::Str => Ok(vec_slice_metadata(cx, t, cx.tcx.types.u8, unique_type_id)), ty::Dynamic(..) => Ok(MetadataCreationResult::new( trait_pointer_metadata(cx, ty, Some(t), unique_type_id), false, )), _ => { - let pointee_metadata = type_metadata(cx, ty, usage_site_span); + let pointee_metadata = type_metadata(cx, ty); if let Some(metadata) = debug_context(cx).type_map.borrow().find_metadata_for_unique_id(unique_type_id) @@ -656,10 +637,8 @@ pub fn type_metadata<'ll, 'tcx>( ty::Tuple(elements) if elements.is_empty() => { MetadataCreationResult::new(basic_type_metadata(cx, t), false) } - ty::Array(typ, _) | ty::Slice(typ) => { - fixed_vec_metadata(cx, unique_type_id, t, typ, usage_site_span) - } - ty::Str => fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8, usage_site_span), + ty::Array(typ, _) | ty::Slice(typ) => fixed_vec_metadata(cx, unique_type_id, t, typ), + ty::Str => fixed_vec_metadata(cx, unique_type_id, t, cx.tcx.types.i8), ty::Dynamic(..) => { MetadataCreationResult::new(trait_pointer_metadata(cx, t, None, unique_type_id), false) } @@ -710,8 +689,7 @@ pub fn type_metadata<'ll, 'tcx>( type_map.borrow_mut().register_type_with_metadata(t, temp_type); let fn_metadata = - subroutine_type_metadata(cx, unique_type_id, t.fn_sig(cx.tcx), usage_site_span) - .metadata; + subroutine_type_metadata(cx, unique_type_id, t.fn_sig(cx.tcx)).metadata; type_map.borrow_mut().remove_type(t); @@ -721,15 +699,8 @@ pub fn type_metadata<'ll, 'tcx>( ty::Closure(def_id, substs) => { let upvar_tys: Vec<_> = substs.as_closure().upvar_tys().collect(); let containing_scope = get_namespace_for_item(cx, def_id); - prepare_tuple_metadata( - cx, - t, - &upvar_tys, - unique_type_id, - usage_site_span, - Some(containing_scope), - ) - .finalize(cx) + prepare_tuple_metadata(cx, t, &upvar_tys, unique_type_id, Some(containing_scope)) + .finalize(cx) } ty::Generator(def_id, substs, _) => { let upvar_tys: Vec<_> = substs @@ -737,25 +708,18 @@ pub fn type_metadata<'ll, 'tcx>( .prefix_tys() .map(|t| cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), t)) .collect(); - prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span, upvar_tys) - .finalize(cx) + prepare_enum_metadata(cx, t, def_id, unique_type_id, upvar_tys).finalize(cx) } ty::Adt(def, ..) => match def.adt_kind() { - AdtKind::Struct => { - prepare_struct_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx) - } - AdtKind::Union => { - prepare_union_metadata(cx, t, unique_type_id, usage_site_span).finalize(cx) - } + AdtKind::Struct => prepare_struct_metadata(cx, t, unique_type_id).finalize(cx), + AdtKind::Union => prepare_union_metadata(cx, t, unique_type_id).finalize(cx), AdtKind::Enum => { - prepare_enum_metadata(cx, t, def.did, unique_type_id, usage_site_span, vec![]) - .finalize(cx) + prepare_enum_metadata(cx, t, def.did, unique_type_id, vec![]).finalize(cx) } }, ty::Tuple(elements) => { let tys: Vec<_> = elements.iter().map(|k| k.expect_ty()).collect(); - prepare_tuple_metadata(cx, t, &tys, unique_type_id, usage_site_span, NO_SCOPE_METADATA) - .finalize(cx) + prepare_tuple_metadata(cx, t, &tys, unique_type_id, NO_SCOPE_METADATA).finalize(cx) } // Type parameters from polymorphized functions. ty::Param(_) => MetadataCreationResult::new(param_type_metadata(cx, t), false), @@ -770,8 +734,7 @@ pub fn type_metadata<'ll, 'tcx>( let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) { Some(metadata) => metadata, None => { - span_bug!( - usage_site_span, + bug!( "expected type metadata for unique \ type ID '{}' to already be in \ the `debuginfo::TypeMap` but it \ @@ -785,8 +748,7 @@ pub fn type_metadata<'ll, 'tcx>( match type_map.find_metadata_for_type(t) { Some(metadata) => { if metadata != metadata_for_uid { - span_bug!( - usage_site_span, + bug!( "mismatch between `Ty` and \ `UniqueTypeId` maps in \ `debuginfo::TypeMap`. \ @@ -1283,7 +1245,6 @@ impl<'ll, 'tcx> MemberDescriptionFactory<'ll, 'tcx> { struct StructMemberDescriptionFactory<'tcx> { ty: Ty<'tcx>, variant: &'tcx ty::VariantDef, - span: Span, } impl<'tcx> StructMemberDescriptionFactory<'tcx> { @@ -1305,7 +1266,7 @@ impl<'tcx> StructMemberDescriptionFactory<'tcx> { let field = layout.field(cx, i); MemberDescription { name, - type_metadata: type_metadata(cx, field.ty, self.span), + type_metadata: type_metadata(cx, field.ty), offset: layout.fields.offset(i), size: field.size, align: field.align.abi, @@ -1322,7 +1283,6 @@ fn prepare_struct_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, struct_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - span: Span, ) -> RecursiveTypeDescription<'ll, 'tcx> { let struct_name = compute_debuginfo_type_name(cx.tcx, struct_type, false); @@ -1348,7 +1308,7 @@ fn prepare_struct_metadata<'ll, 'tcx>( unique_type_id, struct_metadata_stub, struct_metadata_stub, - StructMDF(StructMemberDescriptionFactory { ty: struct_type, variant, span }), + StructMDF(StructMemberDescriptionFactory { ty: struct_type, variant }), ) } @@ -1385,7 +1345,6 @@ fn closure_saved_names_of_captured_variables(tcx: TyCtxt<'_>, def_id: DefId) -> struct TupleMemberDescriptionFactory<'tcx> { ty: Ty<'tcx>, component_types: Vec<Ty<'tcx>>, - span: Span, } impl<'tcx> TupleMemberDescriptionFactory<'tcx> { @@ -1412,7 +1371,7 @@ impl<'tcx> TupleMemberDescriptionFactory<'tcx> { }; MemberDescription { name, - type_metadata: type_metadata(cx, component_type, self.span), + type_metadata: type_metadata(cx, component_type), offset: layout.fields.offset(i), size, align, @@ -1430,7 +1389,6 @@ fn prepare_tuple_metadata<'ll, 'tcx>( tuple_type: Ty<'tcx>, component_types: &[Ty<'tcx>], unique_type_id: UniqueTypeId, - span: Span, containing_scope: Option<&'ll DIScope>, ) -> RecursiveTypeDescription<'ll, 'tcx> { let tuple_name = compute_debuginfo_type_name(cx.tcx, tuple_type, false); @@ -1453,7 +1411,6 @@ fn prepare_tuple_metadata<'ll, 'tcx>( TupleMDF(TupleMemberDescriptionFactory { ty: tuple_type, component_types: component_types.to_vec(), - span, }), ) } @@ -1465,7 +1422,6 @@ fn prepare_tuple_metadata<'ll, 'tcx>( struct UnionMemberDescriptionFactory<'tcx> { layout: TyAndLayout<'tcx>, variant: &'tcx ty::VariantDef, - span: Span, } impl<'tcx> UnionMemberDescriptionFactory<'tcx> { @@ -1481,7 +1437,7 @@ impl<'tcx> UnionMemberDescriptionFactory<'tcx> { let field = self.layout.field(cx, i); MemberDescription { name: f.name.to_string(), - type_metadata: type_metadata(cx, field.ty, self.span), + type_metadata: type_metadata(cx, field.ty), offset: Size::ZERO, size: field.size, align: field.align.abi, @@ -1498,7 +1454,6 @@ fn prepare_union_metadata<'ll, 'tcx>( cx: &CodegenCx<'ll, 'tcx>, union_type: Ty<'tcx>, unique_type_id: UniqueTypeId, - span: Span, ) -> RecursiveTypeDescription<'ll, 'tcx> { let union_name = compute_debuginfo_type_name(cx.tcx, union_type, false); @@ -1518,7 +1473,7 @@ fn prepare_union_metadata<'ll, 'tcx>( unique_type_id, union_metadata_stub, union_metadata_stub, - UnionMDF(UnionMemberDescriptionFactory { layout: cx.layout_of(union_type), variant, span }), + UnionMDF(UnionMemberDescriptionFactory { layout: cx.layout_of(union_type), variant }), ) } @@ -1573,7 +1528,6 @@ struct EnumMemberDescriptionFactory<'ll, 'tcx> { layout: TyAndLayout<'tcx>, tag_type_metadata: Option<&'ll DIType>, common_members: Vec<Option<&'ll DIType>>, - span: Span, } impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { @@ -1605,7 +1559,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { // msvc, then we need to use a different, fallback encoding of the debuginfo. let fallback = cpp_like_debuginfo(cx.tcx); // This will always find the metadata in the type map. - let self_metadata = type_metadata(cx, self.enum_type, self.span); + let self_metadata = type_metadata(cx, self.enum_type); match self.layout.variants { Variants::Single { index } => { @@ -1617,7 +1571,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { let variant_info = variant_info_for(index); let (variant_type_metadata, member_description_factory) = - describe_enum_variant(cx, self.layout, variant_info, self_metadata, self.span); + describe_enum_variant(cx, self.layout, variant_info, self_metadata); let member_descriptions = member_description_factory.create_member_descriptions(cx); @@ -1682,13 +1636,8 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { .map(|(i, _)| { let variant = self.layout.for_variant(cx, i); let variant_info = variant_info_for(i); - let (variant_type_metadata, member_desc_factory) = describe_enum_variant( - cx, - variant, - variant_info, - self_metadata, - self.span, - ); + let (variant_type_metadata, member_desc_factory) = + describe_enum_variant(cx, variant, variant_info, self_metadata); let member_descriptions = member_desc_factory.create_member_descriptions(cx); @@ -1807,7 +1756,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { tag.value.size(cx).bits(), tag.value.align(cx).abi.bits() as u32, create_DIArray(DIB(cx), &tags), - type_metadata(cx, discr_enum_ty, self.span), + type_metadata(cx, discr_enum_ty), true, ) }; @@ -1818,7 +1767,6 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { dataful_variant_layout, variant_info, self_metadata, - self.span, ); let member_descriptions = member_desc_factory.create_member_descriptions(cx); @@ -1864,13 +1812,7 @@ impl<'ll, 'tcx> EnumMemberDescriptionFactory<'ll, 'tcx> { let variant = self.layout.for_variant(cx, i); let variant_info = variant_info_for(i); let (variant_type_metadata, member_desc_factory) = - describe_enum_variant( - cx, - variant, - variant_info, - self_metadata, - self.span, - ); + describe_enum_variant(cx, variant, variant_info, self_metadata); let member_descriptions = member_desc_factory.create_member_descriptions(cx); @@ -1908,7 +1850,6 @@ struct VariantMemberDescriptionFactory<'tcx> { /// Cloned from the `layout::Struct` describing the variant. offsets: Vec<Size>, args: Vec<(String, Ty<'tcx>)>, - span: Span, } impl<'tcx> VariantMemberDescriptionFactory<'tcx> { @@ -1923,7 +1864,7 @@ impl<'tcx> VariantMemberDescriptionFactory<'tcx> { let (size, align) = cx.size_and_align_of(ty); MemberDescription { name: name.to_string(), - type_metadata: type_metadata(cx, ty, self.span), + type_metadata: type_metadata(cx, ty), offset: self.offsets[i], size, align, @@ -2011,7 +1952,6 @@ fn describe_enum_variant<'ll, 'tcx>( layout: layout::TyAndLayout<'tcx>, variant: VariantInfo<'_, 'tcx>, containing_scope: &'ll DIScope, - span: Span, ) -> (&'ll DICompositeType, MemberDescriptionFactory<'ll, 'tcx>) { let metadata_stub = variant.map_struct_name(|variant_name| { let unique_type_id = debug_context(cx) @@ -2033,8 +1973,7 @@ fn describe_enum_variant<'ll, 'tcx>( .map(|i| (variant.field_name(i), layout.field(cx, i).ty)) .collect(); - let member_description_factory = - VariantMDF(VariantMemberDescriptionFactory { offsets, args, span }); + let member_description_factory = VariantMDF(VariantMemberDescriptionFactory { offsets, args }); (metadata_stub, member_description_factory) } @@ -2044,7 +1983,6 @@ fn prepare_enum_metadata<'ll, 'tcx>( enum_type: Ty<'tcx>, enum_def_id: DefId, unique_type_id: UniqueTypeId, - span: Span, outer_field_tys: Vec<Ty<'tcx>>, ) -> RecursiveTypeDescription<'ll, 'tcx> { let tcx = cx.tcx; @@ -2109,8 +2047,7 @@ fn prepare_enum_metadata<'ll, 'tcx>( Some(discriminant_type_metadata) => discriminant_type_metadata, None => { let (discriminant_size, discriminant_align) = (discr.size(cx), discr.align(cx)); - let discriminant_base_type_metadata = - type_metadata(cx, discr.to_ty(tcx), rustc_span::DUMMY_SP); + let discriminant_base_type_metadata = type_metadata(cx, discr.to_ty(tcx)); let item_name; let discriminant_name = match enum_type.kind() { @@ -2202,7 +2139,6 @@ fn prepare_enum_metadata<'ll, 'tcx>( layout, tag_type_metadata: discriminant_type_metadata, common_members: vec![], - span, }), ); } @@ -2272,11 +2208,8 @@ fn prepare_enum_metadata<'ll, 'tcx>( let outer_fields = match layout.variants { Variants::Single { .. } => vec![], Variants::Multiple { .. } => { - let tuple_mdf = TupleMemberDescriptionFactory { - ty: enum_type, - component_types: outer_field_tys, - span, - }; + let tuple_mdf = + TupleMemberDescriptionFactory { ty: enum_type, component_types: outer_field_tys }; tuple_mdf .create_member_descriptions(cx) .into_iter() @@ -2352,7 +2285,6 @@ fn prepare_enum_metadata<'ll, 'tcx>( layout, tag_type_metadata: None, common_members: outer_fields, - span, }), ) } @@ -2368,11 +2300,6 @@ fn composite_type_metadata<'ll, 'tcx>( composite_type_unique_id: UniqueTypeId, member_descriptions: Vec<MemberDescription<'ll>>, containing_scope: Option<&'ll DIScope>, - - // Ignore source location information as long as it - // can't be reconstructed for non-local crates. - _file_metadata: &'ll DIFile, - _definition_span: Span, ) -> &'ll DICompositeType { // Create the (empty) struct metadata node ... let composite_type_metadata = create_struct_stub( @@ -2450,8 +2377,7 @@ fn compute_type_parameters<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) - if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); - let actual_type_metadata = - type_metadata(cx, actual_type, rustc_span::DUMMY_SP); + let actual_type_metadata = type_metadata(cx, actual_type); let name = name.as_str(); Some(unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( @@ -2593,7 +2519,7 @@ pub fn create_global_var_metadata<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId, g let is_local_to_unit = is_node_local_to_unit(cx, def_id); let variable_type = Instance::mono(cx.tcx, def_id).ty(cx.tcx, ty::ParamEnv::reveal_all()); - let type_metadata = type_metadata(cx, variable_type, span); + let type_metadata = type_metadata(cx, variable_type); let var_name = tcx.item_name(def_id); let var_name = var_name.as_str(); let linkage_name = mangled_name_of_instance(cx, Instance::mono(tcx, def_id)).name; @@ -2648,7 +2574,7 @@ fn vtable_type_metadata<'ll, 'tcx>( // 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); - type_metadata(cx, vtable_type, rustc_span::DUMMY_SP) + type_metadata(cx, vtable_type) } /// Creates debug information for the given vtable, which is for the diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index d1cea147a7a..61e49fab6ff 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -390,7 +390,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { signature.push(if fn_abi.ret.is_ignore() { None } else { - Some(type_metadata(cx, fn_abi.ret.layout.ty, rustc_span::DUMMY_SP)) + Some(type_metadata(cx, fn_abi.ret.layout.ty)) }); // Arguments types @@ -415,15 +415,11 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { } _ => t, }; - Some(type_metadata(cx, t, rustc_span::DUMMY_SP)) + Some(type_metadata(cx, t)) })); } else { - signature.extend( - fn_abi - .args - .iter() - .map(|arg| Some(type_metadata(cx, arg.layout.ty, rustc_span::DUMMY_SP))), - ); + signature + .extend(fn_abi.args.iter().map(|arg| Some(type_metadata(cx, arg.layout.ty)))); } create_DIArray(DIB(cx), &signature[..]) @@ -453,8 +449,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if let GenericArgKind::Type(ty) = kind.unpack() { let actual_type = cx.tcx.normalize_erasing_regions(ParamEnv::reveal_all(), ty); - let actual_type_metadata = - type_metadata(cx, actual_type, rustc_span::DUMMY_SP); + let actual_type_metadata = type_metadata(cx, actual_type); let name = name.as_str(); Some(unsafe { Some(llvm::LLVMRustDIBuilderCreateTemplateTypeParameter( @@ -509,7 +504,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if cx.sess().opts.debuginfo == DebugInfo::Full && !impl_self_ty.needs_subst() { - Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP)) + Some(type_metadata(cx, impl_self_ty)) } else { Some(namespace::item_namespace(cx, def.did)) } @@ -584,7 +579,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { let loc = self.lookup_debug_loc(span.lo()); let file_metadata = file_metadata(self, &loc.file); - let type_metadata = type_metadata(self, variable_type, span); + let type_metadata = type_metadata(self, variable_type); let (argument_index, dwarf_tag) = match variable_kind { ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable), diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index bc8d7b3e9e2..a1c7d2b4f61 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2320,7 +2320,6 @@ extern "C" { pub fn LLVMRustSetNormalizedTarget(M: &Module, triple: *const c_char); pub fn LLVMRustAddAlwaysInlinePass(P: &PassManagerBuilder, AddLifetimes: bool); pub fn LLVMRustRunRestrictionPass(M: &Module, syms: *const *const c_char, len: size_t); - pub fn LLVMRustMarkAllFunctionsNounwind(M: &Module); pub fn LLVMRustOpenArchive(path: *const c_char) -> Option<&'static mut Archive>; pub fn LLVMRustArchiveIteratorNew(AR: &Archive) -> &mut ArchiveIterator<'_>; diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index bea454458c4..540979ce02d 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -32,7 +32,7 @@ use rustc_session::Session; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span}; -use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet}; +use rustc_target::spec::{MergeFunctions, SanitizerSet}; use std::any::Any; use std::fs; @@ -313,7 +313,6 @@ pub struct CodegenContext<B: WriteBackendMethods> { pub backend: B, pub prof: SelfProfilerRef, pub lto: Lto, - pub no_landing_pads: bool, pub save_temps: bool, pub fewer_names: bool, pub time_trace: bool, @@ -1039,7 +1038,6 @@ fn start_executing_work<B: ExtraBackendMethods>( crate_types: sess.crate_types().to_vec(), each_linked_rlib_for_lto, lto: sess.lto(), - no_landing_pads: sess.panic_strategy() == PanicStrategy::Abort, fewer_names: sess.fewer_names(), save_temps: sess.opts.cg.save_temps, time_trace: sess.opts.debugging_opts.llvm_time_trace, diff --git a/compiler/rustc_error_codes/src/error_codes/E0038.md b/compiler/rustc_error_codes/src/error_codes/E0038.md index ca2eaa54057..584b78554ef 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0038.md +++ b/compiler/rustc_error_codes/src/error_codes/E0038.md @@ -15,7 +15,7 @@ Two general aspects of trait object types give rise to the restrictions: these types can only be accessed through pointers, such as `&dyn Trait` or `Box<dyn Trait>`. The size of such a pointer is known, but the size of the `dyn Trait` object pointed-to by the pointer is _opaque_ to code working - with it, and different tait objects with the same trait object type may + with it, and different trait objects with the same trait object type may have different sizes. 2. The pointer used to access a trait object is paired with an extra pointer @@ -167,7 +167,7 @@ implementation on-demand. If you call `foo()` with a `bool` parameter, the compiler will only generate code for `foo::<bool>()`. When we have additional type parameters, the number of monomorphized implementations the compiler generates does not grow drastically, since the compiler will only generate an -implementation if the function is called with unparametrized substitutions +implementation if the function is called with unparameterized substitutions (i.e., substitutions where none of the substituted types are themselves parameterized). diff --git a/compiler/rustc_error_codes/src/error_codes/E0183.md b/compiler/rustc_error_codes/src/error_codes/E0183.md index 7e1d08daae1..92fa4c7c21e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0183.md +++ b/compiler/rustc_error_codes/src/error_codes/E0183.md @@ -1,4 +1,4 @@ -Manual implemetation of a `Fn*` trait. +Manual implementation of a `Fn*` trait. Erroneous code example: @@ -33,7 +33,7 @@ impl FnOnce<()> for MyClosure { // ok! } ``` -The argumements must be a tuple representing the argument list. +The arguments must be a tuple representing the argument list. For more info, see the [tracking issue][iss29625]: [iss29625]: https://github.com/rust-lang/rust/issues/29625 diff --git a/compiler/rustc_error_codes/src/error_codes/E0521.md b/compiler/rustc_error_codes/src/error_codes/E0521.md index 65dcac983ac..fedf6365fb5 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0521.md +++ b/compiler/rustc_error_codes/src/error_codes/E0521.md @@ -10,7 +10,7 @@ let _add = |el: &str| { }; ``` -A type anotation of a closure parameter implies a new lifetime declaration. +A type annotation of a closure parameter implies a new lifetime declaration. Consider to drop it, the compiler is reliably able to infer them. ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0581.md b/compiler/rustc_error_codes/src/error_codes/E0581.md index 89f6e3269ec..02468dd9466 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0581.md +++ b/compiler/rustc_error_codes/src/error_codes/E0581.md @@ -10,7 +10,7 @@ fn main() { } ``` -The problem here is that the lifetime isn't contrained by any of the arguments, +The problem here is that the lifetime isn't constrained by any of the arguments, making it impossible to determine how long it's supposed to live. To fix this issue, either use the lifetime in the arguments, or use the diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 46817bc9c3f..5309f217b4a 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -682,6 +682,12 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "the `#[rustc_skip_array_during_method_dispatch]` attribute is used to exclude a trait \ from method dispatch when the receiver is an array, for compatibility in editions < 2021." ), + rustc_attr!( + rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."), ErrorFollowing, + "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \ + definition of a trait, it's currently in experimental form and should be changed before \ + being exposed outside of the std" + ), // ========================================================================== // Internal attributes, Testing: diff --git a/compiler/rustc_incremental/src/persist/file_format.rs b/compiler/rustc_incremental/src/persist/file_format.rs index 392c5bdc15a..68180a2214a 100644 --- a/compiler/rustc_incremental/src/persist/file_format.rs +++ b/compiler/rustc_incremental/src/persist/file_format.rs @@ -190,7 +190,7 @@ fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: & fn rustc_version(nightly_build: bool) -> String { if nightly_build { - if let Some(val) = env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") { + if let Some(val) = env::var_os("RUSTC_FORCE_RUSTC_VERSION") { return val.to_string_lossy().into_owned(); } } diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index f06fc3edf58..7030fd53704 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -1168,25 +1168,6 @@ extern "C" void LLVMRustRunRestrictionPass(LLVMModuleRef M, char **Symbols, passes.run(*unwrap(M)); } -extern "C" void LLVMRustMarkAllFunctionsNounwind(LLVMModuleRef M) { - for (Module::iterator GV = unwrap(M)->begin(), E = unwrap(M)->end(); GV != E; - ++GV) { - GV->setDoesNotThrow(); - Function *F = dyn_cast<Function>(GV); - if (F == nullptr) - continue; - - for (Function::iterator B = F->begin(), BE = F->end(); B != BE; ++B) { - for (BasicBlock::iterator I = B->begin(), IE = B->end(); I != IE; ++I) { - if (isa<InvokeInst>(I)) { - InvokeInst *CI = cast<InvokeInst>(I); - CI->setDoesNotThrow(); - } - } - } - } -} - extern "C" void LLVMRustSetDataLayoutFromTargetMachine(LLVMModuleRef Module, LLVMTargetMachineRef TMR) { diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 39aa1844d69..220bc9c5f75 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -820,6 +820,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { data.skip_array_during_method_dispatch, data.specialization_kind, self.def_path_hash(item_id), + data.must_implement_one_of, ) } EntryKind::TraitAlias => ty::TraitDef::new( @@ -831,6 +832,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { false, ty::trait_def::TraitSpecializationKind::None, self.def_path_hash(item_id), + None, ), _ => bug!("def-index does not refer to trait or trait alias"), } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ee6656ce372..ebb78adf343 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1513,6 +1513,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { is_marker: trait_def.is_marker, skip_array_during_method_dispatch: trait_def.skip_array_during_method_dispatch, specialization_kind: trait_def.specialization_kind, + must_implement_one_of: trait_def.must_implement_one_of.clone(), }; EntryKind::Trait(self.lazy(data)) diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 75c5880f05d..8424a31d59f 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -378,6 +378,7 @@ struct TraitData { is_marker: bool, skip_array_during_method_dispatch: bool, specialization_kind: ty::trait_def::TraitSpecializationKind, + must_implement_one_of: Option<Box<[Ident]>>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 34d059f4ec8..9f8053d4a4e 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,7 +1,7 @@ use crate::traits::specialization_graph; use crate::ty::fast_reject::{self, SimplifiedType, SimplifyParams, StripReferences}; use crate::ty::fold::TypeFoldable; -use crate::ty::{Ty, TyCtxt}; +use crate::ty::{Ident, Ty, TyCtxt}; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::definitions::DefPathHash; @@ -44,6 +44,10 @@ pub struct TraitDef { /// The ICH of this trait's DefPath, cached here so it doesn't have to be /// recomputed all the time. pub def_path_hash: DefPathHash, + + /// List of functions from `#[rustc_must_implement_one_of]` attribute one of which + /// must be implemented. + pub must_implement_one_of: Option<Box<[Ident]>>, } /// Whether this trait is treated specially by the standard library @@ -87,6 +91,7 @@ impl<'tcx> TraitDef { skip_array_during_method_dispatch: bool, specialization_kind: TraitSpecializationKind, def_path_hash: DefPathHash, + must_implement_one_of: Option<Box<[Ident]>>, ) -> TraitDef { TraitDef { def_id, @@ -97,6 +102,7 @@ impl<'tcx> TraitDef { skip_array_during_method_dispatch, specialization_kind, def_path_hash, + must_implement_one_of, } } diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 0bba918994c..5390eed89fa 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -176,9 +176,9 @@ impl StableCrateId { // and no -Cmetadata, symbols from the same crate compiled with different versions of // rustc are named the same. // - // RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER is used to inject rustc version information + // RUSTC_FORCE_RUSTC_VERSION is used to inject rustc version information // during testing. - if let Some(val) = std::env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") { + if let Some(val) = std::env::var_os("RUSTC_FORCE_RUSTC_VERSION") { hasher.write(val.to_string_lossy().into_owned().as_bytes()) } else { hasher.write(option_env!("CFG_VERSION").unwrap_or("unknown version").as_bytes()); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8020893e166..21f4312de35 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1162,6 +1162,7 @@ symbols! { rustc_macro_transparency, rustc_main, rustc_mir, + rustc_must_implement_one_of, rustc_nonnull_optimization_guaranteed, rustc_object_lifetime_default, rustc_on_unimplemented, diff --git a/compiler/rustc_typeck/src/check/check.rs b/compiler/rustc_typeck/src/check/check.rs index 7a3d5990329..eb49cc0233d 100644 --- a/compiler/rustc_typeck/src/check/check.rs +++ b/compiler/rustc_typeck/src/check/check.rs @@ -978,6 +978,10 @@ fn check_impl_items_against_trait<'tcx>( if let Ok(ancestors) = trait_def.ancestors(tcx, impl_id.to_def_id()) { // Check for missing items from trait let mut missing_items = Vec::new(); + + let mut must_implement_one_of: Option<&[Ident]> = + trait_def.must_implement_one_of.as_deref(); + for &trait_item_id in tcx.associated_item_def_ids(impl_trait_ref.def_id) { let is_implemented = ancestors .leaf_def(tcx, trait_item_id) @@ -986,12 +990,37 @@ fn check_impl_items_against_trait<'tcx>( if !is_implemented && tcx.impl_defaultness(impl_id).is_final() { missing_items.push(tcx.associated_item(trait_item_id)); } + + if let Some(required_items) = &must_implement_one_of { + // true if this item is specifically implemented in this impl + let is_implemented_here = ancestors + .leaf_def(tcx, trait_item_id) + .map_or(false, |node_item| !node_item.defining_node.is_from_trait()); + + if is_implemented_here { + let trait_item = tcx.associated_item(trait_item_id); + if required_items.contains(&trait_item.ident) { + must_implement_one_of = None; + } + } + } } if !missing_items.is_empty() { let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); missing_items_err(tcx, impl_span, &missing_items, full_impl_span); } + + if let Some(missing_items) = must_implement_one_of { + let impl_span = tcx.sess.source_map().guess_head_span(full_impl_span); + let attr_span = tcx + .get_attrs(impl_trait_ref.def_id) + .iter() + .find(|attr| attr.has_name(sym::rustc_must_implement_one_of)) + .map(|attr| attr.span); + + missing_items_must_implement_one_of_err(tcx, impl_span, missing_items, attr_span); + } } } diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs index 719266ad5a4..059d4a7f3a4 100644 --- a/compiler/rustc_typeck/src/check/mod.rs +++ b/compiler/rustc_typeck/src/check/mod.rs @@ -637,6 +637,31 @@ fn missing_items_err( err.emit(); } +fn missing_items_must_implement_one_of_err( + tcx: TyCtxt<'_>, + impl_span: Span, + missing_items: &[Ident], + annotation_span: Option<Span>, +) { + let missing_items_msg = + missing_items.iter().map(Ident::to_string).collect::<Vec<_>>().join("`, `"); + + let mut err = struct_span_err!( + tcx.sess, + impl_span, + E0046, + "not all trait items implemented, missing one of: `{}`", + missing_items_msg + ); + err.span_label(impl_span, format!("missing one of `{}` in implementation", missing_items_msg)); + + if let Some(annotation_span) = annotation_span { + err.span_note(annotation_span, "required because of this annotation"); + } + + err.emit(); +} + /// Resugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions. fn bounds_from_generic_predicates<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 2ed98e20f1d..314174e0f85 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1190,9 +1190,11 @@ fn super_predicates_that_define_assoc_type( fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { let item = tcx.hir().expect_item(def_id.expect_local()); - let (is_auto, unsafety) = match item.kind { - hir::ItemKind::Trait(is_auto, unsafety, ..) => (is_auto == hir::IsAuto::Yes, unsafety), - hir::ItemKind::TraitAlias(..) => (false, hir::Unsafety::Normal), + let (is_auto, unsafety, items) = match item.kind { + hir::ItemKind::Trait(is_auto, unsafety, .., items) => { + (is_auto == hir::IsAuto::Yes, unsafety, items) + } + hir::ItemKind::TraitAlias(..) => (false, hir::Unsafety::Normal, &[][..]), _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"), }; @@ -1219,6 +1221,103 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { ty::trait_def::TraitSpecializationKind::None }; let def_path_hash = tcx.def_path_hash(def_id); + + let must_implement_one_of = tcx + .get_attrs(def_id) + .iter() + .find(|attr| attr.has_name(sym::rustc_must_implement_one_of)) + // Check that there are at least 2 arguments of `#[rustc_must_implement_one_of]` + // and that they are all identifiers + .and_then(|attr| match attr.meta_item_list() { + Some(items) if items.len() < 2 => { + tcx.sess + .struct_span_err( + attr.span, + "the `#[rustc_must_implement_one_of]` attribute must be \ + used with at least 2 args", + ) + .emit(); + + None + } + Some(items) => items + .into_iter() + .map(|item| item.ident().ok_or(item.span())) + .collect::<Result<Box<[_]>, _>>() + .map_err(|span| { + tcx.sess + .struct_span_err(span, "must be a name of an associated function") + .emit(); + }) + .ok() + .zip(Some(attr.span)), + // Error is reported by `rustc_attr!` + None => None, + }) + // Check that all arguments of `#[rustc_must_implement_one_of]` reference + // functions in the trait with default implementations + .and_then(|(list, attr_span)| { + let errors = list.iter().filter_map(|ident| { + let item = items.iter().find(|item| item.ident == *ident); + + match item { + Some(item) if matches!(item.kind, hir::AssocItemKind::Fn { .. }) => { + if !item.defaultness.has_value() { + tcx.sess + .struct_span_err( + item.span, + "This function doesn't have a default implementation", + ) + .span_note(attr_span, "required by this annotation") + .emit(); + + return Some(()); + } + + return None; + } + Some(item) => tcx + .sess + .struct_span_err(item.span, "Not a function") + .span_note(attr_span, "required by this annotation") + .note( + "All `#[rustc_must_implement_one_of]` arguments \ + must be associated function names", + ) + .emit(), + None => tcx + .sess + .struct_span_err(ident.span, "Function not found in this trait") + .emit(), + } + + Some(()) + }); + + (errors.count() == 0).then_some(list) + }) + // Check for duplicates + .and_then(|list| { + let mut set: FxHashMap<Symbol, Span> = FxHashMap::default(); + let mut no_dups = true; + + for ident in &*list { + if let Some(dup) = set.insert(ident.name, ident.span) { + tcx.sess + .struct_span_err(vec![dup, ident.span], "Functions names are duplicated") + .note( + "All `#[rustc_must_implement_one_of]` arguments \ + must be unique", + ) + .emit(); + + no_dups = false; + } + } + + no_dups.then_some(list) + }); + ty::TraitDef::new( def_id, unsafety, @@ -1228,6 +1327,7 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: DefId) -> ty::TraitDef { skip_array_during_method_dispatch, spec_kind, def_path_hash, + must_implement_one_of, ) } |
