diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index ddba43cd1f16e..6afa649b6de32 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 5c02e3d0fa7c7..3d5fd2f354e55 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>, - 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>, - 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, 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>, ) -> 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>, 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 d1cea147a7a70..61e49fab6ff88 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 bc8d7b3e9e21c..a1c7d2b4f6156 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 bea454458c4c0..540979ce02d8f 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 { 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( 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 ca2eaa54057fa..584b78554ef88 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`. 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::()`. 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 7e1d08daae1f2..92fa4c7c21e72 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 65dcac983acd5..fedf6365fb559 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 89f6e3269ec36..02468dd946646 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 46817bc9c3f08..5309f217b4ada 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 392c5bdc15ad2..68180a2214a50 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 f06fc3edf5859..7030fd53704dd 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(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(I)) { - InvokeInst *CI = cast(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 39aa1844d6911..220bc9c5f752f 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 ee6656ce37265..ebb78adf343ce 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 75c5880f05d92..8424a31d59fce 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>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index 34d059f4ec849..9f8053d4a4eac 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>, } /// 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>, ) -> 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 0bba918994c51..5390eed89fadc 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 8020893e1663c..21f4312de3516 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 7a3d5990329b9..eb49cc0233d83 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 719266ad5a435..059d4a7f3a4bc 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, +) { + let missing_items_msg = + missing_items.iter().map(Ident::to_string).collect::>().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 2ed98e20f1d06..314174e0f8501 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::, _>>() + .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 = 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, ) } diff --git a/library/core/src/num/bignum.rs b/library/core/src/num/bignum.rs index 98d8a8a1d74ae..de85fdd6ed246 100644 --- a/library/core/src/num/bignum.rs +++ b/library/core/src/num/bignum.rs @@ -19,18 +19,8 @@ )] #![macro_use] -use crate::intrinsics; - /// Arithmetic operations required by bignums. pub trait FullOps: Sized { - /// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`, - /// where `W` is the number of bits in `Self`. - fn full_add(self, other: Self, carry: bool) -> (bool /* carry */, Self); - - /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`, - /// where `W` is the number of bits in `Self`. - fn full_mul(self, other: Self, carry: Self) -> (Self /* carry */, Self); - /// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`, /// where `W` is the number of bits in `Self`. fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /* carry */, Self); @@ -45,22 +35,6 @@ macro_rules! impl_full_ops { ($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => ( $( impl FullOps for $ty { - fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) { - // This cannot overflow; the output is between `0` and `2 * 2^nbits - 1`. - // FIXME: will LLVM optimize this into ADC or similar? - let (v, carry1) = intrinsics::add_with_overflow(self, other); - let (v, carry2) = intrinsics::add_with_overflow(v, if carry {1} else {0}); - (carry1 || carry2, v) - } - - fn full_mul(self, other: $ty, carry: $ty) -> ($ty, $ty) { - // This cannot overflow; - // the output is between `0` and `2^nbits * (2^nbits - 1)`. - // FIXME: will LLVM optimize this into ADC or similar? - let v = (self as $bigty) * (other as $bigty) + (carry as $bigty); - ((v >> <$ty>::BITS) as $ty, v as $ty) - } - fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) { // This cannot overflow; // the output is between `0` and `2^nbits * (2^nbits - 1)`. @@ -173,12 +147,11 @@ macro_rules! define_bignum { pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; use crate::iter; - use crate::num::bignum::FullOps; let mut sz = cmp::max(self.size, other.size); let mut carry = false; for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { - let (c, v) = (*a).full_add(*b, carry); + let (v, c) = (*a).carrying_add(*b, carry); *a = v; carry = c; } @@ -191,13 +164,11 @@ macro_rules! define_bignum { } pub fn add_small(&mut self, other: $ty) -> &mut $name { - use crate::num::bignum::FullOps; - - let (mut carry, v) = self.base[0].full_add(other, false); + let (v, mut carry) = self.base[0].carrying_add(other, false); self.base[0] = v; let mut i = 1; while carry { - let (c, v) = self.base[i].full_add(0, carry); + let (v, c) = self.base[i].carrying_add(0, carry); self.base[i] = v; carry = c; i += 1; @@ -212,12 +183,11 @@ macro_rules! define_bignum { pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name { use crate::cmp; use crate::iter; - use crate::num::bignum::FullOps; let sz = cmp::max(self.size, other.size); let mut noborrow = true; for (a, b) in iter::zip(&mut self.base[..sz], &other.base[..sz]) { - let (c, v) = (*a).full_add(!*b, noborrow); + let (v, c) = (*a).carrying_add(!*b, noborrow); *a = v; noborrow = c; } @@ -229,12 +199,10 @@ macro_rules! define_bignum { /// Multiplies itself by a digit-sized `other` and returns its own /// mutable reference. pub fn mul_small(&mut self, other: $ty) -> &mut $name { - use crate::num::bignum::FullOps; - let mut sz = self.size; let mut carry = 0; for a in &mut self.base[..sz] { - let (c, v) = (*a).full_mul(other, carry); + let (v, c) = (*a).carrying_mul(other, carry); *a = v; carry = c; } diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs index a8455fb355b3c..cc26c04a5d42a 100644 --- a/library/core/src/num/int_log10.rs +++ b/library/core/src/num/int_log10.rs @@ -1,141 +1,140 @@ -mod unchecked { - // 0 < val <= u8::MAX - #[inline] - pub const fn u8(val: u8) -> u32 { - let val = val as u32; - - // For better performance, avoid branches by assembling the solution - // in the bits above the low 8 bits. - - // Adding c1 to val gives 10 in the top bits for val < 10, 11 for val >= 10 - const C1: u32 = 0b11_00000000 - 10; // 758 - // Adding c2 to val gives 01 in the top bits for val < 100, 10 for val >= 100 - const C2: u32 = 0b10_00000000 - 100; // 412 - - // Value of top bits: - // +c1 +c2 1&2 - // 0..=9 10 01 00 = 0 - // 10..=99 11 01 01 = 1 - // 100..=255 11 10 10 = 2 - ((val + C1) & (val + C2)) >> 8 - } +/// These functions compute the integer logarithm of their type, assuming +/// that someone has already checked that the the value is strictly positive. + +// 0 < val <= u8::MAX +#[inline] +pub const fn u8(val: u8) -> u32 { + let val = val as u32; + + // For better performance, avoid branches by assembling the solution + // in the bits above the low 8 bits. + + // Adding c1 to val gives 10 in the top bits for val < 10, 11 for val >= 10 + const C1: u32 = 0b11_00000000 - 10; // 758 + // Adding c2 to val gives 01 in the top bits for val < 100, 10 for val >= 100 + const C2: u32 = 0b10_00000000 - 100; // 412 + + // Value of top bits: + // +c1 +c2 1&2 + // 0..=9 10 01 00 = 0 + // 10..=99 11 01 01 = 1 + // 100..=255 11 10 10 = 2 + ((val + C1) & (val + C2)) >> 8 +} - // 0 < val < 100_000 - #[inline] - const fn less_than_5(val: u32) -> u32 { - // Similar to u8, when adding one of these constants to val, - // we get two possible bit patterns above the low 17 bits, - // depending on whether val is below or above the threshold. - const C1: u32 = 0b011_00000000000000000 - 10; // 393206 - const C2: u32 = 0b100_00000000000000000 - 100; // 524188 - const C3: u32 = 0b111_00000000000000000 - 1000; // 916504 - const C4: u32 = 0b100_00000000000000000 - 10000; // 514288 - - // Value of top bits: - // +c1 +c2 1&2 +c3 +c4 3&4 ^ - // 0..=9 010 011 010 110 011 010 000 = 0 - // 10..=99 011 011 011 110 011 010 001 = 1 - // 100..=999 011 100 000 110 011 010 010 = 2 - // 1000..=9999 011 100 000 111 011 011 011 = 3 - // 10000..=99999 011 100 000 111 100 100 100 = 4 - (((val + C1) & (val + C2)) ^ ((val + C3) & (val + C4))) >> 17 - } +// 0 < val < 100_000 +#[inline] +const fn less_than_5(val: u32) -> u32 { + // Similar to u8, when adding one of these constants to val, + // we get two possible bit patterns above the low 17 bits, + // depending on whether val is below or above the threshold. + const C1: u32 = 0b011_00000000000000000 - 10; // 393206 + const C2: u32 = 0b100_00000000000000000 - 100; // 524188 + const C3: u32 = 0b111_00000000000000000 - 1000; // 916504 + const C4: u32 = 0b100_00000000000000000 - 10000; // 514288 + + // Value of top bits: + // +c1 +c2 1&2 +c3 +c4 3&4 ^ + // 0..=9 010 011 010 110 011 010 000 = 0 + // 10..=99 011 011 011 110 011 010 001 = 1 + // 100..=999 011 100 000 110 011 010 010 = 2 + // 1000..=9999 011 100 000 111 011 011 011 = 3 + // 10000..=99999 011 100 000 111 100 100 100 = 4 + (((val + C1) & (val + C2)) ^ ((val + C3) & (val + C4))) >> 17 +} - // 0 < val <= u16::MAX - #[inline] - pub const fn u16(val: u16) -> u32 { - less_than_5(val as u32) - } +// 0 < val <= u16::MAX +#[inline] +pub const fn u16(val: u16) -> u32 { + less_than_5(val as u32) +} - // 0 < val <= u32::MAX - #[inline] - pub const fn u32(mut val: u32) -> u32 { - let mut log = 0; - if val >= 100_000 { - val /= 100_000; - log += 5; - } - log + less_than_5(val) +// 0 < val <= u32::MAX +#[inline] +pub const fn u32(mut val: u32) -> u32 { + let mut log = 0; + if val >= 100_000 { + val /= 100_000; + log += 5; } + log + less_than_5(val) +} - // 0 < val <= u64::MAX - #[inline] - pub const fn u64(mut val: u64) -> u32 { - let mut log = 0; - if val >= 10_000_000_000 { - val /= 10_000_000_000; - log += 10; - } - if val >= 100_000 { - val /= 100_000; - log += 5; - } - log + less_than_5(val as u32) +// 0 < val <= u64::MAX +#[inline] +pub const fn u64(mut val: u64) -> u32 { + let mut log = 0; + if val >= 10_000_000_000 { + val /= 10_000_000_000; + log += 10; } - - // 0 < val <= u128::MAX - #[inline] - pub const fn u128(mut val: u128) -> u32 { - let mut log = 0; - if val >= 100_000_000_000_000_000_000_000_000_000_000 { - val /= 100_000_000_000_000_000_000_000_000_000_000; - log += 32; - return log + u32(val as u32); - } - if val >= 10_000_000_000_000_000 { - val /= 10_000_000_000_000_000; - log += 16; - } - log + u64(val as u64) + if val >= 100_000 { + val /= 100_000; + log += 5; } + log + less_than_5(val as u32) +} - // 0 < val <= i8::MAX - #[inline] - pub const fn i8(val: i8) -> u32 { - u8(val as u8) +// 0 < val <= u128::MAX +#[inline] +pub const fn u128(mut val: u128) -> u32 { + let mut log = 0; + if val >= 100_000_000_000_000_000_000_000_000_000_000 { + val /= 100_000_000_000_000_000_000_000_000_000_000; + log += 32; + return log + u32(val as u32); } - - // 0 < val <= i16::MAX - #[inline] - pub const fn i16(val: i16) -> u32 { - u16(val as u16) + if val >= 10_000_000_000_000_000 { + val /= 10_000_000_000_000_000; + log += 16; } + log + u64(val as u64) +} - // 0 < val <= i32::MAX - #[inline] - pub const fn i32(val: i32) -> u32 { - u32(val as u32) - } +#[cfg(target_pointer_width = "16")] +#[inline] +pub const fn usize(val: usize) -> u32 { + u16(val as _) +} - // 0 < val <= i64::MAX - #[inline] - pub const fn i64(val: i64) -> u32 { - u64(val as u64) - } +#[cfg(target_pointer_width = "32")] +#[inline] +pub const fn usize(val: usize) -> u32 { + u32(val as _) +} - // 0 < val <= i128::MAX - #[inline] - pub const fn i128(val: i128) -> u32 { - u128(val as u128) - } +#[cfg(target_pointer_width = "64")] +#[inline] +pub const fn usize(val: usize) -> u32 { + u64(val as _) +} + +// 0 < val <= i8::MAX +#[inline] +pub const fn i8(val: i8) -> u32 { + u8(val as u8) } -macro_rules! impl_checked { - ($T:ident) => { - #[inline] - pub const fn $T(val: $T) -> Option { - if val > 0 { Some(unchecked::$T(val)) } else { None } - } - }; +// 0 < val <= i16::MAX +#[inline] +pub const fn i16(val: i16) -> u32 { + u16(val as u16) } -impl_checked! { u8 } -impl_checked! { u16 } -impl_checked! { u32 } -impl_checked! { u64 } -impl_checked! { u128 } -impl_checked! { i8 } -impl_checked! { i16 } -impl_checked! { i32 } -impl_checked! { i64 } -impl_checked! { i128 } +// 0 < val <= i32::MAX +#[inline] +pub const fn i32(val: i32) -> u32 { + u32(val as u32) +} + +// 0 < val <= i64::MAX +#[inline] +pub const fn i64(val: i64) -> u32 { + u64(val as u64) +} + +// 0 < val <= i128::MAX +#[inline] +pub const fn i128(val: i128) -> u32 { + u128(val as u128) +} diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 6f7c5a6d11994..79436c8e8ede4 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2362,7 +2362,11 @@ macro_rules! int_impl { without modifying the original"] #[inline] pub const fn checked_log10(self) -> Option { - int_log10::$ActualT(self as $ActualT) + if self > 0 { + Some(int_log10::$ActualT(self as $ActualT)) + } else { + None + } } /// Computes the absolute value of `self`. diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index e3eab07b9df6d..721c030b410ae 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -264,7 +264,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000; #[lang = "u8"] impl u8 { - uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", + uint_impl! { u8, u8, i8, NonZeroU8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } widening_impl! { u8, u16, 8, unsigned } @@ -813,21 +813,21 @@ impl u8 { #[lang = "u16"] impl u16 { - uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + uint_impl! { u16, u16, i16, NonZeroU16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } widening_impl! { u16, u32, 16, unsigned } } #[lang = "u32"] impl u32 { - uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", + uint_impl! { u32, u32, i32, NonZeroU32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } widening_impl! { u32, u64, 32, unsigned } } #[lang = "u64"] impl u64 { - uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", + uint_impl! { u64, u64, i64, NonZeroU64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", @@ -837,7 +837,7 @@ impl u64 { #[lang = "u128"] impl u128 { - uint_impl! { u128, u128, i128, 128, 340282366920938463463374607431768211455, 16, + uint_impl! { u128, u128, i128, NonZeroU128, 128, 340282366920938463463374607431768211455, 16, "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ @@ -850,7 +850,7 @@ impl u128 { #[cfg(target_pointer_width = "16")] #[lang = "usize"] impl usize { - uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + uint_impl! { usize, u16, isize, NonZeroUsize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } widening_impl! { usize, u32, 16, unsigned } @@ -858,7 +858,7 @@ impl usize { #[cfg(target_pointer_width = "32")] #[lang = "usize"] impl usize { - uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", + uint_impl! { usize, u32, isize, NonZeroUsize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } widening_impl! { usize, u64, 32, unsigned } @@ -867,7 +867,7 @@ impl usize { #[cfg(target_pointer_width = "64")] #[lang = "usize"] impl usize { - uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", + uint_impl! { usize, u64, isize, NonZeroUsize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 8f895c33a6328..e21ae48917953 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -302,7 +302,7 @@ nonzero_integers_div! { // A bunch of methods for unsigned nonzero types only. macro_rules! nonzero_unsigned_operations { - ( $( $Ty: ident($Int: ty); )+ ) => { + ( $( $Ty: ident($Int: ident); )+ ) => { $( impl $Ty { /// Add an unsigned integer to a non-zero value. @@ -442,6 +442,56 @@ macro_rules! nonzero_unsigned_operations { None } } + + /// Returns the base 2 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::log2`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(7).unwrap().log2(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(8).unwrap().log2(), 3);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(9).unwrap().log2(), 3);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn log2(self) -> u32 { + <$Int>::BITS - 1 - self.leading_zeros() + } + + /// Returns the base 10 logarithm of the number, rounded down. + /// + /// This is the same operation as + #[doc = concat!("[`", stringify!($Int), "::log10`],")] + /// except that it has no failure cases to worry about + /// since this value can never be zero. + /// + /// # Examples + /// + /// ``` + /// #![feature(int_log)] + #[doc = concat!("# use std::num::", stringify!($Ty), ";")] + /// + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(99).unwrap().log10(), 1);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(100).unwrap().log10(), 2);")] + #[doc = concat!("assert_eq!(", stringify!($Ty), "::new(101).unwrap().log10(), 2);")] + /// ``` + #[unstable(feature = "int_log", issue = "70887")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn log10(self) -> u32 { + super::int_log10::$Int(self.0) + } } )+ } diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 1dd8b0a18ab1b..0bb654977764d 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1,5 +1,6 @@ macro_rules! uint_impl { - ($SelfT:ty, $ActualT:ident, $SignedT:ident, $BITS:expr, $MaxV:expr, + ($SelfT:ty, $ActualT:ident, $SignedT:ident, $NonZeroT:ident, + $BITS:expr, $MaxV:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, $reversed:expr, $le_bytes:expr, $be_bytes:expr, $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { @@ -839,12 +840,10 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn checked_log2(self) -> Option { - if self <= 0 { - None + if let Some(x) = <$NonZeroT>::new(self) { + Some(x.log2()) } else { - // SAFETY: We just checked that this number is positive - let log = (Self::BITS - 1) - unsafe { intrinsics::ctlz_nonzero(self) as u32 }; - Some(log) + None } } @@ -863,7 +862,11 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn checked_log10(self) -> Option { - int_log10::$ActualT(self as $ActualT) + if let Some(x) = <$NonZeroT>::new(self) { + Some(x.log10()) + } else { + None + } } /// Checked negation. Computes `-self`, returning `None` unless `self == diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 69a0304d41d8c..53f7108aca367 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -13,6 +13,7 @@ - [JSON Output](json.md) - [Tests](tests/index.md) - [Platform Support](platform-support.md) + - [Template for target-specific documentation](platform-support/TEMPLATE.md) - [aarch64-apple-ios-sim](platform-support/aarch64-apple-ios-sim.md) - [\*-kmc-solid_\*](platform-support/kmc-solid.md) - [x86_64-unknown-none](platform-support/x86_64-unknown-none.md) diff --git a/src/doc/rustc/src/platform-support/TEMPLATE.md b/src/doc/rustc/src/platform-support/TEMPLATE.md new file mode 100644 index 0000000000000..e64783fcf194a --- /dev/null +++ b/src/doc/rustc/src/platform-support/TEMPLATE.md @@ -0,0 +1,52 @@ +# `target-name-here` + +**Tier: 3** + +One-sentence description of the target (e.g. CPU, OS) + +## Target maintainers + +- Some Person, `email@example.org`, https://github.com/... + +## Requirements + +Does the target support host tools, or only cross-compilation? Does the target +support std, or alloc (either with a default allocator, or if the user supplies +an allocator)? + +Document the expectations of binaries built for the target. Do they assume +specific minimum features beyond the baseline of the CPU/environment/etc? What +version of the OS or environment do they expect? + +Are there notable `#[target_feature(...)]` or `-C target-feature=` values that +programs may wish to use? + +What calling convention does `extern "C"` use on the target? + +What format do binaries use by default? ELF, PE, something else? + +## Building the target + +If Rust doesn't build the target by default, how can users build it? Can users +just add it to the `target` list in `config.toml`? + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for +this target, you will either need to build Rust with the target enabled (see +"Building the target" above), or build your own copy of `core` by using +`build-std` or similar. + +## Testing + +Does the target support running binaries, or do binaries have varying +expectations that prevent having a standard way to run them? If users can run +binaries, can they do so in some common emulator, or do they need native +hardware? Does the target support running the Rust testsuite? + +## Cross-compilation toolchains and C code + +Does the target support C code? If so, what toolchain target should users use +to build compatible C code? (This may match the target triple, or it may be a +toolchain for a different target triple, potentially with specific options or +caveats.) diff --git a/src/doc/rustc/src/target-tier-policy.md b/src/doc/rustc/src/target-tier-policy.md index cc02b294b4469..53d0470fa8135 100644 --- a/src/doc/rustc/src/target-tier-policy.md +++ b/src/doc/rustc/src/target-tier-policy.md @@ -62,13 +62,22 @@ not preclude an existing target's maintainers using issues (on the Rust repository or otherwise) to track requirements that have not yet been met, as appropriate; however, before officially proposing the introduction or promotion of a target, it should meet all of the necessary requirements. A target -proposal is encouraged to quote the corresponding requirements verbatim as part -of explaining how the target meets those requirements. +proposal must quote the corresponding requirements verbatim and respond to them +as part of explaining how the target meets those requirements. (For the +requirements that simply state that the target or the target developers must +not do something, it suffices to acknowledge the requirement.) For a list of all supported targets and their corresponding tiers ("tier 3", "tier 2", "tier 2 with host tools", "tier 1", or "tier 1 with host tools"), see [platform support](platform-support.md). +Several parts of this policy require providing target-specific documentation. +Such documentation should typically appear in a subdirectory of the +platform-support section of this rustc manual, with a link from the target's +entry in [platform support](platform-support.md). Use +[TEMPLATE.md](platform-support/TEMPLATE.md) as a base, and see other +documentation in that directory for examples. + Note that a target must have already received approval for the next lower tier, and spent a reasonable amount of time at that tier, before making a proposal for promotion to the next higher tier; this is true even if a target meets the @@ -139,17 +148,19 @@ approved by the appropriate team for that shared code before acceptance. or binary. In other words, the introduction of the target must not cause a user installing or running a version of Rust or the Rust tools to be subject to any new license requirements. - - If the target supports building host tools (such as `rustc` or `cargo`), - those host tools must not depend on proprietary (non-FOSS) libraries, other - than ordinary runtime libraries supplied by the platform and commonly used - by other binaries built for the target. For instance, `rustc` built for the - target may depend on a common proprietary C runtime library or console - output library, but must not depend on a proprietary code generation - library or code optimization library. Rust's license permits such - combinations, but the Rust project has no interest in maintaining such - combinations within the scope of Rust itself, even at tier 3. - - Targets should not require proprietary (non-FOSS) components to link a - functional binary or library. + - Compiling, linking, and emitting functional binaries, libraries, or other + code for the target (whether hosted on the target itself or cross-compiling + from another target) must not depend on proprietary (non-FOSS) libraries. + Host tools built for the target itself may depend on the ordinary runtime + libraries supplied by the platform and commonly used by other applications + built for the target, but those libraries must not be required for code + generation for the target; cross-compilation to the target must not require + such libraries at all. For instance, `rustc` built for the target may + depend on a common proprietary C runtime library or console output library, + but must not depend on a proprietary code generation library or code + optimization library. Rust's license permits such combinations, but the + Rust project has no interest in maintaining such combinations within the + scope of Rust itself, even at tier 3. - "onerous" here is an intentionally subjective term. At a minimum, "onerous" legal/licensing terms include but are *not* limited to: non-disclosure requirements, non-compete requirements, contributor license agreements @@ -184,9 +195,9 @@ approved by the appropriate team for that shared code before acceptance. target not implementing those portions. - The target must provide documentation for the Rust community explaining how to build for the target, using cross-compilation if possible. If the target - supports running tests (even if they do not pass), the documentation must - explain how to run tests for the target, using emulation if possible or - dedicated hardware if necessary. + supports running binaries, or running tests (even if they do not pass), the + documentation must explain how to run such binaries or tests for the target, + using emulation if possible or dedicated hardware if necessary. - Tier 3 targets must not impose burden on the authors of pull requests, or other developers in the community, to maintain the target. In particular, do not post comments (automated or manual) on a PR that derail or suggest a diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 3fd9c0a194485..a9a3a0af276b1 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -923,9 +923,7 @@ impl LangString { data.original = string.to_owned(); - let tokens = Self::tokens(string).collect::>(); - - for token in tokens { + for token in Self::tokens(string) { match token { "should_panic" => { data.should_panic = true; diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index d7f33d6131c84..7cc0e74a79bcb 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -111,6 +111,12 @@ body { font: 1rem/1.4 "Source Serif 4", NanumBarunGothic, serif; margin: 0; position: relative; + /* We use overflow-wrap: break-word for Safari, which doesn't recognize + `anywhere`: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap */ + overflow-wrap: break-word; + /* Then override it with `anywhere`, which is required to make non-Safari browsers break + more aggressively when we want them to. */ + overflow-wrap: anywhere; -webkit-font-feature-settings: "kern", "liga"; -moz-font-feature-settings: "kern", "liga"; @@ -446,6 +452,7 @@ nav.sub { text-align: center; border-bottom: 1px solid; overflow-wrap: break-word; + overflow-wrap: anywhere; word-wrap: break-word; /* deprecated */ word-break: break-word; /* Chrome, non-standard */ } @@ -576,6 +583,7 @@ nav.sub { } .docblock-short { + overflow-wrap: break-word; overflow-wrap: anywhere; } .docblock-short p { @@ -641,6 +649,7 @@ nav.sub { flex-grow: 1; margin: 0px; padding: 0px; + overflow-wrap: break-word; overflow-wrap: anywhere; } @@ -669,6 +678,7 @@ nav.sub { margin: .5em 0; width: calc(100% - 2px); overflow-x: auto; + overflow-wrap: normal; display: block; } @@ -1495,6 +1505,7 @@ pre.rust { padding: 4px 8px; text-align: center; background: rgba(0,0,0,0); + overflow-wrap: normal; } #theme-choices > button:not(:first-child) { @@ -2099,9 +2110,14 @@ details.rustdoc-toggle[open] > summary.hideme::after { } .docblock code { + overflow-wrap: break-word; overflow-wrap: anywhere; } + .docblock table code { + overflow-wrap: normal; + } + .sub-container { flex-direction: column; } diff --git a/src/test/incremental/cache_file_headers.rs b/src/test/incremental/cache_file_headers.rs index 7f1ef886ac831..9cf611c3379e8 100644 --- a/src/test/incremental/cache_file_headers.rs +++ b/src/test/incremental/cache_file_headers.rs @@ -7,7 +7,7 @@ // The `l33t haxx0r` Rust compiler is known to produce incr. comp. artifacts // that are outrageously incompatible with just about anything, even itself: -//[rpass1] rustc-env:RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER="l33t haxx0r rustc 2.1 LTS" +//[rpass1] rustc-env:RUSTC_FORCE_RUSTC_VERSION="l33t haxx0r rustc 2.1 LTS" // revisions:rpass1 rpass2 // compile-flags: -Z query-dep-graph diff --git a/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile b/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile index fd66702db7f2a..091508cd805b9 100644 --- a/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile +++ b/src/test/run-make-fulldeps/crate-hash-rustc-version/Makefile @@ -27,7 +27,7 @@ all: $(RUSTC) b.rs --extern a=$(TMPDIR)/liba$(EXT) --crate-type=bin -Crpath $(FLAGS) $(call RUN,b) # Now re-compile a.rs with another rustc version - RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER=deadfeed $(RUSTC) a.rs --crate-type=dylib $(FLAGS) + RUSTC_FORCE_RUSTC_VERSION=deadfeed $(RUSTC) a.rs --crate-type=dylib $(FLAGS) # After compiling with a different rustc version, write symbols to disk again. $(NM_CMD) $(call DYLIB,a) > $(TMPDIR)/symbolsafter # As a sanity check, test if the symbols changed: diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of.rs new file mode 100644 index 0000000000000..5ba2f5ce33426 --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of.rs @@ -0,0 +1,44 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(eq, neq)] +trait Equal { + fn eq(&self, other: &Self) -> bool { + !self.neq(other) + } + + fn neq(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +struct T0; +struct T1; +struct T2; +struct T3; + +impl Equal for T0 { + fn eq(&self, _other: &Self) -> bool { + true + } +} + +impl Equal for T1 { + fn neq(&self, _other: &Self) -> bool { + false + } +} + +impl Equal for T2 { + fn eq(&self, _other: &Self) -> bool { + true + } + + fn neq(&self, _other: &Self) -> bool { + false + } +} + +impl Equal for T3 {} +//~^ not all trait items implemented, missing one of: `eq`, `neq` + +fn main() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of.stderr new file mode 100644 index 0000000000000..5a4dd1388b2e0 --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of.stderr @@ -0,0 +1,15 @@ +error[E0046]: not all trait items implemented, missing one of: `eq`, `neq` + --> $DIR/rustc_must_implement_one_of.rs:41:1 + | +LL | impl Equal for T3 {} + | ^^^^^^^^^^^^^^^^^ missing one of `eq`, `neq` in implementation + | +note: required because of this annotation + --> $DIR/rustc_must_implement_one_of.rs:3:1 + | +LL | #[rustc_must_implement_one_of(eq, neq)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0046`. diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs new file mode 100644 index 0000000000000..56e8fcff0fce5 --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.rs @@ -0,0 +1,19 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(a, a)] +//~^ Functions names are duplicated +trait Trait { + fn a() {} +} + +#[rustc_must_implement_one_of(b, a, a, c, b, c)] +//~^ Functions names are duplicated +//~| Functions names are duplicated +//~| Functions names are duplicated +trait Trait1 { + fn a() {} + fn b() {} + fn c() {} +} + +fn main() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr new file mode 100644 index 0000000000000..777beba618277 --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_duplicates.stderr @@ -0,0 +1,34 @@ +error: Functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:3:31 + | +LL | #[rustc_must_implement_one_of(a, a)] + | ^ ^ + | + = note: All `#[rustc_must_implement_one_of]` arguments must be unique + +error: Functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:34 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: All `#[rustc_must_implement_one_of]` arguments must be unique + +error: Functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:31 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: All `#[rustc_must_implement_one_of]` arguments must be unique + +error: Functions names are duplicated + --> $DIR/rustc_must_implement_one_of_duplicates.rs:9:40 + | +LL | #[rustc_must_implement_one_of(b, a, a, c, b, c)] + | ^ ^ + | + = note: All `#[rustc_must_implement_one_of]` arguments must be unique + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.rs new file mode 100644 index 0000000000000..ec2995872de02 --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.rs @@ -0,0 +1,13 @@ +#[rustc_must_implement_one_of(eq, neq)] +//~^ 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 +trait Equal { + fn eq(&self, other: &Self) -> bool { + !self.neq(other) + } + + fn neq(&self, other: &Self) -> bool { + !self.eq(other) + } +} + +fn main() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr new file mode 100644 index 0000000000000..228bc3e35c21d --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_gated.stderr @@ -0,0 +1,11 @@ +error[E0658]: 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 + --> $DIR/rustc_must_implement_one_of_gated.rs:1:1 + | +LL | #[rustc_must_implement_one_of(eq, neq)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs new file mode 100644 index 0000000000000..1089e5f9c4ab9 --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.rs @@ -0,0 +1,38 @@ +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(a, b)] +//~^ Function not found in this trait +//~| Function not found in this trait +trait Tr0 {} + +#[rustc_must_implement_one_of(a, b)] +//~^ Function not found in this trait +trait Tr1 { + fn a() {} +} + +#[rustc_must_implement_one_of(a)] +//~^ the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args +trait Tr2 { + fn a() {} +} + +#[rustc_must_implement_one_of] +//~^ malformed `rustc_must_implement_one_of` attribute input +trait Tr3 {} + +#[rustc_must_implement_one_of(A, B)] +trait Tr4 { + const A: u8 = 1; //~ Not a function + + type B; //~ Not a function +} + +#[rustc_must_implement_one_of(a, b)] +trait Tr5 { + fn a(); //~ This function doesn't have a default implementation + + fn b(); //~ This function doesn't have a default implementation +} + +fn main() {} diff --git a/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr new file mode 100644 index 0000000000000..74a6dc8fec97c --- /dev/null +++ b/src/test/ui/traits/default-method/rustc_must_implement_one_of_misuse.stderr @@ -0,0 +1,82 @@ +error: malformed `rustc_must_implement_one_of` attribute input + --> $DIR/rustc_must_implement_one_of_misuse.rs:20:1 + | +LL | #[rustc_must_implement_one_of] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_must_implement_one_of(function1, function2, ...)]` + +error: Function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:31 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: Function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:3:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: Function not found in this trait + --> $DIR/rustc_must_implement_one_of_misuse.rs:8:34 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^ + +error: the `#[rustc_must_implement_one_of]` attribute must be used with at least 2 args + --> $DIR/rustc_must_implement_one_of_misuse.rs:14:1 + | +LL | #[rustc_must_implement_one_of(a)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Not a function + --> $DIR/rustc_must_implement_one_of_misuse.rs:26:5 + | +LL | const A: u8 = 1; + | ^^^^^^^^^^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1 + | +LL | #[rustc_must_implement_one_of(A, B)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names + +error: Not a function + --> $DIR/rustc_must_implement_one_of_misuse.rs:28:5 + | +LL | type B; + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:24:1 + | +LL | #[rustc_must_implement_one_of(A, B)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: All `#[rustc_must_implement_one_of]` arguments must be associated function names + +error: This function doesn't have a default implementation + --> $DIR/rustc_must_implement_one_of_misuse.rs:33:5 + | +LL | fn a(); + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: This function doesn't have a default implementation + --> $DIR/rustc_must_implement_one_of_misuse.rs:35:5 + | +LL | fn b(); + | ^^^^^^^ + | +note: required by this annotation + --> $DIR/rustc_must_implement_one_of_misuse.rs:31:1 + | +LL | #[rustc_must_implement_one_of(a, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors +