diff options
53 files changed, 1042 insertions, 444 deletions
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 1a96dd8bec4..aabbe8ac276 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -13,7 +13,7 @@ use smallvec::SmallVec; use crate::attributes; use crate::llvm::AttributePlace::Function; -use crate::llvm::{self, Attribute, AttributeKind, AttributePlace}; +use crate::llvm::{self, AllocKindFlags, Attribute, AttributeKind, AttributePlace}; use crate::llvm_util; pub use rustc_attr::{InlineAttr, InstructionSetAttr, OptimizeAttr}; @@ -227,6 +227,10 @@ pub(crate) fn default_optimisation_attrs<'ll>( attrs } +fn create_alloc_family_attr(llcx: &llvm::Context) -> &llvm::Attribute { + llvm::CreateAttrStringValue(llcx, "alloc-family", "__rust_alloc") +} + /// Composite function which sets LLVM attributes for function depending on its AST (`#[attribute]`) /// attributes. pub fn from_fn_attrs<'ll, 'tcx>( @@ -309,11 +313,54 @@ pub fn from_fn_attrs<'ll, 'tcx>( // Need this for AArch64. to_add.push(llvm::CreateAttrStringValue(cx.llcx, "branch-target-enforcement", "false")); } - if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) { + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) + || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR_ZEROED) + { + if llvm_util::get_version() >= (15, 0, 0) { + to_add.push(create_alloc_family_attr(cx.llcx)); + // apply to argument place instead of function + let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx); + attributes::apply_to_llfn(llfn, AttributePlace::Argument(1), &[alloc_align]); + to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 0)); + let mut flags = AllocKindFlags::Alloc | AllocKindFlags::Aligned; + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) { + flags |= AllocKindFlags::Uninitialized; + } else { + flags |= AllocKindFlags::Zeroed; + } + to_add.push(llvm::CreateAllocKindAttr(cx.llcx, flags)); + } // apply to return place instead of function (unlike all other attributes applied in this function) let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx); attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]); } + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::REALLOCATOR) { + if llvm_util::get_version() >= (15, 0, 0) { + to_add.push(create_alloc_family_attr(cx.llcx)); + to_add.push(llvm::CreateAllocKindAttr( + cx.llcx, + AllocKindFlags::Realloc | AllocKindFlags::Aligned, + )); + // applies to argument place instead of function place + let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx); + attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]); + // apply to argument place instead of function + let alloc_align = AttributeKind::AllocAlign.create_attr(cx.llcx); + attributes::apply_to_llfn(llfn, AttributePlace::Argument(2), &[alloc_align]); + to_add.push(llvm::CreateAllocSizeAttr(cx.llcx, 3)); + } + let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx); + attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]); + } + if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::DEALLOCATOR) { + if llvm_util::get_version() >= (15, 0, 0) { + to_add.push(create_alloc_family_attr(cx.llcx)); + to_add.push(llvm::CreateAllocKindAttr(cx.llcx, AllocKindFlags::Free)); + // applies to argument place instead of function place + let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx); + attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]); + } + } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) { to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry")); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs index e2fa5e488ed..45de284d22a 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs @@ -20,19 +20,6 @@ pub enum OptimizationDiagnosticKind { OptimizationRemarkOther, } -impl OptimizationDiagnosticKind { - pub fn describe(self) -> &'static str { - match self { - OptimizationRemark | OptimizationRemarkOther => "remark", - OptimizationMissed => "missed", - OptimizationAnalysis => "analysis", - OptimizationAnalysisFPCommute => "floating-point", - OptimizationAnalysisAliasing => "aliasing", - OptimizationFailure => "failure", - } - } -} - pub struct OptimizationDiagnostic<'ll> { pub kind: OptimizationDiagnosticKind, pub pass_name: String, diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index f64eb79b0a8..9ee6d39fdc9 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -193,6 +193,9 @@ pub enum AttributeKind { SanitizeMemTag = 34, NoCfCheck = 35, ShadowCallStack = 36, + AllocSize = 37, + AllocatedPointer = 38, + AllocAlign = 39, } /// LLVMIntPredicate @@ -569,16 +572,6 @@ pub enum ArchiveKind { K_COFF, } -/// LLVMRustPassKind -#[derive(Copy, Clone, PartialEq, Debug)] -#[repr(C)] -#[allow(dead_code)] // Variants constructed by C++. -pub enum PassKind { - Other, - Function, - Module, -} - // LLVMRustThinLTOData extern "C" { pub type ThinLTOData; @@ -589,10 +582,6 @@ extern "C" { pub type ThinLTOBuffer; } -// LLVMRustModuleNameCallback -pub type ThinLTOModuleNameCallback = - unsafe extern "C" fn(*mut c_void, *const c_char, *const c_char); - /// LLVMRustThinLTOModule #[repr(C)] pub struct ThinLTOModule { @@ -658,9 +647,6 @@ extern "C" { } #[repr(C)] pub struct Builder<'a>(InvariantOpaque<'a>); -extern "C" { - pub type MemoryBuffer; -} #[repr(C)] pub struct PassManager<'a>(InvariantOpaque<'a>); extern "C" { @@ -986,6 +972,22 @@ pub mod debuginfo { } } +use bitflags::bitflags; +// These values **must** match with LLVMRustAllocKindFlags +bitflags! { + #[repr(transparent)] + #[derive(Default)] + pub struct AllocKindFlags : u64 { + const Unknown = 0; + const Alloc = 1; + const Realloc = 1 << 1; + const Free = 1 << 2; + const Uninitialized = 1 << 3; + const Zeroed = 1 << 4; + const Aligned = 1 << 5; + } +} + extern "C" { pub type ModuleBuffer; } @@ -1013,7 +1015,6 @@ extern "C" { pub fn LLVMSetDataLayout(M: &Module, Triple: *const c_char); /// See Module::setModuleInlineAsm. - pub fn LLVMSetModuleInlineAsm2(M: &Module, Asm: *const c_char, AsmLen: size_t); pub fn LLVMRustAppendModuleInlineAsm(M: &Module, Asm: *const c_char, AsmLen: size_t); /// See llvm::LLVMTypeKind::getTypeID. @@ -1167,7 +1168,6 @@ extern "C" { pub fn LLVMGetInitializer(GlobalVar: &Value) -> Option<&Value>; pub fn LLVMSetInitializer<'a>(GlobalVar: &'a Value, ConstantVal: &'a Value); pub fn LLVMIsThreadLocal(GlobalVar: &Value) -> Bool; - pub fn LLVMSetThreadLocal(GlobalVar: &Value, IsThreadLocal: Bool); pub fn LLVMSetThreadLocalMode(GlobalVar: &Value, Mode: ThreadLocalMode); pub fn LLVMIsGlobalConstant(GlobalVar: &Value) -> Bool; pub fn LLVMSetGlobalConstant(GlobalVar: &Value, IsConstant: Bool); @@ -1193,6 +1193,8 @@ extern "C" { pub fn LLVMRustCreateByValAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; pub fn LLVMRustCreateStructRetAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; pub fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute; + pub fn LLVMRustCreateAllocSizeAttr(C: &Context, size_arg: u32) -> &Attribute; + pub fn LLVMRustCreateAllocKindAttr(C: &Context, size_arg: u64) -> &Attribute; // Operations on functions pub fn LLVMRustGetOrInsertFunction<'a>( @@ -2246,7 +2248,6 @@ extern "C" { pub fn LLVMIsAConstantInt(value_ref: &Value) -> Option<&ConstantInt>; - pub fn LLVMRustPassKind(Pass: &Pass) -> PassKind; pub fn LLVMRustFindAndCreatePass(Pass: *const c_char) -> Option<&'static mut Pass>; pub fn LLVMRustCreateAddressSanitizerFunctionPass(Recover: bool) -> &'static mut Pass; pub fn LLVMRustCreateModuleAddressSanitizerPass(Recover: bool) -> &'static mut Pass; @@ -2363,7 +2364,6 @@ extern "C" { ) -> LLVMRustResult; pub fn LLVMRustSetLLVMOptions(Argc: c_int, Argv: *const *const c_char); pub fn LLVMRustPrintPasses(); - pub fn LLVMRustGetInstructionCount(M: &Module) -> u32; 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); @@ -2461,7 +2461,6 @@ extern "C" { pub fn LLVMRustPositionBuilderAtStart<'a>(B: &Builder<'a>, BB: &'a BasicBlock); pub fn LLVMRustSetComdat<'a>(M: &'a Module, V: &'a Value, Name: *const c_char, NameLen: size_t); - pub fn LLVMRustUnsetComdat(V: &Value); pub fn LLVMRustSetModulePICLevel(M: &Module); pub fn LLVMRustSetModulePIELevel(M: &Module); pub fn LLVMRustSetModuleCodeModel(M: &Module, Model: CodeModel); @@ -2493,11 +2492,6 @@ extern "C" { Module: &Module, Target: &TargetMachine, ) -> bool; - pub fn LLVMRustGetThinLTOModuleImports( - Data: *const ThinLTOData, - ModuleNameCallback: ThinLTOModuleNameCallback, - CallbackPayload: *mut c_void, - ); pub fn LLVMRustFreeThinLTOData(Data: &'static mut ThinLTOData); pub fn LLVMRustParseBitcodeForLTO( Context: &Context, diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 48fbc1de8ee..6602a4ab863 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -95,6 +95,14 @@ pub fn CreateUWTableAttr(llcx: &Context, async_: bool) -> &Attribute { unsafe { LLVMRustCreateUWTableAttr(llcx, async_) } } +pub fn CreateAllocSizeAttr(llcx: &Context, size_arg: u32) -> &Attribute { + unsafe { LLVMRustCreateAllocSizeAttr(llcx, size_arg) } +} + +pub fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &Attribute { + unsafe { LLVMRustCreateAllocKindAttr(llcx, kind_arg.bits()) } +} + #[derive(Copy, Clone)] pub enum AttributePlace { ReturnValue, @@ -158,12 +166,6 @@ pub fn SetUniqueComdat(llmod: &Module, val: &Value) { } } -pub fn UnsetComdat(val: &Value) { - unsafe { - LLVMRustUnsetComdat(val); - } -} - pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) { unsafe { LLVMSetUnnamedAddress(global, unnamed); diff --git a/compiler/rustc_error_messages/locales/en-US/passes.ftl b/compiler/rustc_error_messages/locales/en-US/passes.ftl index 04c67cf8ff7..f95e33cd16a 100644 --- a/compiler/rustc_error_messages/locales/en-US/passes.ftl +++ b/compiler/rustc_error_messages/locales/en-US/passes.ftl @@ -149,3 +149,110 @@ passes-cold = {passes-should-be-applied-to-fn} passes-link = attribute should be applied to an `extern` block with non-Rust ABI .warn = {-passes-previously-accepted} .label = not an `extern` block + +passes-link-name = attribute should be applied to a foreign function or static + .warn = {-passes-previously-accepted} + .label = not a foreign function or static + .help = try `#[link(name = "{$value}")]` instead + +passes-no-link = attribute should be applied to an `extern crate` item + .label = not an `extern crate` item + +passes-export-name = attribute should be applied to a free function, impl method or static + .label = not a free function, impl method or static + +passes-rustc-layout-scalar-valid-range-not-struct = attribute should be applied to a struct + .label = not a struct + +passes-rustc-layout-scalar-valid-range-arg = expected exactly one integer literal argument + +passes-rustc-legacy-const-generics-only = #[rustc_legacy_const_generics] functions must only have const generics + .label = non-const generic parameter + +passes-rustc-legacy-const-generics-index = #[rustc_legacy_const_generics] must have one index for each generic parameter + .label = generic parameters + +passes-rustc-legacy-const-generics-index-exceed = index exceeds number of arguments + .label = there {$arg_count -> + [one] is + *[other] are + } only {$arg_count} {$arg_count -> + [one] argument + *[other] arguments + } + +passes-rustc-legacy-const-generics-index-negative = arguments should be non-negative integers + +passes-rustc-dirty-clean = attribute requires -Z query-dep-graph to be enabled + +passes-link-section = attribute should be applied to a function or static + .warn = {-passes-previously-accepted} + .label = not a function or static + +passes-no-mangle-foreign = `#[no_mangle]` has no effect on a foreign {$foreign_item_kind} + .warn = {-passes-previously-accepted} + .label = foreign {$foreign_item_kind} + .note = symbol names in extern blocks are not mangled + .suggestion = remove this attribute + +passes-no-mangle = attribute should be applied to a free function, impl method or static + .warn = {-passes-previously-accepted} + .label = not a free function, impl method or static + +passes-repr-ident = meta item in `repr` must be an identifier + +passes-repr-conflicting = conflicting representation hints + +passes-used-static = attribute must be applied to a `static` variable + +passes-used-compiler-linker = `used(compiler)` and `used(linker)` can't be used together + +passes-allow-internal-unstable = attribute should be applied to a macro + .label = not a macro + +passes-debug-visualizer-placement = attribute should be applied to a module + +passes-debug-visualizer-invalid = invalid argument + .note-1 = expected: `natvis_file = "..."` + .note-2 = OR + .note-3 = expected: `gdb_script_file = "..."` + +passes-rustc-allow-const-fn-unstable = attribute should be applied to `const fn` + .label = not a `const fn` + +passes-rustc-std-internal-symbol = attribute should be applied to functions or statics + .label = not a function or static + +passes-const-trait = attribute should be applied to a trait + +passes-stability-promotable = attribute cannot be applied to an expression + +passes-deprecated = attribute is ignored here + +passes-macro-use = `#[{$name}]` only has an effect on `extern crate` and modules + +passes-macro-export = `#[macro_export]` only has an effect on macro definitions + +passes-plugin-registrar = `#[plugin_registrar]` only has an effect on functions + +passes-unused-empty-lints-note = attribute `{$name}` with an empty list has no effect + +passes-unused-no-lints-note = attribute `{$name}` without any lints has no effect + +passes-unused-default-method-body-const-note = + `default_method_body_is_const` has been replaced with `#[const_trait]` on traits + +passes-unused = unused attribute + .suggestion = remove this attribute + +passes-non-exported-macro-invalid-attrs = attribute should be applied to function or closure + .label = not a function or closure + +passes-unused-duplicate = unused attribute + .suggestion = remove this attribute + .note = attribute also specified here + .warn = {-passes-previously-accepted} + +passes-unused-multiple = multiple `{$name}` attributes + .suggestion = remove this attribute + .note = attribute also specified here diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index c806df82145..7b540e67aab 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -532,6 +532,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_attr!(rustc_allocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), rustc_attr!(rustc_allocator_nounwind, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), + rustc_attr!(rustc_reallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), + rustc_attr!(rustc_deallocator, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), + rustc_attr!(rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing, IMPL_DETAIL), gated!( alloc_error_handler, Normal, template!(Word), WarnFollowing, experimental!(alloc_error_handler) diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index be764cfe83b..39faed0bf36 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2412,9 +2412,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { #[derive(Debug)] enum SubOrigin<'hir> { GAT(&'hir hir::Generics<'hir>), - Impl(&'hir hir::Generics<'hir>), - Trait(&'hir hir::Generics<'hir>), - Fn(&'hir hir::Generics<'hir>), + Impl, + Trait, + Fn, Unknown, } let sub_origin = 'origin: { @@ -2429,34 +2429,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { kind: hir::ImplItemKind::TyAlias(..), generics, .. - }) => SubOrigin::GAT(generics), - Node::ImplItem(hir::ImplItem { - kind: hir::ImplItemKind::Fn(..), - generics, - .. - }) => SubOrigin::Fn(generics), - Node::TraitItem(hir::TraitItem { + }) + | Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Type(..), generics, .. }) => SubOrigin::GAT(generics), - Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(..), - generics, + Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(..), .. - }) => SubOrigin::Fn(generics), - Node::Item(hir::Item { - kind: hir::ItemKind::Trait(_, _, generics, _, _), + }) + | Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(..), .. - }) => SubOrigin::Trait(generics), + }) + | Node::Item(hir::Item { + kind: hir::ItemKind::Fn(..), .. + }) => SubOrigin::Fn, Node::Item(hir::Item { - kind: hir::ItemKind::Impl(hir::Impl { generics, .. }), + kind: hir::ItemKind::Trait(..), .. - }) => SubOrigin::Impl(generics), + }) => SubOrigin::Trait, Node::Item(hir::Item { - kind: hir::ItemKind::Fn(_, generics, _), - .. - }) => SubOrigin::Fn(generics), + kind: hir::ItemKind::Impl(..), .. + }) => SubOrigin::Impl, _ => continue, }; } diff --git a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h index bca5425e728..93f302b44e8 100644 --- a/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h +++ b/compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h @@ -86,6 +86,9 @@ enum LLVMRustAttribute { SanitizeMemTag = 34, NoCfCheck = 35, ShadowCallStack = 36, + AllocSize = 37, + AllocatedPointer = 38, + AllocAlign = 39, }; typedef struct OpaqueRustString *RustStringRef; diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index e0f10f77e89..0a6bd49992d 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -90,23 +90,6 @@ extern "C" void LLVMTimeTraceProfilerFinish(const char* FileName) { timeTraceProfilerCleanup(); } -enum class LLVMRustPassKind { - Other, - Function, - Module, -}; - -static LLVMRustPassKind toRust(PassKind Kind) { - switch (Kind) { - case PT_Function: - return LLVMRustPassKind::Function; - case PT_Module: - return LLVMRustPassKind::Module; - default: - return LLVMRustPassKind::Other; - } -} - extern "C" LLVMPassRef LLVMRustFindAndCreatePass(const char *PassName) { #if LLVM_VERSION_LT(15, 0) StringRef SR(PassName); @@ -172,12 +155,6 @@ extern "C" LLVMPassRef LLVMRustCreateHWAddressSanitizerPass(bool Recover) { #endif } -extern "C" LLVMRustPassKind LLVMRustPassKind(LLVMPassRef RustPass) { - assert(RustPass); - Pass *Pass = unwrap(RustPass); - return toRust(Pass->getPassKind()); -} - extern "C" void LLVMRustAddPass(LLVMPassManagerRef PMR, LLVMPassRef RustPass) { #if LLVM_VERSION_LT(15, 0) assert(RustPass); @@ -1604,28 +1581,6 @@ LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data, LLVMModuleRef M, return true; } -extern "C" typedef void (*LLVMRustModuleNameCallback)(void*, // payload - const char*, // importing module name - const char*); // imported module name - -// Calls `module_name_callback` for each module import done by ThinLTO. -// The callback is provided with regular null-terminated C strings. -extern "C" void -LLVMRustGetThinLTOModules(const LLVMRustThinLTOData *data, - LLVMRustModuleNameCallback module_name_callback, - void* callback_payload) { - for (const auto& importing_module : data->ImportLists) { - const std::string importing_module_id = importing_module.getKey().str(); - const auto& imports = importing_module.getValue(); - for (const auto& imported_module : imports) { - const std::string imported_module_id = imported_module.getKey().str(); - module_name_callback(callback_payload, - importing_module_id.c_str(), - imported_module_id.c_str()); - } - } -} - // This struct and various functions are sort of a hack right now, but the // problem is that we've got in-memory LLVM modules after we generate and // optimize all codegen-units for one compilation in rustc. To be compatible diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 4615558b912..ef1a65488e2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -88,10 +88,6 @@ extern "C" char *LLVMRustGetLastError(void) { return Ret; } -extern "C" unsigned int LLVMRustGetInstructionCount(LLVMModuleRef M) { - return unwrap(M)->getInstructionCount(); -} - extern "C" void LLVMRustSetLastError(const char *Err) { free((void *)LastError); LastError = strdup(Err); @@ -234,6 +230,14 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) { return Attribute::SanitizeMemTag; case ShadowCallStack: return Attribute::ShadowCallStack; + case AllocSize: + return Attribute::AllocSize; +#if LLVM_VERSION_GE(15, 0) + case AllocatedPointer: + return Attribute::AllocatedPointer; + case AllocAlign: + return Attribute::AllocAlign; +#endif } report_fatal_error("bad AttributeKind"); } @@ -305,6 +309,67 @@ extern "C" LLVMAttributeRef LLVMRustCreateUWTableAttr(LLVMContextRef C, bool Asy #endif } +extern "C" LLVMAttributeRef LLVMRustCreateAllocSizeAttr(LLVMContextRef C, uint32_t ElementSizeArg) { + return wrap(Attribute::getWithAllocSizeArgs(*unwrap(C), ElementSizeArg, None)); +} + +#if LLVM_VERSION_GE(15, 0) + +// These values **must** match ffi::AllocKindFlags. +// It _happens_ to match the LLVM values of llvm::AllocFnKind, +// but that's happenstance and we do explicit conversions before +// passing them to LLVM. +enum class LLVMRustAllocKindFlags : uint64_t { + Unknown = 0, + Alloc = 1, + Realloc = 1 << 1, + Free = 1 << 2, + Uninitialized = 1 << 3, + Zeroed = 1 << 4, + Aligned = 1 << 5, +}; + +static LLVMRustAllocKindFlags operator&(LLVMRustAllocKindFlags A, LLVMRustAllocKindFlags B) { + return static_cast<LLVMRustAllocKindFlags>(static_cast<uint64_t>(A) & + static_cast<uint64_t>(B)); +} + +static bool isSet(LLVMRustAllocKindFlags F) { return F != LLVMRustAllocKindFlags::Unknown; } + +static llvm::AllocFnKind allocKindFromRust(LLVMRustAllocKindFlags F) { + llvm::AllocFnKind AFK = llvm::AllocFnKind::Unknown; + if (isSet(F & LLVMRustAllocKindFlags::Alloc)) { + AFK |= llvm::AllocFnKind::Alloc; + } + if (isSet(F & LLVMRustAllocKindFlags::Realloc)) { + AFK |= llvm::AllocFnKind::Realloc; + } + if (isSet(F & LLVMRustAllocKindFlags::Free)) { + AFK |= llvm::AllocFnKind::Free; + } + if (isSet(F & LLVMRustAllocKindFlags::Uninitialized)) { + AFK |= llvm::AllocFnKind::Uninitialized; + } + if (isSet(F & LLVMRustAllocKindFlags::Zeroed)) { + AFK |= llvm::AllocFnKind::Zeroed; + } + if (isSet(F & LLVMRustAllocKindFlags::Aligned)) { + AFK |= llvm::AllocFnKind::Aligned; + } + return AFK; +} +#endif + +extern "C" LLVMAttributeRef LLVMRustCreateAllocKindAttr(LLVMContextRef C, uint64_t AllocKindArg) { +#if LLVM_VERSION_GE(15, 0) + return wrap(Attribute::get(*unwrap(C), Attribute::AllocKind, + static_cast<uint64_t>(allocKindFromRust(static_cast<LLVMRustAllocKindFlags>(AllocKindArg))))); +#else + report_fatal_error( + "allockind attributes are new in LLVM 15 and should not be used on older LLVMs"); +#endif +} + // Enable a fast-math flag // // https://llvm.org/docs/LangRef.html#fast-math-flags @@ -1460,11 +1525,6 @@ extern "C" void LLVMRustSetComdat(LLVMModuleRef M, LLVMValueRef V, } } -extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) { - GlobalObject *GV = unwrap<GlobalObject>(V); - GV->setComdat(nullptr); -} - enum class LLVMRustLinkage { ExternalLinkage = 0, AvailableExternallyLinkage = 1, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 65cae29c58d..6bf237b8ed5 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -375,9 +375,13 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { use std::collections::vec_deque::VecDeque; let mut visible_parent_map: DefIdMap<DefId> = Default::default(); - // This is a secondary visible_parent_map, storing the DefId of parents that re-export - // the child as `_`. Since we prefer parents that don't do this, merge this map at the - // end, only if we're missing any keys from the former. + // This is a secondary visible_parent_map, storing the DefId of + // parents that re-export the child as `_` or module parents + // which are `#[doc(hidden)]`. Since we prefer paths that don't + // do this, merge this map at the end, only if we're missing + // keys from the former. + // This is a rudimentary check that does not catch all cases, + // just the easiest. let mut fallback_map: DefIdMap<DefId> = Default::default(); // Issue 46112: We want the map to prefer the shortest @@ -412,6 +416,11 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { return; } + if ty::util::is_doc_hidden(tcx, parent) { + fallback_map.insert(def_id, parent); + return; + } + match visible_parent_map.entry(def_id) { Entry::Occupied(mut entry) => { // If `child` is defined in crate `cnum`, ensure @@ -439,8 +448,9 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) { } } - // Fill in any missing entries with the (less preferable) path ending in `::_`. - // We still use this path in a diagnostic that suggests importing `::*`. + // Fill in any missing entries with the less preferable path. + // If this path re-exports the child as `_`, we still use this + // path in a diagnostic that suggests importing `::*`. for (child, parent) in fallback_map { visible_parent_map.entry(child).or_insert(parent); } diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index 321fcd43797..45d33a1659f 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -50,7 +50,7 @@ bitflags! { /// the hot path. const COLD = 1 << 0; /// `#[rustc_allocator]`: a hint to LLVM that the pointer returned from this - /// function is never null. + /// function is never null and the function has no side effects other than allocating. const ALLOCATOR = 1 << 1; /// An indicator that function will never unwind. Will become obsolete /// once C-unwind is fully stabilized. @@ -91,6 +91,12 @@ bitflags! { const NO_COVERAGE = 1 << 15; /// `#[used(linker)]`: indicates that LLVM nor the linker can eliminate this function. const USED_LINKER = 1 << 16; + /// `#[rustc_deallocator]`: a hint to LLVM that the function only deallocates memory. + const DEALLOCATOR = 1 << 17; + /// `#[rustc_reallocator]`: a hint to LLVM that the function only reallocates memory. + const REALLOCATOR = 1 << 18; + /// `#[rustc_allocator_zeroed]`: a hint to LLVM that the function only allocates zeroed memory. + const ALLOCATOR_ZEROED = 1 << 19; } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f88997f884a..f3ccbbb5679 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -7,7 +7,7 @@ use crate::errors; use rustc_ast::{ast, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; use rustc_data_structures::fx::FxHashMap; -use rustc_errors::{fluent, pluralize, struct_span_err, Applicability, MultiSpan}; +use rustc_errors::{fluent, struct_span_err, Applicability, MultiSpan}; use rustc_expand::base::resolve_path; use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP}; use rustc_hir as hir; @@ -1180,30 +1180,22 @@ impl CheckAttrVisitor<'_> { _ => { // FIXME: #[cold] was previously allowed on non-functions/statics and some crates // used this, so only emit a warning. - self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - let mut diag = - lint.build("attribute should be applied to a foreign function or static"); - diag.warn( - "this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!", + let attr_span = matches!(target, Target::ForeignMod).then_some(attr.span); + if let Some(s) = attr.value_str() { + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::LinkName { span, attr_span, value: s.as_str() }, ); - - // See issue #47725 - if let Target::ForeignMod = target { - if let Some(value) = attr.value_str() { - diag.span_help( - attr.span, - &format!(r#"try `#[link(name = "{value}")]` instead"#), - ); - } else { - diag.span_help(attr.span, r#"try `#[link(name = "...")]` instead"#); - } - } - - diag.span_label(span, "not a foreign function or static"); - diag.emit(); - }); + } else { + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::LinkName { span, attr_span, value: "..." }, + ); + }; } } } @@ -1221,14 +1213,7 @@ impl CheckAttrVisitor<'_> { true } _ => { - self.tcx - .sess - .struct_span_err( - attr.span, - "attribute should be applied to an `extern crate` item", - ) - .span_label(span, "not an `extern crate` item") - .emit(); + self.tcx.sess.emit_err(errors::NoLink { attr_span: attr.span, span }); false } } @@ -1258,14 +1243,7 @@ impl CheckAttrVisitor<'_> { true } _ => { - self.tcx - .sess - .struct_span_err( - attr.span, - "attribute should be applied to a free function, impl method or static", - ) - .span_label(span, "not a free function, impl method or static") - .emit(); + self.tcx.sess.emit_err(errors::ExportName { attr_span: attr.span, span }); false } } @@ -1278,11 +1256,10 @@ impl CheckAttrVisitor<'_> { target: Target, ) -> bool { if target != Target::Struct { - self.tcx - .sess - .struct_span_err(attr.span, "attribute should be applied to a struct") - .span_label(span, "not a struct") - .emit(); + self.tcx.sess.emit_err(errors::RustcLayoutScalarValidRangeNotStruct { + attr_span: attr.span, + span, + }); return false; } @@ -1293,10 +1270,7 @@ impl CheckAttrVisitor<'_> { if matches!(&list[..], &[NestedMetaItem::Literal(Lit { kind: LitKind::Int(..), .. })]) { true } else { - self.tcx - .sess - .struct_span_err(attr.span, "expected exactly one integer literal argument") - .emit(); + self.tcx.sess.emit_err(errors::RustcLayoutScalarValidRangeArg { attr_span: attr.span }); false } } @@ -1311,11 +1285,10 @@ impl CheckAttrVisitor<'_> { ) -> bool { let is_function = matches!(target, Target::Fn); if !is_function { - self.tcx - .sess - .struct_span_err(attr.span, "attribute should be applied to a function") - .span_label(span, "not a function") - .emit(); + self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { + attr_span: attr.span, + defn_span: span, + }); return false; } @@ -1335,29 +1308,20 @@ impl CheckAttrVisitor<'_> { match param.kind { hir::GenericParamKind::Const { .. } => {} _ => { - self.tcx - .sess - .struct_span_err( - attr.span, - "#[rustc_legacy_const_generics] functions must \ - only have const generics", - ) - .span_label(param.span, "non-const generic parameter") - .emit(); + self.tcx.sess.emit_err(errors::RustcLegacyConstGenericsOnly { + attr_span: attr.span, + param_span: param.span, + }); return false; } } } if list.len() != generics.params.len() { - self.tcx - .sess - .struct_span_err( - attr.span, - "#[rustc_legacy_const_generics] must have one index for each generic parameter", - ) - .span_label(generics.span, "generic parameters") - .emit(); + self.tcx.sess.emit_err(errors::RustcLegacyConstGenericsIndex { + attr_span: attr.span, + generics_span: generics.span, + }); return false; } @@ -1367,19 +1331,10 @@ impl CheckAttrVisitor<'_> { if let Some(LitKind::Int(val, _)) = meta.literal().map(|lit| &lit.kind) { if *val >= arg_count { let span = meta.span(); - self.tcx - .sess - .struct_span_err(span, "index exceeds number of arguments") - .span_label( - span, - format!( - "there {} only {} argument{}", - pluralize!("is", arg_count), - arg_count, - pluralize!(arg_count) - ), - ) - .emit(); + self.tcx.sess.emit_err(errors::RustcLegacyConstGenericsIndexExceed { + span, + arg_count: arg_count as usize, + }); return false; } } else { @@ -1388,10 +1343,7 @@ impl CheckAttrVisitor<'_> { } if !invalid_args.is_empty() { - self.tcx - .sess - .struct_span_err(invalid_args, "arguments should be non-negative integers") - .emit(); + self.tcx.sess.emit_err(errors::RustcLegacyConstGenericsIndexNegative { invalid_args }); false } else { true @@ -1403,11 +1355,10 @@ impl CheckAttrVisitor<'_> { fn check_applied_to_fn_or_method(&self, attr: &Attribute, span: Span, target: Target) -> bool { let is_function = matches!(target, Target::Fn | Target::Method(..)); if !is_function { - self.tcx - .sess - .struct_span_err(attr.span, "attribute should be applied to a function") - .span_label(span, "not a function") - .emit(); + self.tcx.sess.emit_err(errors::AttrShouldBeAppliedToFn { + attr_span: attr.span, + defn_span: span, + }); false } else { true @@ -1437,10 +1388,7 @@ impl CheckAttrVisitor<'_> { if self.tcx.sess.opts.unstable_opts.query_dep_graph { true } else { - self.tcx - .sess - .struct_span_err(attr.span, "attribute requires -Z query-dep-graph to be enabled") - .emit(); + self.tcx.sess.emit_err(errors::RustcDirtyClean { span: attr.span }); false } } @@ -1459,16 +1407,12 @@ impl CheckAttrVisitor<'_> { _ => { // FIXME: #[link_section] was previously allowed on non-functions/statics and some // crates used this, so only emit a warning. - self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - lint.build("attribute should be applied to a function or static") - .warn( - "this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!", - ) - .span_label(span, "not a function or static") - .emit(); - }); + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::LinkSection { span }, + ); } } } @@ -1494,41 +1438,22 @@ impl CheckAttrVisitor<'_> { Target::ForeignStatic => "static", _ => unreachable!(), }; - self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - lint.build(&format!( - "`#[no_mangle]` has no effect on a foreign {foreign_item_kind}" - )) - .warn( - "this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!", - ) - .span_label(span, format!("foreign {foreign_item_kind}")) - .note("symbol names in extern blocks are not mangled") - .span_suggestion( - attr.span, - "remove this attribute", - "", - Applicability::MachineApplicable, - ) - .emit(); - }); + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::NoMangleForeign { span, attr_span: attr.span, foreign_item_kind }, + ); } _ => { // FIXME: #[no_mangle] was previously allowed on non-functions/statics and some // crates used this, so only emit a warning. - self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - lint.build( - "attribute should be applied to a free function, impl method or static", - ) - .warn( - "this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!", - ) - .span_label(span, "not a free function, impl method or static") - .emit(); - }); + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::NoMangle { span }, + ); } } } @@ -1561,13 +1486,7 @@ impl CheckAttrVisitor<'_> { for hint in &hints { if !hint.is_meta_item() { - struct_span_err!( - self.tcx.sess, - hint.span(), - E0565, - "meta item in `repr` must be an identifier" - ) - .emit(); + self.tcx.sess.emit_err(errors::ReprIdent { span: hint.span() }); continue; } @@ -1688,15 +1607,11 @@ impl CheckAttrVisitor<'_> { return false; })) { - self.tcx.struct_span_lint_hir( + self.tcx.emit_spanned_lint( CONFLICTING_REPR_HINTS, hir_id, hint_spans.collect::<Vec<Span>>(), - |lint| { - lint.build("conflicting representation hints") - .code(rustc_errors::error_code!(E0566)) - .emit(); - }, + errors::ReprConflicting, ); } } @@ -1706,9 +1621,7 @@ impl CheckAttrVisitor<'_> { let mut used_compiler_span = None; for attr in attrs.iter().filter(|attr| attr.has_name(sym::used)) { if target != Target::Static { - self.tcx - .sess - .span_err(attr.span, "attribute must be applied to a `static` variable"); + self.tcx.sess.emit_err(errors::UsedStatic { span: attr.span }); } let inner = attr.meta_item_list(); match inner.as_deref() { @@ -1734,14 +1647,9 @@ impl CheckAttrVisitor<'_> { } } if let (Some(linker_span), Some(compiler_span)) = (used_linker_span, used_compiler_span) { - let spans = vec![linker_span, compiler_span]; self.tcx .sess - .struct_span_err( - spans, - "`used(compiler)` and `used(linker)` can't be used together", - ) - .emit(); + .emit_err(errors::UsedCompilerLinker { spans: vec![linker_span, compiler_span] }); } } @@ -1783,9 +1691,7 @@ impl CheckAttrVisitor<'_> { _ => { self.tcx .sess - .struct_span_err(attr.span, "attribute should be applied to a macro") - .span_label(span, "not a macro") - .emit(); + .emit_err(errors::AllowInternalUnstable { attr_span: attr.span, span }); false } } @@ -1796,29 +1702,26 @@ impl CheckAttrVisitor<'_> { match target { Target::Mod => {} _ => { - self.tcx - .sess - .struct_span_err(attr.span, "attribute should be applied to a module") - .emit(); + self.tcx.sess.emit_err(errors::DebugVisualizerPlacement { span: attr.span }); return false; } } let Some(hints) = attr.meta_item_list() else { - self.emit_debugger_visualizer_err(attr.span); + self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span }); return false; }; let hint = match hints.len() { 1 => &hints[0], _ => { - self.emit_debugger_visualizer_err(attr.span); + self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span }); return false; } }; let Some(meta_item) = hint.meta_item() else { - self.emit_debugger_visualizer_err(attr.span); + self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: attr.span }); return false; }; @@ -1826,7 +1729,7 @@ impl CheckAttrVisitor<'_> { (sym::natvis_file, Some(value)) => value, (sym::gdb_script_file, Some(value)) => value, (_, _) => { - self.emit_debugger_visualizer_err(meta_item.span); + self.tcx.sess.emit_err(errors::DebugVisualizerInvalid { span: meta_item.span }); return false; } }; @@ -1855,16 +1758,6 @@ impl CheckAttrVisitor<'_> { } } - fn emit_debugger_visualizer_err(&self, span: Span) { - self.tcx - .sess - .struct_span_err(span, "invalid argument") - .note(r#"expected: `natvis_file = "..."`"#) - .note(r#"OR"#) - .note(r#"expected: `gdb_script_file = "..."`"#) - .emit(); - } - /// Outputs an error for `#[allow_internal_unstable]` which can only be applied to macros. /// (Allows proc_macro functions) fn check_rustc_allow_const_fn_unstable( @@ -1891,9 +1784,7 @@ impl CheckAttrVisitor<'_> { _ => { self.tcx .sess - .struct_span_err(attr.span, "attribute should be applied to `const fn`") - .span_label(span, "not a `const fn`") - .emit(); + .emit_err(errors::RustcAllowConstFnUnstable { attr_span: attr.span, span }); false } } @@ -1910,9 +1801,7 @@ impl CheckAttrVisitor<'_> { _ => { self.tcx .sess - .struct_span_err(attr.span, "attribute should be applied functions or statics") - .span_label(span, "not a function or static") - .emit(); + .emit_err(errors::RustcStdInternalSymbol { attr_span: attr.span, span }); false } } @@ -1923,10 +1812,7 @@ impl CheckAttrVisitor<'_> { match target { Target::Trait => true, _ => { - self.tcx - .sess - .struct_span_err(attr.span, "attribute should be applied to a trait") - .emit(); + self.tcx.sess.emit_err(errors::ConstTrait { attr_span: attr.span }); false } } @@ -1935,10 +1821,7 @@ impl CheckAttrVisitor<'_> { fn check_stability_promotable(&self, attr: &Attribute, _span: Span, target: Target) -> bool { match target { Target::Expression => { - self.tcx - .sess - .struct_span_err(attr.span, "attribute cannot be applied to an expression") - .emit(); + self.tcx.sess.emit_err(errors::StabilityPromotable { attr_span: attr.span }); false } _ => true, @@ -1948,9 +1831,12 @@ impl CheckAttrVisitor<'_> { fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: Span, target: Target) { match target { Target::Closure | Target::Expression | Target::Statement | Target::Arm => { - self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - lint.build("attribute is ignored here").emit(); - }); + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::Deprecated, + ); } _ => {} } @@ -1961,29 +1847,30 @@ impl CheckAttrVisitor<'_> { match target { Target::ExternCrate | Target::Mod => {} _ => { - self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - lint.build(&format!( - "`#[{name}]` only has an effect on `extern crate` and modules" - )) - .emit(); - }); + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::MacroUse { name }, + ); } } } fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) { if target != Target::MacroDef { - self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - lint.build("`#[macro_export]` only has an effect on macro definitions").emit(); - }); + self.tcx.emit_spanned_lint(UNUSED_ATTRIBUTES, hir_id, attr.span, errors::MacroExport); } } fn check_plugin_registrar(&self, hir_id: HirId, attr: &Attribute, target: Target) { if target != Target::Fn { - self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - lint.build("`#[plugin_registrar]` only has an effect on functions").emit(); - }); + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::PluginRegistrar, + ); } } @@ -2002,10 +1889,7 @@ impl CheckAttrVisitor<'_> { | sym::target_feature ) && attr.meta_item_list().map_or(false, |list| list.is_empty()) { - format!( - "attribute `{}` with an empty list has no effect", - attr.name_or_empty() - ) + errors::UnusedNote::EmptyList { name: attr.name_or_empty() } } else if matches!( attr.name_or_empty(), sym::allow | sym::warn | sym::deny | sym::forbid | sym::expect @@ -2015,27 +1899,19 @@ impl CheckAttrVisitor<'_> { && let MetaItemKind::NameValue(_) = &item.kind && item.path == sym::reason { - format!( - "attribute `{}` without any lints has no effect", - attr.name_or_empty() - ) + errors::UnusedNote::NoLints { name: attr.name_or_empty() } } else if attr.name_or_empty() == sym::default_method_body_is_const { - format!("`default_method_body_is_const` has been replaced with `#[const_trait]` on traits") + errors::UnusedNote::DefaultMethodBodyConst } else { return; }; - self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| { - lint.build("unused attribute") - .span_suggestion( - attr.span, - "remove this attribute", - "", - Applicability::MachineApplicable, - ) - .note(¬e) - .emit(); - }); + self.tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + attr.span, + errors::Unused { attr_span: attr.span, note }, + ); } } @@ -2206,14 +2082,7 @@ fn check_non_exported_macro_for_invalid_attrs(tcx: TyCtxt<'_>, item: &Item<'_>) for attr in attrs { if attr.has_name(sym::inline) { - struct_span_err!( - tcx.sess, - attr.span, - E0518, - "attribute should be applied to function or closure", - ) - .span_label(attr.span, "not a function or closure") - .emit(); + tcx.sess.emit_err(errors::NonExportedMacroInvalidAttrs { attr_span: attr.span }); } } } @@ -2253,23 +2122,20 @@ fn check_duplicates( } else { (attr.span, *entry.get()) }; - tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, this, |lint| { - let mut db = lint.build("unused attribute"); - db.span_note(other, "attribute also specified here").span_suggestion( + tcx.emit_spanned_lint( + UNUSED_ATTRIBUTES, + hir_id, + this, + errors::UnusedDuplicate { this, - "remove this attribute", - "", - Applicability::MachineApplicable, - ); - if matches!(duplicates, FutureWarnFollowing | FutureWarnPreceding) { - db.warn( - "this was previously accepted by the compiler but is \ - being phased out; it will become a hard error in \ - a future release!", - ); - } - db.emit(); - }); + other, + warning: matches!( + duplicates, + FutureWarnFollowing | FutureWarnPreceding + ) + .then_some(()), + }, + ); } Entry::Vacant(entry) => { entry.insert(attr.span); @@ -2284,19 +2150,11 @@ fn check_duplicates( } else { (attr.span, *entry.get()) }; - tcx.sess - .struct_span_err( - this, - &format!("multiple `{}` attributes", attr.name_or_empty()), - ) - .span_note(other, "attribute also specified here") - .span_suggestion( - this, - "remove this attribute", - "", - Applicability::MachineApplicable, - ) - .emit(); + tcx.sess.emit_err(errors::UnusedMultiple { + this, + other, + name: attr.name_or_empty(), + }); } Entry::Vacant(entry) => { entry.insert(attr.span); diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index fcd1e9363b1..0d4317f6b88 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1,5 +1,5 @@ use rustc_errors::{Applicability, MultiSpan}; -use rustc_macros::{LintDiagnostic, SessionDiagnostic}; +use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic}; use rustc_span::{Span, Symbol}; #[derive(LintDiagnostic)] @@ -360,3 +360,268 @@ pub struct Link { #[label] pub span: Option<Span>, } + +#[derive(LintDiagnostic)] +#[lint(passes::link_name)] +#[warn_] +pub struct LinkName<'a> { + #[help] + pub attr_span: Option<Span>, + #[label] + pub span: Span, + pub value: &'a str, +} + +#[derive(SessionDiagnostic)] +#[error(passes::no_link)] +pub struct NoLink { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::export_name)] +pub struct ExportName { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::rustc_layout_scalar_valid_range_not_struct)] +pub struct RustcLayoutScalarValidRangeNotStruct { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::rustc_layout_scalar_valid_range_arg)] +pub struct RustcLayoutScalarValidRangeArg { + #[primary_span] + pub attr_span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::rustc_legacy_const_generics_only)] +pub struct RustcLegacyConstGenericsOnly { + #[primary_span] + pub attr_span: Span, + #[label] + pub param_span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::rustc_legacy_const_generics_index)] +pub struct RustcLegacyConstGenericsIndex { + #[primary_span] + pub attr_span: Span, + #[label] + pub generics_span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::rustc_legacy_const_generics_index_exceed)] +pub struct RustcLegacyConstGenericsIndexExceed { + #[primary_span] + #[label] + pub span: Span, + pub arg_count: usize, +} + +#[derive(SessionDiagnostic)] +#[error(passes::rustc_legacy_const_generics_index_negative)] +pub struct RustcLegacyConstGenericsIndexNegative { + #[primary_span] + pub invalid_args: Vec<Span>, +} + +#[derive(SessionDiagnostic)] +#[error(passes::rustc_dirty_clean)] +pub struct RustcDirtyClean { + #[primary_span] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[lint(passes::link_section)] +#[warn_] +pub struct LinkSection { + #[label] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[lint(passes::no_mangle_foreign)] +#[warn_] +#[note] +pub struct NoMangleForeign { + #[label] + pub span: Span, + #[suggestion(applicability = "machine-applicable")] + pub attr_span: Span, + pub foreign_item_kind: &'static str, +} + +#[derive(LintDiagnostic)] +#[lint(passes::no_mangle)] +#[warn_] +pub struct NoMangle { + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::repr_ident, code = "E0565")] +pub struct ReprIdent { + #[primary_span] + pub span: Span, +} + +#[derive(LintDiagnostic)] +#[lint(passes::repr_conflicting, code = "E0566")] +pub struct ReprConflicting; + +#[derive(SessionDiagnostic)] +#[error(passes::used_static)] +pub struct UsedStatic { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::used_compiler_linker)] +pub struct UsedCompilerLinker { + #[primary_span] + pub spans: Vec<Span>, +} + +#[derive(SessionDiagnostic)] +#[error(passes::allow_internal_unstable)] +pub struct AllowInternalUnstable { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::debug_visualizer_placement)] +pub struct DebugVisualizerPlacement { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::debug_visualizer_invalid)] +#[note(passes::note_1)] +#[note(passes::note_2)] +#[note(passes::note_3)] +pub struct DebugVisualizerInvalid { + #[primary_span] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::rustc_allow_const_fn_unstable)] +pub struct RustcAllowConstFnUnstable { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::rustc_std_internal_symbol)] +pub struct RustcStdInternalSymbol { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::const_trait)] +pub struct ConstTrait { + #[primary_span] + pub attr_span: Span, +} + +#[derive(SessionDiagnostic)] +#[error(passes::stability_promotable)] +pub struct StabilityPromotable { + #[primary_span] + pub attr_span: Span, +} + +#[derive(LintDiagnostic)] +#[lint(passes::deprecated)] +pub struct Deprecated; + +#[derive(LintDiagnostic)] +#[lint(passes::macro_use)] +pub struct MacroUse { + pub name: Symbol, +} + +#[derive(LintDiagnostic)] +#[lint(passes::macro_export)] +pub struct MacroExport; + +#[derive(LintDiagnostic)] +#[lint(passes::plugin_registrar)] +pub struct PluginRegistrar; + +#[derive(SessionSubdiagnostic)] +pub enum UnusedNote { + #[note(passes::unused_empty_lints_note)] + EmptyList { name: Symbol }, + #[note(passes::unused_no_lints_note)] + NoLints { name: Symbol }, + #[note(passes::unused_default_method_body_const_note)] + DefaultMethodBodyConst, +} + +#[derive(LintDiagnostic)] +#[lint(passes::unused)] +pub struct Unused { + #[suggestion(applicability = "machine-applicable")] + pub attr_span: Span, + #[subdiagnostic] + pub note: UnusedNote, +} + +#[derive(SessionDiagnostic)] +#[error(passes::non_exported_macro_invalid_attrs, code = "E0518")] +pub struct NonExportedMacroInvalidAttrs { + #[primary_span] + #[label] + pub attr_span: Span, +} + +#[derive(LintDiagnostic)] +#[lint(passes::unused_duplicate)] +pub struct UnusedDuplicate { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub this: Span, + #[note] + pub other: Span, + #[warn_] + pub warning: Option<()>, +} + +#[derive(SessionDiagnostic)] +#[error(passes::unused_multiple)] +pub struct UnusedMultiple { + #[primary_span] + #[suggestion(code = "", applicability = "machine-applicable")] + pub this: Span, + #[note] + pub other: Span, + pub name: Symbol, +} diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 6631470f219..e955a1798b7 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -524,7 +524,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { let crate_root = self.r.resolve_crate_root(source.ident); let crate_name = match crate_root.kind { ModuleKind::Def(.., name) => name, - ModuleKind::Block(..) => unreachable!(), + ModuleKind::Block => unreachable!(), }; // HACK(eddyb) unclear how good this is, but keeping `$crate` // in `source` breaks `src/test/ui/imports/import-crate-var.rs`, @@ -936,7 +936,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> { if self.block_needs_anonymous_module(block) { let module = self.r.new_module( Some(parent), - ModuleKind::Block(block.id), + ModuleKind::Block, expansion.to_expn_id(), block.span, parent.no_implicit_prelude, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 8a655cbf384..0343e8d9b8e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -163,7 +163,7 @@ impl<'a> Resolver<'a> { let container = match parent.kind { ModuleKind::Def(kind, _, _) => kind.descr(parent.def_id()), - ModuleKind::Block(..) => "block", + ModuleKind::Block => "block", }; let old_noun = match old_binding.is_import() { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 0cc6d05d1d0..6e678288142 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -218,7 +218,7 @@ impl<'a> Resolver<'a> { return Some((self.expn_def_scope(ctxt.remove_mark()), None)); } - if let ModuleKind::Block(..) = module.kind { + if let ModuleKind::Block = module.kind { return Some((module.parent.unwrap().nearest_item_scope(), None)); } @@ -333,7 +333,7 @@ impl<'a> Resolver<'a> { }; match module.kind { - ModuleKind::Block(..) => {} // We can see through blocks + ModuleKind::Block => {} // We can see through blocks _ => break, } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index f979403e097..6b49c6b1ac6 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1444,7 +1444,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> { // Items from this module self.r.add_module_candidates(module, &mut names, &filter_fn); - if let ModuleKind::Block(..) = module.kind { + if let ModuleKind::Block = module.kind { // We can see through blocks } else { // Items from the prelude diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 6945306a691..31d10008efb 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -437,7 +437,7 @@ enum ModuleKind { /// f(); // Resolves to (1) /// } /// ``` - Block(NodeId), + Block, /// Any module with a name. /// /// This could be: @@ -454,7 +454,7 @@ impl ModuleKind { /// Get name of the module. pub fn name(&self) -> Option<Symbol> { match self { - ModuleKind::Block(..) => None, + ModuleKind::Block => None, ModuleKind::Def(.., name) => Some(*name), } } @@ -530,7 +530,7 @@ impl<'a> ModuleData<'a> { ) -> Self { let is_foreign = match kind { ModuleKind::Def(_, def_id, _) => !def_id.is_local(), - ModuleKind::Block(_) => false, + ModuleKind::Block => false, }; ModuleData { parent, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 54d67c52541..c75b6772487 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1202,6 +1202,7 @@ symbols! { rustc, rustc_allocator, rustc_allocator_nounwind, + rustc_allocator_zeroed, rustc_allow_const_fn_unstable, rustc_allow_incoherent_impl, rustc_allowed_through_unstable_modules, @@ -1214,6 +1215,7 @@ symbols! { rustc_const_stable, rustc_const_unstable, rustc_conversion_suggestion, + rustc_deallocator, rustc_def_path, rustc_diagnostic_item, rustc_diagnostic_macros, @@ -1258,6 +1260,7 @@ symbols! { rustc_private, rustc_proc_macro_decls, rustc_promotable, + rustc_reallocator, rustc_regions, rustc_reservation_impl, rustc_serialize, diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 0fcbfa734f8..2159cbd3a24 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2775,6 +2775,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs { } } else if attr.has_name(sym::rustc_allocator_nounwind) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND; + } else if attr.has_name(sym::rustc_reallocator) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::REALLOCATOR; + } else if attr.has_name(sym::rustc_deallocator) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::DEALLOCATOR; + } else if attr.has_name(sym::rustc_allocator_zeroed) { + codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED; } else if attr.has_name(sym::naked) { codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED; } else if attr.has_name(sym::no_mangle) { diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index efdc86bf57a..cc8da7bccff 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -25,15 +25,18 @@ extern "Rust" { // (the code expanding that attribute macro generates those functions), or to call // the default implementations in libstd (`__rdl_alloc` etc. in `library/std/src/alloc.rs`) // otherwise. - // The rustc fork of LLVM also special-cases these function names to be able to optimize them + // The rustc fork of LLVM 14 and earlier also special-cases these function names to be able to optimize them // like `malloc`, `realloc`, and `free`, respectively. #[rustc_allocator] #[rustc_allocator_nounwind] fn __rust_alloc(size: usize, align: usize) -> *mut u8; + #[cfg_attr(not(bootstrap), rustc_deallocator)] #[rustc_allocator_nounwind] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); + #[cfg_attr(not(bootstrap), rustc_reallocator)] #[rustc_allocator_nounwind] fn __rust_realloc(ptr: *mut u8, old_size: usize, align: usize, new_size: usize) -> *mut u8; + #[cfg_attr(not(bootstrap), rustc_allocator_zeroed)] #[rustc_allocator_nounwind] fn __rust_alloc_zeroed(size: usize, align: usize) -> *mut u8; } diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 6dc8563c421..234fa213da8 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1000,7 +1000,7 @@ pub fn copy<T: Copy>(x: &T) -> T { /// /// This function will unsafely assume the pointer `src` is valid for [`size_of::<U>`][size_of] /// bytes by transmuting `&T` to `&U` and then reading the `&U` (except that this is done in a way -/// that is correct even when `&U` makes stricter alignment requirements than `&T`). It will also +/// that is correct even when `&U` has stricter alignment requirements than `&T`). It will also /// unsafely create a copy of the contained value instead of moving out of `src`. /// /// It is not a compile-time error if `T` and `U` have different sizes, but it diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 18f7f6a35e9..96addbd1a05 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -898,7 +898,7 @@ pub trait Read { /// use std::fs::File; /// /// fn main() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; + /// let f = File::open("foo.txt")?; /// /// for byte in f.bytes() { /// println!("{}", byte.unwrap()); @@ -932,8 +932,8 @@ pub trait Read { /// use std::fs::File; /// /// fn main() -> io::Result<()> { - /// let mut f1 = File::open("foo.txt")?; - /// let mut f2 = File::open("bar.txt")?; + /// let f1 = File::open("foo.txt")?; + /// let f2 = File::open("bar.txt")?; /// /// let mut handle = f1.chain(f2); /// let mut buffer = String::new(); @@ -973,7 +973,7 @@ pub trait Read { /// use std::fs::File; /// /// fn main() -> io::Result<()> { - /// let mut f = File::open("foo.txt")?; + /// let f = File::open("foo.txt")?; /// let mut buffer = [0; 5]; /// /// // read at most five bytes diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index f15baff59db..a091f06dd53 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -7,6 +7,7 @@ use crate::fs::{self, Metadata, OpenOptions}; use crate::io; use crate::path::Path; +use crate::sealed::Sealed; use crate::sys; use crate::sys_common::{AsInner, AsInnerMut}; @@ -502,17 +503,20 @@ impl MetadataExt for Metadata { /// Windows-specific extensions to [`fs::FileType`]. /// /// On Windows, a symbolic link knows whether it is a file or directory. -#[unstable(feature = "windows_file_type_ext", issue = "none")] -pub trait FileTypeExt { +#[stable(feature = "windows_file_type_ext", since = "1.64.0")] +pub trait FileTypeExt: Sealed { /// Returns `true` if this file type is a symbolic link that is also a directory. - #[unstable(feature = "windows_file_type_ext", issue = "none")] + #[stable(feature = "windows_file_type_ext", since = "1.64.0")] fn is_symlink_dir(&self) -> bool; /// Returns `true` if this file type is a symbolic link that is also a file. - #[unstable(feature = "windows_file_type_ext", issue = "none")] + #[stable(feature = "windows_file_type_ext", since = "1.64.0")] fn is_symlink_file(&self) -> bool; } -#[unstable(feature = "windows_file_type_ext", issue = "none")] +#[stable(feature = "windows_file_type_ext", since = "1.64.0")] +impl Sealed for fs::FileType {} + +#[stable(feature = "windows_file_type_ext", since = "1.64.0")] impl FileTypeExt for fs::FileType { fn is_symlink_dir(&self) -> bool { self.as_inner().is_symlink_dir() diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 3d678b2290d..aa7cda46bda 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -651,6 +651,12 @@ impl Step for Rustc { panic!("Cannot use and generate PGO profiles at the same time"); } + // With LLD, we can use ICF (identical code folding) to reduce the executable size + // of librustc_driver/rustc and to improve i-cache utilization. + if builder.config.use_lld { + cargo.rustflag("-Clink-args=-Wl,--icf=all"); + } + let is_collecting = if let Some(path) = &builder.config.rust_profile_generate { if compiler.stage == 1 { cargo.rustflag(&format!("-Cprofile-generate={}", path)); diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index ab6c888030e..f262bc3c7d8 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -122,7 +122,8 @@ ENV RUST_CONFIGURE_ARGS \ --set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \ --set llvm.thin-lto=true \ --set llvm.ninja=false \ - --set rust.jemalloc + --set rust.jemalloc \ + --set rust.use-lld=true ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ diff --git a/src/ci/pgo.sh b/src/ci/pgo.sh index 28bed1fa035..4773dc09960 100755 --- a/src/ci/pgo.sh +++ b/src/ci/pgo.sh @@ -195,3 +195,7 @@ rm -r $BUILD_ARTIFACTS/llvm $BUILD_ARTIFACTS/lld $@ \ --rust-profile-use=${RUSTC_PROFILE_MERGED_FILE} \ --llvm-profile-use=${LLVM_PROFILE_MERGED_FILE} + +echo "Rustc binary size" +ls -la ./build/$PGO_HOST/stage2/bin +ls -la ./build/$PGO_HOST/stage2/lib diff --git a/src/doc/rustdoc/src/deprecated-features.md b/src/doc/rustdoc/src/deprecated-features.md index 2bc6e8fc8ae..9438948af54 100644 --- a/src/doc/rustdoc/src/deprecated-features.md +++ b/src/doc/rustdoc/src/deprecated-features.md @@ -10,4 +10,4 @@ change in any release. In the past the most common use case for customizing passes was to omit the `strip-private` pass. You can do this more easily, and without risk of the pass being changed, by passing -[`--document-private-items`](./unstable-features.md#--document-private-items). +[`--document-private-items`](command-line-arguments.md#--document-private-items-show-items-that-are-not-public). diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 30b3d6defb4..32b35007490 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -466,7 +466,7 @@ Note that the third item is the crate root, which in this case is undocumented. and is also accepted on stable toolchains. It can also be used with `--show-coverage`. Take a look at its -[documentation](#--show-coverage-get-statistics-about-code-documentation-coverage) for more +[documentation](#--show-coverage-calculate-the-percentage-of-items-with-documentation) for more information. ### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c9ef4748a48..07237438a0d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1993,6 +1993,7 @@ fn clean_maybe_renamed_item<'tcx>( ItemKind::Trait(_, _, generics, bounds, item_ids) => { let items = item_ids.iter().map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx)).collect(); + TraitItem(Trait { def_id, items, diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 4170c73b246..52a2effca0f 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -1485,6 +1485,7 @@ fn init_id_map() -> FxHashMap<Cow<'static, str>, usize> { map.insert("synthetic-implementations-list".into(), 1); map.insert("blanket-implementations-list".into(), 1); map.insert("deref-methods".into(), 1); + map.insert("layout".into(), 1); map } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 81cc12c9d55..69d66693f75 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1,9 +1,5 @@ use clean::AttributesExt; -use std::cmp::Ordering; -use std::fmt; -use std::rc::Rc; - use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir as hir; use rustc_hir::def::CtorKind; @@ -15,6 +11,9 @@ use rustc_middle::ty::{Adt, TyCtxt}; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_target::abi::{Layout, Primitive, TagEncoding, Variants}; +use std::cmp::Ordering; +use std::fmt; +use std::rc::Rc; use super::{ collect_paths_for_type, document, ensure_trailing_slash, item_ty_to_section, @@ -37,6 +36,7 @@ use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine}; use crate::html::url_parts_builder::UrlPartsBuilder; use askama::Template; +use itertools::Itertools; const ITEM_TABLE_OPEN: &str = "<div class=\"item-table\">"; const ITEM_TABLE_CLOSE: &str = "</div>"; @@ -539,6 +539,8 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: let count_types = required_types.len() + provided_types.len(); let count_consts = required_consts.len() + provided_consts.len(); let count_methods = required_methods.len() + provided_methods.len(); + let must_implement_one_of_functions = + cx.tcx().trait_def(t.def_id).must_implement_one_of.clone(); // Output the trait definition wrap_into_docblock(w, |w| { @@ -784,13 +786,22 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } // Output the documentation for each function individually - if !required_methods.is_empty() { + if !required_methods.is_empty() || must_implement_one_of_functions.is_some() { write_small_section_header( w, "required-methods", "Required Methods", "<div class=\"methods\">", ); + + if let Some(list) = must_implement_one_of_functions.as_deref() { + write!( + w, + "<div class=\"stab must_implement\">At least one of the `{}` methods is required.</div>", + list.iter().join("`, `") + ); + } + for m in required_methods { trait_item(w, cx, m, it); } @@ -1869,7 +1880,11 @@ fn document_type_layout(w: &mut Buffer, cx: &Context<'_>, ty_def_id: DefId) { return; } - writeln!(w, "<h2 class=\"small-section-header\">Layout</h2>"); + writeln!( + w, + "<h2 id=\"layout\" class=\"small-section-header\"> \ + Layout<a href=\"#layout\" class=\"anchor\"></a></h2>" + ); writeln!(w, "<div class=\"docblock\">"); let tcx = cx.tcx(); diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index 7ff8063904a..c42cac59bd6 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -205,11 +205,13 @@ details.rustdoc-toggle > summary::before { /* Created this empty rule to satisfy the theme checks. */ .stab.empty-impl {} +.stab.must_implement {} .stab.unstable, .stab.deprecated, .stab.portability, -.stab.empty-impl { +.stab.empty-impl, +.stab.must_implement { color: #c5c5c5; background: #314559 !important; border-style: none !important; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index 8e753f57682..62d9eaa02e6 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -180,6 +180,7 @@ details.rustdoc-toggle > summary::before { .stab.empty-impl { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; } .stab.unstable { background: #FFF5D6; border-color: #FFC600; color: #2f2f2f; } .stab.deprecated { background: #ffc4c4; border-color: #db7b7b; color: #2f2f2f; } +.stab.must_implement { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; } .stab.portability { background: #F3DFFF; border-color: #b07bdb; color: #2f2f2f; } .stab.portability > code { background: none; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 40d965c39c3..b751acff152 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -163,6 +163,7 @@ details.rustdoc-toggle > summary::before { .stab.empty-impl { background: #FFF5D6; border-color: #FFC600; } .stab.unstable { background: #FFF5D6; border-color: #FFC600; } .stab.deprecated { background: #ffc4c4; border-color: #db7b7b; } +.stab.must_implement { background: #F3DFFF; border-color: #b07bdb; } .stab.portability { background: #F3DFFF; border-color: #b07bdb; } .stab.portability > code { background: none; } diff --git a/src/test/codegen/box-maybe-uninit-llvm14.rs b/src/test/codegen/box-maybe-uninit-llvm14.rs new file mode 100644 index 00000000000..bd1a6599c33 --- /dev/null +++ b/src/test/codegen/box-maybe-uninit-llvm14.rs @@ -0,0 +1,26 @@ +// compile-flags: -O + +// Once we're done with llvm 14 and earlier, this test can be deleted. + +#![crate_type="lib"] + +use std::mem::MaybeUninit; + +// Boxing a `MaybeUninit` value should not copy junk from the stack +#[no_mangle] +pub fn box_uninitialized() -> Box<MaybeUninit<usize>> { + // CHECK-LABEL: @box_uninitialized + // CHECK-NOT: store + // CHECK-NOT: alloca + // CHECK-NOT: memcpy + // CHECK-NOT: memset + Box::new(MaybeUninit::uninit()) +} + +// FIXME: add a test for a bigger box. Currently broken, see +// https://github.com/rust-lang/rust/issues/58201. + +// Hide the LLVM 15+ `allocalign` attribute in the declaration of __rust_alloc +// from the CHECK-NOT above. We don't check the attributes here because we can't rely +// on all of them being set until LLVM 15. +// CHECK: declare noalias{{.*}} @__rust_alloc(i{{[0-9]+}}, i{{[0-9]+.*}}) diff --git a/src/test/codegen/box-maybe-uninit.rs b/src/test/codegen/box-maybe-uninit.rs index 5004f787cde..e105e26f16a 100644 --- a/src/test/codegen/box-maybe-uninit.rs +++ b/src/test/codegen/box-maybe-uninit.rs @@ -1,4 +1,5 @@ // compile-flags: -O +// min-llvm-version: 15.0 #![crate_type="lib"] use std::mem::MaybeUninit; @@ -16,3 +17,9 @@ pub fn box_uninitialized() -> Box<MaybeUninit<usize>> { // FIXME: add a test for a bigger box. Currently broken, see // https://github.com/rust-lang/rust/issues/58201. + +// Hide the `allocalign` attribute in the declaration of __rust_alloc +// from the CHECK-NOT above, and also verify the attributes got set reasonably. +// CHECK: declare noalias ptr @__rust_alloc(i{{[0-9]+}}, i{{[0-9]+}} allocalign) unnamed_addr [[RUST_ALLOC_ATTRS:#[0-9]+]] + +// CHECK-DAG: attributes [[RUST_ALLOC_ATTRS]] = { {{.*}} allockind("alloc,uninitialized,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} } diff --git a/src/test/codegen/vec-calloc-llvm14.rs b/src/test/codegen/vec-calloc-llvm14.rs new file mode 100644 index 00000000000..08302796c41 --- /dev/null +++ b/src/test/codegen/vec-calloc-llvm14.rs @@ -0,0 +1,144 @@ +// compile-flags: -O +// only-x86_64 +// ignore-debug + +#![crate_type = "lib"] + +// CHECK-LABEL: @vec_zero_bytes +#[no_mangle] +pub fn vec_zero_bytes(n: usize) -> Vec<u8> { + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + // CHECK-NOT: call {{.*}}llvm.memset + + // CHECK: call {{.*}}__rust_alloc_zeroed( + + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + // CHECK-NOT: call {{.*}}llvm.memset + + // CHECK: ret void + vec![0; n] +} + +// CHECK-LABEL: @vec_one_bytes +#[no_mangle] +pub fn vec_one_bytes(n: usize) -> Vec<u8> { + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc_zeroed( + + // CHECK: call {{.*}}__rust_alloc( + // CHECK: call {{.*}}llvm.memset + + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc_zeroed( + + // CHECK: ret void + vec![1; n] +} + +// CHECK-LABEL: @vec_zero_scalar +#[no_mangle] +pub fn vec_zero_scalar(n: usize) -> Vec<i32> { + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + + // CHECK: call {{.*}}__rust_alloc_zeroed( + + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + + // CHECK: ret void + vec![0; n] +} + +// CHECK-LABEL: @vec_one_scalar +#[no_mangle] +pub fn vec_one_scalar(n: usize) -> Vec<i32> { + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc_zeroed( + + // CHECK: call {{.*}}__rust_alloc( + + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc_zeroed( + + // CHECK: ret void + vec![1; n] +} + +// CHECK-LABEL: @vec_zero_rgb48 +#[no_mangle] +pub fn vec_zero_rgb48(n: usize) -> Vec<[u16; 3]> { + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + + // CHECK: call {{.*}}__rust_alloc_zeroed( + + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + + // CHECK: ret void + vec![[0, 0, 0]; n] +} + +// CHECK-LABEL: @vec_zero_array_16 +#[no_mangle] +pub fn vec_zero_array_16(n: usize) -> Vec<[i64; 16]> { + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + + // CHECK: call {{.*}}__rust_alloc_zeroed( + + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + + // CHECK: ret void + vec![[0_i64; 16]; n] +} + +// CHECK-LABEL: @vec_zero_tuple +#[no_mangle] +pub fn vec_zero_tuple(n: usize) -> Vec<(i16, u8, char)> { + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + + // CHECK: call {{.*}}__rust_alloc_zeroed( + + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc( + + // CHECK: ret void + vec![(0, 0, '\0'); n] +} + +// CHECK-LABEL: @vec_non_zero_tuple +#[no_mangle] +pub fn vec_non_zero_tuple(n: usize) -> Vec<(i16, u8, char)> { + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc_zeroed( + + // CHECK: call {{.*}}__rust_alloc( + + // CHECK-NOT: call {{.*}}alloc::vec::from_elem + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: call {{.*}}__rust_alloc_zeroed( + + // CHECK: ret void + vec![(0, 0, 'A'); n] +} diff --git a/src/test/codegen/vec-calloc.rs b/src/test/codegen/vec-calloc.rs index 08302796c41..435a4ab5187 100644 --- a/src/test/codegen/vec-calloc.rs +++ b/src/test/codegen/vec-calloc.rs @@ -1,6 +1,7 @@ // compile-flags: -O // only-x86_64 // ignore-debug +// min-llvm-version: 15.0 #![crate_type = "lib"] @@ -142,3 +143,8 @@ pub fn vec_non_zero_tuple(n: usize) -> Vec<(i16, u8, char)> { // CHECK: ret void vec![(0, 0, 'A'); n] } + +// Ensure that __rust_alloc_zeroed gets the right attributes for LLVM to optimize it away. +// CHECK: declare noalias ptr @__rust_alloc_zeroed(i64, i64 allocalign) unnamed_addr [[RUST_ALLOC_ZEROED_ATTRS:#[0-9]+]] + +// CHECK-DAG: attributes [[RUST_ALLOC_ZEROED_ATTRS]] = { {{.*}} allockind("alloc,zeroed,aligned") allocsize(0) uwtable "alloc-family"="__rust_alloc" {{.*}} } diff --git a/src/test/rustdoc/must_implement_one_of.rs b/src/test/rustdoc/must_implement_one_of.rs new file mode 100644 index 00000000000..1f1dd5d5796 --- /dev/null +++ b/src/test/rustdoc/must_implement_one_of.rs @@ -0,0 +1,10 @@ +#![crate_name = "c"] +#![feature(rustc_attrs)] + +#[rustc_must_implement_one_of(a, b)] +// @matches c/trait.Trait.html '//*[@class="stab must_implement"]' \ +// 'At least one of the `a`, `b` methods is required.$' +pub trait Trait { + fn a() {} + fn b() {} +} diff --git a/src/test/rustdoc/type-layout.rs b/src/test/rustdoc/type-layout.rs index 4eea9809ac5..e5c6e9dc3f9 100644 --- a/src/test/rustdoc/type-layout.rs +++ b/src/test/rustdoc/type-layout.rs @@ -2,6 +2,7 @@ // @has type_layout/struct.Foo.html 'Size: ' // @has - ' bytes' +// @has - '//*[@id="layout"]/a[@href="#layout"]' '' pub struct Foo { pub a: usize, b: Vec<String>, diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.stderr b/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.stderr index 46c206f3bf9..e849ca2829e 100644 --- a/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.stderr +++ b/src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.stderr @@ -4,14 +4,14 @@ error: malformed `rustc_lint_diagnostics` attribute input LL | #[rustc_lint_diagnostics(a)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_lint_diagnostics]` -error: attribute should be applied to a function +error: attribute should be applied to a function definition --> $DIR/diagnostics_incorrect.rs:5:1 | LL | #[rustc_lint_diagnostics] | ^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | struct Foo; - | ----------- not a function + | ----------- not a function definition error: aborting due to 2 previous errors diff --git a/src/test/ui-fulldeps/internal-lints/query_stability_incorrect.stderr b/src/test/ui-fulldeps/internal-lints/query_stability_incorrect.stderr index b5156f2ac59..3f78b39edd9 100644 --- a/src/test/ui-fulldeps/internal-lints/query_stability_incorrect.stderr +++ b/src/test/ui-fulldeps/internal-lints/query_stability_incorrect.stderr @@ -4,14 +4,14 @@ error: malformed `rustc_lint_query_instability` attribute input LL | #[rustc_lint_query_instability(a)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_lint_query_instability]` -error: attribute should be applied to a function +error: attribute should be applied to a function definition --> $DIR/query_stability_incorrect.rs:5:1 | LL | #[rustc_lint_query_instability] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | LL | struct Foo; - | ----------- not a function + | ----------- not a function definition error: aborting due to 2 previous errors diff --git a/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr b/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr index bfe7bb2e10d..1ced1433fe9 100644 --- a/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr +++ b/src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr @@ -50,13 +50,13 @@ error: arguments should be non-negative integers LL | #[rustc_legacy_const_generics(1, a, 2, b)] | ^ ^ -error: attribute should be applied to a function +error: attribute should be applied to a function definition --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:18:1 | LL | #[rustc_legacy_const_generics(0)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | struct S; - | --------- not a function + | --------- not a function definition error: #[rustc_legacy_const_generics] functions must only have const generics --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:29:1 @@ -66,21 +66,21 @@ LL | #[rustc_legacy_const_generics(0)] LL | fn foo8<X>() {} | - non-const generic parameter -error: attribute should be applied to a function +error: attribute should be applied to a function definition --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:33:5 | LL | #[rustc_legacy_const_generics(0)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | fn foo9<const X: usize>() {} - | ---------------------------- not a function + | ---------------------------- not a function definition -error: attribute should be applied to a function +error: attribute should be applied to a function definition --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:25:5 | LL | #[rustc_legacy_const_generics(1)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | fn foo7<const X: usize>(); - | -------------------------- not a function + | -------------------------- not a function definition error[E0044]: foreign items may not have const parameters --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:26:5 diff --git a/src/test/ui/issues/issue-30371.rs b/src/test/ui/issues/issue-30371.rs index 58521b95cf6..a1ae9a36bc1 100644 --- a/src/test/ui/issues/issue-30371.rs +++ b/src/test/ui/issues/issue-30371.rs @@ -1,6 +1,5 @@ // run-pass #![allow(unreachable_code)] -#![allow(unused_mut)] // rust-lang/rust#54586 #![deny(unused_variables)] fn main() { diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs new file mode 100644 index 00000000000..15e0af1de64 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] + +extern crate core; + +pub mod __private { + #[doc(hidden)] + pub use core::option::Option::{self, None, Some}; +} diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs new file mode 100644 index 00000000000..5a5079d8204 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs @@ -0,0 +1,8 @@ +#![crate_type = "lib"] + +extern crate core; + +#[doc(hidden)] +pub mod __private { + pub use core::option::Option::{self, None, Some}; +} diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs new file mode 100644 index 00000000000..38dabc9d71f --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs @@ -0,0 +1,10 @@ +// aux-build:hidden-child.rs + +// FIXME(compiler-errors): This currently suggests the wrong thing. +// UI test exists to track the problem. + +extern crate hidden_child; + +fn main() { + let x: Option<i32> = 1i32; //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr new file mode 100644 index 00000000000..67f4ac08de2 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/hidden-child.rs:9:26 + | +LL | let x: Option<i32> = 1i32; + | ----------- ^^^^ expected enum `Option`, found `i32` + | | + | expected due to this + | + = note: expected enum `Option<i32>` + found type `i32` +help: try wrapping the expression in `hidden_child::__private::Some` + | +LL | let x: Option<i32> = hidden_child::__private::Some(1i32); + | ++++++++++++++++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs new file mode 100644 index 00000000000..4d96d6c16cb --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs @@ -0,0 +1,7 @@ +// aux-build:hidden-parent.rs + +extern crate hidden_parent; + +fn main() { + let x: Option<i32> = 1i32; //~ ERROR mismatched types +} diff --git a/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr new file mode 100644 index 00000000000..d92b8127910 --- /dev/null +++ b/src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/hidden-parent.rs:6:26 + | +LL | let x: Option<i32> = 1i32; + | ----------- ^^^^ expected enum `Option`, found `i32` + | | + | expected due to this + | + = note: expected enum `Option<i32>` + found type `i32` +help: try wrapping the expression in `Some` + | +LL | let x: Option<i32> = Some(1i32); + | +++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/tools/linkchecker/main.rs b/src/tools/linkchecker/main.rs index c9b1649200d..a7c78d80ccd 100644 --- a/src/tools/linkchecker/main.rs +++ b/src/tools/linkchecker/main.rs @@ -348,11 +348,6 @@ impl Checker { return; } - // These appear to be broken in mdbook right now? - if fragment.starts_with('-') { - return; - } - parse_ids(&mut target_ids.borrow_mut(), &pretty_path, target_source, report); if target_ids.borrow().contains(*fragment) { |
