]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #99769 - bjorn3:sync_cg_clif-2022-07-26, r=bjorn3
authorYuki Okushi <jtitor@2k36.org>
Wed, 27 Jul 2022 10:05:34 +0000 (19:05 +0900)
committerGitHub <noreply@github.com>
Wed, 27 Jul 2022 10:05:34 +0000 (19:05 +0900)
Sync rustc_codegen_cranelift

I did a large refactoring of the intrinsics module to remove the intrinsic_match macro which is not very clear to other people. This also enables rustfmt to run on this code. While I already did a sync yesterday, I am going to do another sync again to avoid potential conflicts as those will likely be painful to resolve.

r? ``@ghost``

``@rustbot`` label +A-codegen +A-cranelift +T-compiler

97 files changed:
Cargo.lock
compiler/rustc_borrowck/src/type_check/mod.rs
compiler/rustc_codegen_llvm/src/attributes.rs
compiler/rustc_codegen_llvm/src/llvm/diagnostic.rs
compiler/rustc_codegen_llvm/src/llvm/ffi.rs
compiler/rustc_codegen_llvm/src/llvm/mod.rs
compiler/rustc_const_eval/src/transform/check_consts/ops.rs
compiler/rustc_error_messages/locales/en-US/passes.ftl
compiler/rustc_feature/src/builtin_attrs.rs
compiler/rustc_infer/src/infer/error_reporting/mod.rs
compiler/rustc_infer/src/infer/opaque_types.rs
compiler/rustc_llvm/llvm-wrapper/LLVMWrapper.h
compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
compiler/rustc_middle/src/ty/mod.rs
compiler/rustc_middle/src/ty/print/pretty.rs
compiler/rustc_passes/src/check_attr.rs
compiler/rustc_passes/src/errors.rs
compiler/rustc_resolve/src/build_reduced_graph.rs
compiler/rustc_resolve/src/diagnostics.rs
compiler/rustc_resolve/src/ident.rs
compiler/rustc_resolve/src/late/diagnostics.rs
compiler/rustc_resolve/src/lib.rs
compiler/rustc_span/src/symbol.rs
compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
compiler/rustc_typeck/src/collect.rs
compiler/rustc_typeck/src/collect/type_of.rs
library/alloc/benches/lib.rs
library/alloc/benches/vec.rs
library/alloc/src/alloc.rs
library/alloc/src/lib.rs
library/alloc/src/vec/into_iter.rs
library/alloc/tests/lib.rs
library/alloc/tests/vec.rs
library/core/src/cmp.rs
library/core/src/mem/mod.rs
library/std/src/io/mod.rs
library/std/src/os/windows/fs.rs
src/bootstrap/config.rs
src/doc/rustdoc/src/deprecated-features.md
src/doc/rustdoc/src/unstable-features.md
src/librustdoc/Cargo.toml
src/librustdoc/clean/mod.rs
src/librustdoc/clean/types.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/render/print_item.rs
src/librustdoc/html/static/css/themes/ayu.css
src/librustdoc/html/static/css/themes/dark.css
src/librustdoc/html/static/css/themes/light.css
src/test/codegen/box-maybe-uninit-llvm14.rs [new file with mode: 0644]
src/test/codegen/box-maybe-uninit.rs
src/test/codegen/vec-calloc-llvm14.rs [new file with mode: 0644]
src/test/codegen/vec-calloc.rs
src/test/rustdoc/must_implement_one_of.rs [new file with mode: 0644]
src/test/rustdoc/type-layout.rs
src/test/ui-fulldeps/internal-lints/diagnostics_incorrect.stderr
src/test/ui-fulldeps/internal-lints/query_stability_incorrect.stderr
src/test/ui/const-generics/issues/issue-90318.rs
src/test/ui/const-generics/issues/issue-90318.stderr
src/test/ui/consts/const-eval/const_raw_ptr_ops.rs
src/test/ui/consts/const-eval/const_raw_ptr_ops.stderr
src/test/ui/consts/issue-25826.rs
src/test/ui/consts/issue-25826.stderr
src/test/ui/consts/min_const_fn/cmp_fn_pointers.rs
src/test/ui/consts/min_const_fn/cmp_fn_pointers.stderr
src/test/ui/consts/miri_unleashed/ptr_arith.rs
src/test/ui/consts/miri_unleashed/ptr_arith.stderr
src/test/ui/error-codes/E0395.rs [deleted file]
src/test/ui/error-codes/E0395.stderr [deleted file]
src/test/ui/impl-trait/issue-99073-2.rs
src/test/ui/impl-trait/issue-99073-2.stderr
src/test/ui/impl-trait/issue-99073.rs
src/test/ui/impl-trait/issue-99073.stderr
src/test/ui/intrinsics/const-eval-select-bad.stderr
src/test/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr
src/test/ui/issues/issue-30371.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.rs
src/test/ui/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.rs
src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr [deleted file]
src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/cross-crate.rs
src/test/ui/rfc-2632-const-trait-impl/cross-crate.stock.stderr
src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr [new file with mode: 0644]
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.rs
src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-child.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/auxiliary/hidden-parent.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-child.stderr [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.rs [new file with mode: 0644]
src/test/ui/suggestions/dont-suggest-doc-hidden-variant-for-enum/hidden-parent.stderr [new file with mode: 0644]
src/tools/cargo
src/tools/linkchecker/main.rs

index ed3e30342f2f61f475891338e7564cd2cb8ecb48..2325d0f3bf263a8e8f43b2f2d5570767fc023021 100644 (file)
@@ -202,9 +202,9 @@ dependencies = [
 
 [[package]]
 name = "bitflags"
-version = "1.2.1"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitmaps"
@@ -2394,9 +2394,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.4.1"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -3044,9 +3044,9 @@ dependencies = [
 
 [[package]]
 name = "pulldown-cmark"
-version = "0.9.1"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34f197a544b0c9ab3ae46c359a7ec9cbbb5c7bf97054266fecb7ead794a181d6"
+checksum = "2d9cc634bc78768157b5cbfe988ffcd1dcba95cd2b2f03a88316c08c6d00ed63"
 dependencies = [
  "bitflags",
  "memchr",
index eb9df281e7d24ab26a755ed2e6b28f199c6b916d..cf2140097e6da02b45253fef2e86ec5777de83d4 100644 (file)
@@ -21,7 +21,6 @@
 use rustc_infer::infer::{
     InferCtxt, InferOk, LateBoundRegion, LateBoundRegionConversionTime, NllRegionVariableOrigin,
 };
-use rustc_infer::traits::ObligationCause;
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
 use rustc_middle::mir::AssertKind;
@@ -225,26 +224,6 @@ pub(crate) fn type_check<'mir, 'tcx>(
                     )
                     .unwrap();
                     let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
-                    // Check that RPITs are only constrained in their outermost
-                    // function, otherwise report a mismatched types error.
-                    if let OpaqueTyOrigin::FnReturn(parent) | OpaqueTyOrigin::AsyncFn(parent)
-                            = infcx.opaque_ty_origin_unchecked(opaque_type_key.def_id, hidden_type.span)
-                        && parent.to_def_id() != body.source.def_id()
-                    {
-                        infcx
-                            .report_mismatched_types(
-                                &ObligationCause::misc(
-                                    hidden_type.span,
-                                    infcx.tcx.hir().local_def_id_to_hir_id(
-                                        body.source.def_id().expect_local(),
-                                    ),
-                                ),
-                                infcx.tcx.mk_opaque(opaque_type_key.def_id.to_def_id(), opaque_type_key.substs),
-                                hidden_type.ty,
-                                ty::error::TypeError::Mismatch,
-                            )
-                            .emit();
-                    }
                     trace!(
                         "finalized opaque type {:?} to {:#?}",
                         opaque_type_key,
index 1a96dd8bec47a606eef74a08ee39dd116522dbfc..aabbe8ac276d7ca7233618dcee8c3944da1fecdc 100644 (file)
@@ -13,7 +13,7 @@
 
 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"));
     }
index e2fa5e488edd04f2b67634f7fa5ee6a72de14304..45de284d22a6735bafb39d1d8eead2604de9cf95 100644 (file)
@@ -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,
index f64eb79b0a8e2b545b41f09ce0e5d1f7a3dcb83b..9ee6d39fdc9bf95095f14d1a86cb0086db1b52a7 100644 (file)
@@ -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 @@ pub enum PassKind {
     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 @@ struct InvariantOpaque<'a> {
 }
 #[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 fn from_generic(kind: rustc_session::config::DebugInfo) -> Self {
     }
 }
 
+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 @@ pub fn from_generic(kind: rustc_session::config::DebugInfo) -> Self {
     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 @@ pub fn LLVMRustGetOrInsertGlobal<'a>(
     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 @@ pub fn LLVMCreateStringAttribute(
     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 @@ pub fn LLVMRustDIBuilderCreateDebugLocation<'a>(
 
     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 @@ pub fn LLVMRustPrintModule(
     ) -> 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 @@ pub fn LLVMRustBuildOperandBundleDef<'a>(
     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 @@ pub fn LLVMRustPrepareThinLTOImport(
         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,
index 48fbc1de8ee4407adbf323e87430a66ad98ff3c2..6602a4ab8636cc0be034fbbaacabbef009b94667 100644 (file)
@@ -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);
index 1d083b0bf8268b011cab72d22a78e66227bf6f07..3380226164460c74254966bf27dc14c15a564887 100644 (file)
@@ -23,8 +23,8 @@
 
 use super::ConstCx;
 use crate::errors::{
-    MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrComparisonErr, RawPtrToIntErr,
-    StaticAccessErr, TransientMutBorrowErr, TransientMutBorrowErrRaw,
+    MutDerefErr, NonConstOpErr, PanicNonStrErr, RawPtrToIntErr, StaticAccessErr,
+    TransientMutBorrowErr, TransientMutBorrowErrRaw,
 };
 use crate::util::{call_kind, CallDesugaringKind, CallKind};
 
@@ -654,10 +654,10 @@ fn build_error(
 impl<'tcx> NonConstOp<'tcx> for RawPtrComparison {
     fn build_error(
         &self,
-        ccx: &ConstCx<'_, 'tcx>,
+        _: &ConstCx<'_, 'tcx>,
         span: Span,
     ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
-        ccx.tcx.sess.create_err(RawPtrComparisonErr { span })
+        span_bug!(span, "raw ptr comparison should already be caught in the trait system");
     }
 }
 
index 04c67cf8ff73ae3542c4ee5676c0876d9f5a555c..f95e33cd16a7ddfcb48434e0fd1c6f01a81ba22e 100644 (file)
@@ -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
index c806df8214586859883b28b34d6a97227d01153a..7b540e67aab3ddf7fa39931fb725e3ca65a1553b 100644 (file)
@@ -532,6 +532,9 @@ pub struct 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)
index be764cfe83bc3eceea37cc88803a5709423a524f..39faed0bf365cbbb8a9e772fb5c5c7484b0f994f 100644 (file)
@@ -2412,9 +2412,9 @@ fn binding_suggestion<'tcx, S: fmt::Display>(
         #[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 @@ enum SubOrigin<'hir> {
                                         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,
                                 };
                             }
index a6c5ed579c73656f6a157136bbb7da86f4920504..a1c7b70bd9cdf5e72f3f207176fb3bc77e91f484 100644 (file)
@@ -430,7 +430,7 @@ pub fn opaque_type_origin(&self, def_id: LocalDefId, span: Span) -> Option<Opaqu
     }
 
     #[instrument(skip(self), level = "trace")]
-    pub fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin {
+    fn opaque_ty_origin_unchecked(&self, def_id: LocalDefId, span: Span) -> OpaqueTyOrigin {
         let origin = match self.tcx.hir().expect_item(def_id).kind {
             hir::ItemKind::OpaqueTy(hir::OpaqueTy { origin, .. }) => origin,
             ref itemkind => {
index bca5425e7287c947d10a29e53e2af42e8710c247..93f302b44e87cc58c67bb6496f17ef8258ef9b0d 100644 (file)
@@ -86,6 +86,9 @@ enum LLVMRustAttribute {
   SanitizeMemTag = 34,
   NoCfCheck = 35,
   ShadowCallStack = 36,
+  AllocSize = 37,
+  AllocatedPointer = 38,
+  AllocAlign = 39,
 };
 
 typedef struct OpaqueRustString *RustStringRef;
index e0f10f77e89b0d74cc92c44d1c8fe985b5677ab2..0a6bd49992d9932f37326f75cfba45d046ed6e1e 100644 (file)
@@ -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
index 4615558b912984e4537e058c82e8aad292369e7f..ef1a65488e2e4fff51f64b3e3bde106dac51c4ee 100644 (file)
@@ -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,
index 65cae29c58dcbdd21accf3086843208d21f3f1de..6bf237b8ed5dfc5482e3fa76b1408b050768980b 100644 (file)
@@ -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);
             }
index 321fcd43797cc18f5feb7e0739264548dd9e29ee..45d33a1659ffa42fbc0ae603025f44c80bdbda4a 100644 (file)
@@ -50,7 +50,7 @@ pub struct CodegenFnAttrFlags: u32 {
         /// 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 @@ pub struct CodegenFnAttrFlags: u32 {
         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;
     }
 }
 
index 281a12655469494fce2d668a2132199e0615411a..31c523aaca9ae39614fea9658eb9c4322fb2646e 100644 (file)
@@ -829,6 +829,14 @@ pub fn self_ty(self) -> Ty<'tcx> {
     pub fn is_const_if_const(self) -> bool {
         self.constness == BoundConstness::ConstIfConst
     }
+
+    pub fn is_constness_satisfied_by(self, constness: hir::Constness) -> bool {
+        match (self.constness, constness) {
+            (BoundConstness::NotConst, _)
+            | (BoundConstness::ConstIfConst, hir::Constness::Const) => true,
+            (BoundConstness::ConstIfConst, hir::Constness::NotConst) => false,
+        }
+    }
 }
 
 impl<'tcx> PolyTraitPredicate<'tcx> {
index 03bb515904cd01e0b5719e035582785b5941de26..819513884cedc8555f7c72afdab1da8d15fafbfa 100644 (file)
@@ -2556,7 +2556,7 @@ pub fn print_modifiers_and_trait_path(
 
     ty::TraitPredicate<'tcx> {
         p!(print(self.trait_ref.self_ty()), ": ");
-        if let ty::BoundConstness::ConstIfConst = self.constness {
+        if let ty::BoundConstness::ConstIfConst = self.constness && cx.tcx().features().const_trait_impl {
             p!("~const ");
         }
         p!(print(self.trait_ref.print_only_trait_path()))
index f88997f884a4478bf5f5618fc14ab356e7631c9e..f3ccbbb56792dc3493c88a2487fec396a6ecb669 100644 (file)
@@ -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 @@ fn check_link_name(&self, hir_id: HirId, attr: &Attribute, span: Span, target: T
             _ => {
                 // 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 @@ fn check_no_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Tar
                 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 @@ fn check_export_name(
                 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 @@ fn check_rustc_layout_scalar_valid_range(
         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 @@ fn check_rustc_layout_scalar_valid_range(
         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 @@ fn check_rustc_legacy_const_generics(
     ) -> 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 @@ fn check_rustc_legacy_const_generics(
             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 @@ fn check_rustc_legacy_const_generics(
             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 @@ fn check_rustc_legacy_const_generics(
         }
 
         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 @@ fn check_rustc_legacy_const_generics(
     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 @@ fn check_rustc_dirty_clean(&self, attr: &Attribute) -> bool {
         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 @@ fn check_link_section(&self, hir_id: HirId, attr: &Attribute, span: Span, target
             _ => {
                 // 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 @@ fn check_no_mangle(&self, hir_id: HirId, attr: &Attribute, span: Span, target: T
                     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 @@ fn check_repr(
 
         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 @@ fn check_repr(
                     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 @@ fn check_used(&self, attrs: &[Attribute], target: Target) {
         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 @@ fn check_used(&self, attrs: &[Attribute], target: Target) {
             }
         }
         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 @@ fn check_allow_internal_unstable(
             _ => {
                 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 @@ fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool {
         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 @@ fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool {
             (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 @@ fn check_debugger_visualizer(&self, attr: &Attribute, target: Target) -> bool {
         }
     }
 
-    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 @@ fn check_rustc_allow_const_fn_unstable(
             _ => {
                 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 @@ fn check_rustc_std_internal_symbol(
             _ => {
                 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 @@ fn check_const_trait(&self, attr: &Attribute, _span: Span, target: Target) -> bo
         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 @@ fn check_const_trait(&self, attr: &Attribute, _span: Span, target: Target) -> bo
     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 @@ fn check_stability_promotable(&self, attr: &Attribute, _span: Span, target: Targ
     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 @@ fn check_macro_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
         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 @@ fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
                 | 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 @@ fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
             && 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(&note)
-                .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);
index fcd1e9363b1bed01018495447afebf0d5e9fe647..0d4317f6b8881e1dbaff8c9234d49e6e351d3be8 100644 (file)
@@ -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,
+}
index 6631470f2191ba27ed8be21956310bb642a2c9b0..e955a1798b73563199056b85371e71c56ed16475 100644 (file)
@@ -524,7 +524,7 @@ fn build_reduced_graph_for_use_tree(
                         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 @@ fn build_reduced_graph_for_block(&mut self, block: &Block) {
         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,
index 8a655cbf3845ad68a182ec1578b86f1e4a48cd1c..0343e8d9b8ec34f5ac8181d90480f79f0e2a09a2 100644 (file)
@@ -163,7 +163,7 @@ pub(crate) fn report_conflict<'b>(
 
         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() {
index 0cc6d05d1d086ac072ea3c175978268e9cd36c51..6e6782881427b678e1ecc863a7bd31524dba17eb 100644 (file)
@@ -218,7 +218,7 @@ fn hygienic_lexical_parent(
             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 @@ pub(crate) fn resolve_ident_in_lexical_scope(
             };
 
             match module.kind {
-                ModuleKind::Block(..) => {} // We can see through blocks
+                ModuleKind::Block => {} // We can see through blocks
                 _ => break,
             }
 
index f979403e09735225ff3fc228bce4c286487918c4..6b49c6b1ac63eeaeb66086678a5c6e06d302791e 100644 (file)
@@ -1444,7 +1444,7 @@ fn lookup_typo_candidate(
                     // 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
index 6945306a6918962d806ada168105cc4603aa9abf..31d10008efbfbe8b9278f8c66c4cf356df41d73c 100644 (file)
@@ -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 @@ fn new(
     ) -> Self {
         let is_foreign = match kind {
             ModuleKind::Def(_, def_id, _) => !def_id.is_local(),
-            ModuleKind::Block(_) => false,
+            ModuleKind::Block => false,
         };
         ModuleData {
             parent,
index 54d67c5254188c2714d8a52b132e38a52b0bb11e..c75b6772487f9f6fb4e2dae1ee3b3ad737525308 100644 (file)
         rustc,
         rustc_allocator,
         rustc_allocator_nounwind,
+        rustc_allocator_zeroed,
         rustc_allow_const_fn_unstable,
         rustc_allow_incoherent_impl,
         rustc_allowed_through_unstable_modules,
         rustc_const_stable,
         rustc_const_unstable,
         rustc_conversion_suggestion,
+        rustc_deallocator,
         rustc_def_path,
         rustc_diagnostic_item,
         rustc_diagnostic_macros,
         rustc_private,
         rustc_proc_macro_decls,
         rustc_promotable,
+        rustc_reallocator,
         rustc_regions,
         rustc_reservation_impl,
         rustc_serialize,
index 41c5087c43d42a15c5dd2ffc9d5b664bb352d76a..c77540b2f469bc5110c83bfe84c061caab8fdf45 100644 (file)
@@ -666,7 +666,7 @@ fn report_selection_error(
                             );
                         } else if !suggested {
                             // Can't show anything else useful, try to find similar impls.
-                            let impl_candidates = self.find_similar_impl_candidates(trait_ref);
+                            let impl_candidates = self.find_similar_impl_candidates(trait_predicate);
                             if !self.report_similar_impl_candidates(
                                 impl_candidates,
                                 trait_ref,
@@ -701,7 +701,7 @@ fn report_selection_error(
                                 {
                                     let trait_ref = trait_pred.to_poly_trait_ref();
                                     let impl_candidates =
-                                        self.find_similar_impl_candidates(trait_ref);
+                                        self.find_similar_impl_candidates(trait_pred);
                                     self.report_similar_impl_candidates(
                                         impl_candidates,
                                         trait_ref,
@@ -1325,7 +1325,7 @@ fn fuzzy_match_tys(
 
     fn find_similar_impl_candidates(
         &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Vec<ImplCandidate<'tcx>>;
 
     fn report_similar_impl_candidates(
@@ -1694,18 +1694,22 @@ fn describe_generator(&self, body_id: hir::BodyId) -> Option<&'static str> {
 
     fn find_similar_impl_candidates(
         &self,
-        trait_ref: ty::PolyTraitRef<'tcx>,
+        trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> Vec<ImplCandidate<'tcx>> {
         self.tcx
-            .all_impls(trait_ref.def_id())
+            .all_impls(trait_pred.def_id())
             .filter_map(|def_id| {
-                if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative {
+                if self.tcx.impl_polarity(def_id) == ty::ImplPolarity::Negative
+                    || !trait_pred
+                        .skip_binder()
+                        .is_constness_satisfied_by(self.tcx.constness(def_id))
+                {
                     return None;
                 }
 
                 let imp = self.tcx.impl_trait_ref(def_id).unwrap();
 
-                self.fuzzy_match_tys(trait_ref.skip_binder().self_ty(), imp.self_ty(), false)
+                self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false)
                     .map(|similarity| ImplCandidate { trait_ref: imp, similarity })
             })
             .collect()
index 0fcbfa734f8fe93dbb9f9b9d49bf5f21a3a1b99c..0e78c60ca5b6a5b6f3770754b80c74a6dffe6787 100644 (file)
@@ -2090,10 +2090,17 @@ fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
         // from the trait itself that *shouldn't* be shown as the source of
         // an obligation and instead be skipped. Otherwise we'd use
         // `tcx.def_span(def_id);`
+
+        let constness = if tcx.has_attr(def_id, sym::const_trait) {
+            ty::BoundConstness::ConstIfConst
+        } else {
+            ty::BoundConstness::NotConst
+        };
+
         let span = rustc_span::DUMMY_SP;
         result.predicates =
             tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once((
-                ty::TraitRef::identity(tcx, def_id).without_const().to_predicate(tcx),
+                ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx),
                 span,
             ))));
     }
@@ -2775,6 +2782,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) {
index 1d7406e00ad0a63ff9e6dadb2b49561932873609..64ac655e0c393f43cd5282bcc4dc3fe7b1dab3ee 100644 (file)
@@ -335,37 +335,11 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
                     tcx.mk_adt(def, substs)
                 }
                 ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
-                    find_opaque_ty_constraints(tcx, def_id)
+                    find_opaque_ty_constraints_for_tait(tcx, def_id)
                 }
                 // Opaque types desugared from `impl Trait`.
                 ItemKind::OpaqueTy(OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn(owner) | hir::OpaqueTyOrigin::AsyncFn(owner), .. }) => {
-                    let concrete_ty = tcx
-                        .mir_borrowck(owner)
-                        .concrete_opaque_types
-                        .get(&def_id)
-                        .copied()
-                        .map(|concrete| concrete.ty)
-                        .unwrap_or_else(|| {
-                            let table = tcx.typeck(owner);
-                            if let Some(_) = table.tainted_by_errors {
-                                // Some error in the
-                                // owner fn prevented us from populating
-                                // the `concrete_opaque_types` table.
-                                tcx.ty_error()
-                            } else {
-                                table.concrete_opaque_types.get(&def_id).copied().unwrap_or_else(|| {
-                                    // We failed to resolve the opaque type or it
-                                    // resolves to itself. We interpret this as the
-                                    // no values of the hidden type ever being constructed,
-                                    // so we can just make the hidden type be `!`.
-                                    // For backwards compatibility reasons, we fall back to
-                                    // `()` until we the diverging default is changed.
-                                    Some(tcx.mk_diverging_default())
-                                }).expect("RPIT always have a hidden type from typeck")
-                            }
-                        });
-                    debug!("concrete_ty = {:?}", concrete_ty);
-                    concrete_ty
+                    find_opaque_ty_constraints_for_rpit(tcx, def_id, owner)
                 }
                 ItemKind::Trait(..)
                 | ItemKind::TraitAlias(..)
@@ -519,7 +493,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
 /// fn b<T>() -> Foo<T, u32> { .. }
 /// ```
 ///
-fn find_opaque_ty_constraints(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
+fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
     use rustc_hir::{Expr, ImplItem, Item, TraitItem};
 
     struct ConstraintLocator<'tcx> {
@@ -660,6 +634,122 @@ fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
     }
 }
 
+fn find_opaque_ty_constraints_for_rpit(
+    tcx: TyCtxt<'_>,
+    def_id: LocalDefId,
+    owner_def_id: LocalDefId,
+) -> Ty<'_> {
+    use rustc_hir::{Expr, ImplItem, Item, TraitItem};
+
+    struct ConstraintChecker<'tcx> {
+        tcx: TyCtxt<'tcx>,
+
+        /// def_id of the opaque type whose defining uses are being checked
+        def_id: LocalDefId,
+
+        found: ty::OpaqueHiddenType<'tcx>,
+    }
+
+    impl ConstraintChecker<'_> {
+        #[instrument(skip(self), level = "debug")]
+        fn check(&self, def_id: LocalDefId) {
+            // Use borrowck to get the type with unerased regions.
+            let concrete_opaque_types = &self.tcx.mir_borrowck(def_id).concrete_opaque_types;
+            debug!(?concrete_opaque_types);
+            for &(def_id, concrete_type) in concrete_opaque_types {
+                if def_id != self.def_id {
+                    // Ignore constraints for other opaque types.
+                    continue;
+                }
+
+                debug!(?concrete_type, "found constraint");
+
+                if concrete_type.ty != self.found.ty
+                    && !(concrete_type, self.found).references_error()
+                {
+                    self.found.report_mismatch(&concrete_type, self.tcx);
+                }
+            }
+        }
+    }
+
+    impl<'tcx> intravisit::Visitor<'tcx> for ConstraintChecker<'tcx> {
+        type NestedFilter = nested_filter::OnlyBodies;
+
+        fn nested_visit_map(&mut self) -> Self::Map {
+            self.tcx.hir()
+        }
+        fn visit_expr(&mut self, ex: &'tcx Expr<'tcx>) {
+            if let hir::ExprKind::Closure { .. } = ex.kind {
+                let def_id = self.tcx.hir().local_def_id(ex.hir_id);
+                self.check(def_id);
+            }
+            intravisit::walk_expr(self, ex);
+        }
+        fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
+            trace!(?it.def_id);
+            // The opaque type itself or its children are not within its reveal scope.
+            if it.def_id != self.def_id {
+                self.check(it.def_id);
+                intravisit::walk_item(self, it);
+            }
+        }
+        fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
+            trace!(?it.def_id);
+            // The opaque type itself or its children are not within its reveal scope.
+            if it.def_id != self.def_id {
+                self.check(it.def_id);
+                intravisit::walk_impl_item(self, it);
+            }
+        }
+        fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
+            trace!(?it.def_id);
+            self.check(it.def_id);
+            intravisit::walk_trait_item(self, it);
+        }
+    }
+
+    let concrete = tcx.mir_borrowck(owner_def_id).concrete_opaque_types.get(&def_id).copied();
+
+    if let Some(concrete) = concrete {
+        let scope = tcx.hir().local_def_id_to_hir_id(owner_def_id);
+        debug!(?scope);
+        let mut locator = ConstraintChecker { def_id: def_id, tcx, found: concrete };
+
+        match tcx.hir().get(scope) {
+            Node::Item(it) => intravisit::walk_item(&mut locator, it),
+            Node::ImplItem(it) => intravisit::walk_impl_item(&mut locator, it),
+            Node::TraitItem(it) => intravisit::walk_trait_item(&mut locator, it),
+            other => bug!("{:?} is not a valid scope for an opaque type item", other),
+        }
+    }
+
+    concrete.map(|concrete| concrete.ty).unwrap_or_else(|| {
+        let table = tcx.typeck(owner_def_id);
+        if let Some(_) = table.tainted_by_errors {
+            // Some error in the
+            // owner fn prevented us from populating
+            // the `concrete_opaque_types` table.
+            tcx.ty_error()
+        } else {
+            table
+                .concrete_opaque_types
+                .get(&def_id)
+                .copied()
+                .unwrap_or_else(|| {
+                    // We failed to resolve the opaque type or it
+                    // resolves to itself. We interpret this as the
+                    // no values of the hidden type ever being constructed,
+                    // so we can just make the hidden type be `!`.
+                    // For backwards compatibility reasons, we fall back to
+                    // `()` until we the diverging default is changed.
+                    Some(tcx.mk_diverging_default())
+                })
+                .expect("RPIT always have a hidden type from typeck")
+        }
+    })
+}
+
 fn infer_placeholder_type<'a>(
     tcx: TyCtxt<'a>,
     def_id: LocalDefId,
index 7dc0f7cebd535e886446fc9898a573e2f666d229..72ac897d4f178d0236193de5f24c516cd1c6692f 100644 (file)
@@ -2,6 +2,7 @@
 // See https://github.com/rust-lang/rust/issues/73535#event-3477699747
 #![cfg(not(target_os = "android"))]
 #![feature(btree_drain_filter)]
+#![feature(iter_next_chunk)]
 #![feature(map_first_last)]
 #![feature(repr_simd)]
 #![feature(slice_partition_dedup)]
index efc47327e8a86d2fd89b8dec30bf076eb468750f..663f6b9dd1c9c038cbe3fbad3cbcb753329d27ec 100644 (file)
@@ -762,3 +762,23 @@ fn bench_retain_whole_100000(b: &mut Bencher) {
     let mut v = black_box(vec![826u32; 100000]);
     b.iter(|| v.retain(|x| *x == 826u32));
 }
+
+#[bench]
+fn bench_next_chunk(b: &mut Bencher) {
+    let v = vec![13u8; 2048];
+
+    b.iter(|| {
+        const CHUNK: usize = 8;
+
+        let mut sum = [0u32; CHUNK];
+        let mut iter = black_box(v.clone()).into_iter();
+
+        while let Ok(chunk) = iter.next_chunk::<CHUNK>() {
+            for i in 0..CHUNK {
+                sum[i] += chunk[i] as u32;
+            }
+        }
+
+        sum
+    })
+}
index efdc86bf57a8af6e1eb32f0092551da6fd0920e5..cc8da7bccff751b89aaacd76518ff88b88698ac8 100644 (file)
     // (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;
 }
index 315469387e5ae86a6499b90931382794df4f3d04..8b6f4054851dd454ae01fa96d2e4c7aa909c090b 100644 (file)
@@ -89,6 +89,7 @@
 #![feature(alloc_layout_extra)]
 #![feature(allocator_api)]
 #![feature(array_chunks)]
+#![feature(array_into_iter_constructors)]
 #![feature(array_methods)]
 #![feature(array_windows)]
 #![feature(assert_matches)]
 #![feature(hasher_prefixfree_extras)]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
+#![feature(iter_next_chunk)]
 #![feature(layout_for_ptr)]
+#![feature(maybe_uninit_array_assume_init)]
 #![feature(maybe_uninit_slice)]
+#![feature(maybe_uninit_uninit_array)]
 #![cfg_attr(test, feature(new_uninit))]
 #![feature(nonnull_slice_from_raw_parts)]
 #![feature(pattern)]
index 28979457b7fd389049ee21ef83308be1264949c5..1b483e3fc7793a499fcc236781eea1e5f96f8123 100644 (file)
@@ -2,13 +2,14 @@
 use super::AsVecIntoIter;
 use crate::alloc::{Allocator, Global};
 use crate::raw_vec::RawVec;
+use core::array;
 use core::fmt;
 use core::intrinsics::arith_offset;
 use core::iter::{
     FusedIterator, InPlaceIterable, SourceIter, TrustedLen, TrustedRandomAccessNoCoerce,
 };
 use core::marker::PhantomData;
-use core::mem::{self, ManuallyDrop};
+use core::mem::{self, ManuallyDrop, MaybeUninit};
 #[cfg(not(no_global_oom_handling))]
 use core::ops::Deref;
 use core::ptr::{self, NonNull};
@@ -124,7 +125,6 @@ pub(super) fn forget_allocation_drop_remaining(&mut self) {
     }
 
     /// Forgets to Drop the remaining elements while still allowing the backing allocation to be freed.
-    #[cfg(not(no_global_oom_handling))]
     pub(crate) fn forget_remaining_elements(&mut self) {
         self.ptr = self.end;
     }
@@ -204,6 +204,43 @@ fn count(self) -> usize {
         self.len()
     }
 
+    #[inline]
+    fn next_chunk<const N: usize>(&mut self) -> Result<[T; N], core::array::IntoIter<T, N>> {
+        let mut raw_ary = MaybeUninit::uninit_array();
+
+        let len = self.len();
+
+        if mem::size_of::<T>() == 0 {
+            if len < N {
+                self.forget_remaining_elements();
+                // Safety: ZSTs can be conjured ex nihilo, only the amount has to be correct
+                return Err(unsafe { array::IntoIter::new_unchecked(raw_ary, 0..len) });
+            }
+
+            self.ptr = unsafe { arith_offset(self.ptr as *const i8, N as isize) as *mut T };
+            // Safety: ditto
+            return Ok(unsafe { MaybeUninit::array_assume_init(raw_ary) });
+        }
+
+        if len < N {
+            // Safety: `len` indicates that this many elements are available and we just checked that
+            // it fits into the array.
+            unsafe {
+                ptr::copy_nonoverlapping(self.ptr, raw_ary.as_mut_ptr() as *mut T, len);
+                self.forget_remaining_elements();
+                return Err(array::IntoIter::new_unchecked(raw_ary, 0..len));
+            }
+        }
+
+        // Safety: `len` is larger than the array size. Copy a fixed amount here to fully initialize
+        // the array.
+        return unsafe {
+            ptr::copy_nonoverlapping(self.ptr, raw_ary.as_mut_ptr() as *mut T, N);
+            self.ptr = self.ptr.add(N);
+            Ok(MaybeUninit::array_assume_init(raw_ary))
+        };
+    }
+
     unsafe fn __iterator_get_unchecked(&mut self, i: usize) -> Self::Item
     where
         Self: TrustedRandomAccessNoCoerce,
index c29e7b9c81efb0d985887809ccadaec3ff0d4092..d83cd29ddbad92e5d76b3694a7f87a7303265eed 100644 (file)
@@ -27,6 +27,7 @@
 #![feature(binary_heap_as_slice)]
 #![feature(inplace_iteration)]
 #![feature(iter_advance_by)]
+#![feature(iter_next_chunk)]
 #![feature(round_char_boundary)]
 #![feature(slice_group_by)]
 #![feature(slice_partition_dedup)]
index 699567be5a004224252367d7c0daf4799b444d01..d94da8f5f5a0eac6731a298606f33715bd95f932 100644 (file)
@@ -1,4 +1,5 @@
 use core::alloc::{Allocator, Layout};
+use core::iter::IntoIterator;
 use core::ptr::NonNull;
 use std::alloc::System;
 use std::assert_matches::assert_matches;
@@ -930,6 +931,15 @@ fn test_into_iter_count() {
     assert_eq!([1, 2, 3].into_iter().count(), 3);
 }
 
+#[test]
+fn test_into_iter_next_chunk() {
+    let mut iter = b"lorem".to_vec().into_iter();
+
+    assert_eq!(iter.next_chunk().unwrap(), [b'l', b'o']); // N is inferred as 2
+    assert_eq!(iter.next_chunk().unwrap(), [b'r', b'e', b'm']); // N is inferred as 3
+    assert_eq!(iter.next_chunk::<4>().unwrap_err().as_slice(), &[]); // N is explicitly 4
+}
+
 #[test]
 fn test_into_iter_clone() {
     fn iter_equal<I: Iterator<Item = i32>>(it: I, slice: &[i32]) {
index ac286c171f0809078c48df25f184a3506575fc0f..20bb67687848fc1cb9c68dcdab594b2553743b39 100644 (file)
@@ -1503,9 +1503,10 @@ fn cmp(&self, _: &!) -> Ordering {
     // & pointers
 
     #[stable(feature = "rust1", since = "1.0.0")]
-    impl<A: ?Sized, B: ?Sized> PartialEq<&B> for &A
+    #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+    impl<A: ?Sized, B: ?Sized> const PartialEq<&B> for &A
     where
-        A: PartialEq<B>,
+        A: ~const PartialEq<B>,
     {
         #[inline]
         fn eq(&self, other: &&B) -> bool {
index 6dc8563c421fc99ecac9bbb4e657af3af045a074..234fa213da89f4ee3101d15cd4d5a4752e7ab329 100644 (file)
@@ -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
index 18f7f6a35e98f8ba31d3ef807d04b92dc1480dec..96addbd1a0558c5273c2a3a2bf55a27c62d8411f 100644 (file)
@@ -898,7 +898,7 @@ fn by_ref(&mut self) -> &mut Self
     /// 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 @@ fn bytes(self) -> Bytes<Self>
     /// 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 @@ fn chain<R: Read>(self, next: R) -> Chain<Self, R>
     /// 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
index f15baff59dbfb589b0dec2f68fd235b14822da03..a091f06dd532cc14aaa5f4f75cae8c43264f8256 100644 (file)
@@ -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 @@ fn file_index(&self) -> Option<u64> {
 /// 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()
index ea0f78e2a6be9da2c9461497e2bafb53ca18b6ec..c7212ad2c21665160df2edf44b1aa5509b110d5a 100644 (file)
@@ -411,7 +411,11 @@ pub struct Target {
 impl Target {
     pub fn from_triple(triple: &str) -> Self {
         let mut target: Self = Default::default();
-        if triple.contains("-none") || triple.contains("nvptx") || triple.contains("switch") {
+        if triple.contains("-none")
+            || triple.contains("nvptx")
+            || triple.contains("switch")
+            || triple.contains("-uefi")
+        {
             target.no_std = true;
         }
         target
index 2bc6e8fc8ae4df6606001b710e7793f585fcc4ba..9438948af544a86a22fac07b7d79b87b2777ce97 100644 (file)
@@ -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).
index 30b3d6defb4b86e0636957e41159eacb38d9acef..32b350074903e14e24e62212020e052c18be7183 100644 (file)
@@ -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
index 0bd72625f150989e21579681e2e6b98ad3277518..ddaa7438e1778e5b32d743faa1b05f62fe8c1e05 100644 (file)
@@ -10,7 +10,7 @@ path = "lib.rs"
 arrayvec = { version = "0.7", default-features = false }
 askama = { version = "0.11", default-features = false, features = ["config"] }
 atty = "0.2"
-pulldown-cmark = { version = "0.9", default-features = false }
+pulldown-cmark = { version = "0.9.2", default-features = false }
 minifier = "0.2.1"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
index c9ef4748a48451619cadda1289bbd09d54d5d97e..07237438a0d3267697a2f754d4fbe369e1bd0b93 100644 (file)
@@ -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,
index 2d364f3402e9630f3958987abc9fbabd2217ad08..83d8ed3fc87fb6a0d8cf112f6c9def6b5ee0db24 100644 (file)
@@ -2175,8 +2175,8 @@ pub(crate) fn last(&self) -> Symbol {
     pub(crate) fn whole_name(&self) -> String {
         self.segments
             .iter()
-            .map(|s| if s.name == kw::PathRoot { String::new() } else { s.name.to_string() })
-            .intersperse("::".into())
+            .map(|s| if s.name == kw::PathRoot { "" } else { s.name.as_str() })
+            .intersperse("::")
             .collect()
     }
 
index 4170c73b246252314dd4aa6ea24daf03a9159ee8..52a2effca0ff7957db687d69d1a8eae9df941269 100644 (file)
@@ -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
 }
 
index 81cc12c9d55961dc23407e07c9488d00ee6ec7d2..69d66693f752e92b9528917f15f82aad73c22696 100644 (file)
@@ -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_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::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 trait_item(w: &mut Buffer, cx: &mut Context<'_>, m: &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 write_size_of_layout(w: &mut Buffer, layout: Layout<'_>, tag_size: u64) {
         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();
index 7ff8063904acef718711d7c9c8913fc0c798c232..c42cac59bd6fa36f43bf262b9ae74b15478d91da 100644 (file)
@@ -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;
index 8e753f57682063d8598013ddeb4e46c244840d7a..62d9eaa02e6a7e645b8969972c1d199e087b6f81 100644 (file)
@@ -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; }
 
index 40d965c39c390a0fb48bb895667592b4cd3adcf2..b751acff152cb4b2863fcd600999bc4c57728033 100644 (file)
@@ -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 (file)
index 0000000..bd1a659
--- /dev/null
@@ -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]+.*}})
index 5004f787cde190725b2b5d3b69a117a319fcb0a6..e105e26f16a23c6db15cc840c45a946b8794e4ed 100644 (file)
@@ -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 (file)
index 0000000..0830279
--- /dev/null
@@ -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]
+}
index 08302796c41a1e14a8cbdb124d6078442e857eb5..435a4ab5187f6ed5c468c4e26d4051ae22f04ea0 100644 (file)
@@ -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 (file)
index 0000000..1f1dd5d
--- /dev/null
@@ -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() {}
+}
index 4eea9809ac58f66e19e5bab3f29307c6a6c19d6d..e5c6e9dc3f9ed30f29c95cf134d565ed1ef7e386 100644 (file)
@@ -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>,
index 46c206f3bf9fb0772ba9fc3ba4d9b19ea4ca6c8d..e849ca2829e434c5532471666df115c9612498e4 100644 (file)
@@ -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
 
index b5156f2ac5905551077f73b3265e75c7d5d14410..3f78b39edd96a3adcddf933de7e810ca03798eac 100644 (file)
@@ -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
 
index bebd0c6ac1202d656c67299d2dac1f19a105a02c..d6c48e63bb3ce70f98fbdbebddae06b2019356a7 100644 (file)
@@ -12,16 +12,14 @@ impl True for If<true> {}
 fn consume<T: 'static>(_val: T)
 where
     If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
-    //~^ ERROR: overly complex generic constant
-    //~| ERROR: cannot call non-const operator in constants
+    //~^ ERROR: can't compare
 {
 }
 
 fn test<T: 'static>()
 where
     If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
-    //~^ ERROR: overly complex generic constant
-    //~| ERROR: cannot call non-const operator in constants
+    //~^ ERROR: can't compare
 {
 }
 
index c8690ecd0da7e84434306962292eb922f7abe4b8..aba4b5c1a8d8d8794f8cae24f8bf22d3ad610f33 100644 (file)
@@ -1,53 +1,29 @@
-error: overly complex generic constant
-  --> $DIR/issue-90318.rs:14:8
+error[E0277]: can't compare `TypeId` with `_` in const contexts
+  --> $DIR/issue-90318.rs:14:28
    |
 LL |     If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
-   |        ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
-   |          |
-   |          borrowing is not supported in generic constants
+   |                            ^^ no implementation for `TypeId == _`
    |
-   = help: consider moving this anonymous constant into a `const` function
-   = note: this operation may be supported in the future
-
-error[E0015]: cannot call non-const operator in constants
-  --> $DIR/issue-90318.rs:14:10
+   = help: the trait `~const PartialEq<_>` is not implemented for `TypeId`
+note: the trait `PartialEq<_>` is implemented for `TypeId`, but that implementation is not `const`
+  --> $DIR/issue-90318.rs:14:28
    |
 LL |     If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/any.rs:LL:COL
-   |
-LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-   |                       ^^^^^^^^^
-   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+   |                            ^^
 
-error: overly complex generic constant
-  --> $DIR/issue-90318.rs:22:8
+error[E0277]: can't compare `TypeId` with `_` in const contexts
+  --> $DIR/issue-90318.rs:21:28
    |
 LL |     If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
-   |        ^^-----------------^^^^^^^^^^^^^^^^^^^^^^^^
-   |          |
-   |          borrowing is not supported in generic constants
+   |                            ^^ no implementation for `TypeId == _`
    |
-   = help: consider moving this anonymous constant into a `const` function
-   = note: this operation may be supported in the future
-
-error[E0015]: cannot call non-const operator in constants
-  --> $DIR/issue-90318.rs:22:10
+   = help: the trait `~const PartialEq<_>` is not implemented for `TypeId`
+note: the trait `PartialEq<_>` is implemented for `TypeId`, but that implementation is not `const`
+  --> $DIR/issue-90318.rs:21:28
    |
 LL |     If<{ TypeId::of::<T>() != TypeId::of::<()>() }>: True,
-   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/any.rs:LL:COL
-   |
-LL | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
-   |                       ^^^^^^^^^
-   = note: calls in constants are limited to constant functions, tuple structs and tuple variants
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
+   |                            ^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
index e238e13b8e2da46fff8542ce21a634f011144655..cd7c980077533bea1f5d4366ad82dba067bafb25 100644 (file)
@@ -1,6 +1,6 @@
 fn main() {}
 
 // unconst and bad, will thus error in miri
-const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR cannot be reliably
+const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 }; //~ ERROR can't compare
 // unconst and bad, will thus error in miri
-const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR cannot be reliably
+const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 }; //~ ERROR can't compare
index 1f5bca273d3b040012c8b4dd13c8e613d1b9fcdb..168fa0ad0f0ed0ad2c567800ebaa26b9cc80c8a7 100644 (file)
@@ -1,18 +1,49 @@
-error: pointers cannot be reliably compared during const eval
-  --> $DIR/const_raw_ptr_ops.rs:4:26
+error[E0277]: can't compare `*const i32` with `_` in const contexts
+  --> $DIR/const_raw_ptr_ops.rs:4:43
    |
 LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                           ^^ no implementation for `*const i32 == _`
    |
-   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+   = help: the trait `~const PartialEq<_>` is not implemented for `*const i32`
+note: the trait `PartialEq<_>` is implemented for `*const i32`, but that implementation is not `const`
+  --> $DIR/const_raw_ptr_ops.rs:4:43
+   |
+LL | const X: bool = unsafe { &1 as *const i32 == &2 as *const i32 };
+   |                                           ^^
+   = help: the following other types implement trait `PartialEq<Rhs>`:
+             f32
+             f64
+             i128
+             i16
+             i32
+             i64
+             i8
+             isize
+           and 6 others
 
-error: pointers cannot be reliably compared during const eval
-  --> $DIR/const_raw_ptr_ops.rs:6:27
+error[E0277]: can't compare `*const i32` with `_` in const contexts
+  --> $DIR/const_raw_ptr_ops.rs:6:44
    |
 LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                            ^^ no implementation for `*const i32 == _`
    |
-   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+   = help: the trait `~const PartialEq<_>` is not implemented for `*const i32`
+note: the trait `PartialEq<_>` is implemented for `*const i32`, but that implementation is not `const`
+  --> $DIR/const_raw_ptr_ops.rs:6:44
+   |
+LL | const X2: bool = unsafe { 42 as *const i32 == 43 as *const i32 };
+   |                                            ^^
+   = help: the following other types implement trait `PartialEq<Rhs>`:
+             f32
+             f64
+             i128
+             i16
+             i32
+             i64
+             i8
+             isize
+           and 6 others
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0277`.
index d1093c205798a0b8875111e57d65d23625d0e74b..c340c30a113b5108a4e719b8d67f20afb9cb6533 100644 (file)
@@ -1,6 +1,6 @@
 fn id<T>(t: T) -> T { t }
 fn main() {
     const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
-    //~^ ERROR pointers cannot be reliably compared during const eval
+    //~^ ERROR can't compare
     println!("{}", A);
 }
index 780edd2149fe102ce3ed1fd78264ecf77f247b4c..b80befa26f6e007392731a55ee323596a621adf3 100644 (file)
@@ -1,10 +1,20 @@
-error: pointers cannot be reliably compared during const eval
-  --> $DIR/issue-25826.rs:3:30
+error[E0277]: can't compare `*const ()` with `*const ()` in const contexts
+  --> $DIR/issue-25826.rs:3:52
    |
 LL |     const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
-   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                    ^ no implementation for `*const () < *const ()` and `*const () > *const ()`
    |
-   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+   = help: the trait `~const PartialOrd` is not implemented for `*const ()`
+note: the trait `PartialOrd` is implemented for `*const ()`, but that implementation is not `const`
+  --> $DIR/issue-25826.rs:3:52
+   |
+LL |     const A: bool = unsafe { id::<u8> as *const () < id::<u16> as *const () };
+   |                                                    ^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | fn main() where *const (): ~const PartialOrd {
+   |           ++++++++++++++++++++++++++++++++++
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0277`.
index e07b269c386eabee6dfc0c5e59c673e973e82bd2..9a2775688c6fa43c1f1a2b1c515b7350de3de96d 100644 (file)
@@ -1,6 +1,6 @@
 const fn cmp(x: fn(), y: fn()) -> bool {
     unsafe { x == y }
-    //~^ ERROR pointers cannot be reliably compared
+    //~^ ERROR can't compare
 }
 
 fn main() {}
index 3845068d8411c652cfca567167c846d75d0d4a4d..8a1b20a334567a9e041da3aa42a2716df4b438c6 100644 (file)
@@ -1,10 +1,16 @@
-error: pointers cannot be reliably compared during const eval
-  --> $DIR/cmp_fn_pointers.rs:2:14
+error[E0277]: can't compare `fn()` with `_` in const contexts
+  --> $DIR/cmp_fn_pointers.rs:2:16
    |
 LL |     unsafe { x == y }
-   |              ^^^^^^
+   |                ^^ no implementation for `fn() == _`
    |
-   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
+   = help: the trait `~const PartialEq<_>` is not implemented for `fn()`
+note: the trait `PartialEq<_>` is implemented for `fn()`, but that implementation is not `const`
+  --> $DIR/cmp_fn_pointers.rs:2:16
+   |
+LL |     unsafe { x == y }
+   |                ^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0277`.
index 2beb531cc6890c5b4600f0391d187de7bec617aa..13e6af36e0200225f5277c4937d5e10c196e636e 100644 (file)
@@ -2,14 +2,8 @@
 #![feature(core_intrinsics)]
 #![allow(const_err)]
 
-// During CTFE, we prevent pointer comparison and pointer-to-int casts.
-
-static CMP: () = {
-    let x = &0 as *const _;
-    let _v = x == x;
-    //~^ ERROR could not evaluate static initializer
-    //~| "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
-};
+// During CTFE, we prevent pointer-to-int casts.
+// Pointer comparisons are prevented in the trait system.
 
 static PTR_INT_CAST: () = {
     let x = &0 as *const _ as usize;
index 47142752f0ee09d42f8291a13a41c3ef6e4213e6..00cff23fb3fbe4471c490bdd82afa3a4424fc7b8 100644 (file)
@@ -1,17 +1,11 @@
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ptr_arith.rs:9:14
-   |
-LL |     let _v = x == x;
-   |              ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
-
-error[E0080]: could not evaluate static initializer
-  --> $DIR/ptr_arith.rs:15:13
+  --> $DIR/ptr_arith.rs:9:13
    |
 LL |     let x = &0 as *const _ as usize;
    |             ^^^^^^^^^^^^^^^^^^^^^^^ "exposing pointers" needs an rfc before being allowed inside constants
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ptr_arith.rs:23:14
+  --> $DIR/ptr_arith.rs:17:14
    |
 LL |     let _v = x + 0;
    |              ^ unable to turn pointer into raw bytes
@@ -19,16 +13,11 @@ LL |     let _v = x + 0;
 warning: skipping const checks
    |
 help: skipping check that does not even have a feature gate
-  --> $DIR/ptr_arith.rs:9:14
-   |
-LL |     let _v = x == x;
-   |              ^^^^^^
-help: skipping check that does not even have a feature gate
-  --> $DIR/ptr_arith.rs:15:13
+  --> $DIR/ptr_arith.rs:9:13
    |
 LL |     let x = &0 as *const _ as usize;
    |             ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/error-codes/E0395.rs b/src/test/ui/error-codes/E0395.rs
deleted file mode 100644 (file)
index d2edd97..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-static FOO: i32 = 42;
-static BAR: i32 = 42;
-
-static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
-//~^ ERROR pointers cannot be reliably compared during const eval
-
-fn main() {
-}
diff --git a/src/test/ui/error-codes/E0395.stderr b/src/test/ui/error-codes/E0395.stderr
deleted file mode 100644 (file)
index ea17e95..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-error: pointers cannot be reliably compared during const eval
-  --> $DIR/E0395.rs:4:29
-   |
-LL | static BAZ: bool = unsafe { (&FOO as *const i32) == (&BAR as *const i32) };
-   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #53020 <https://github.com/rust-lang/rust/issues/53020> for more information
-
-error: aborting due to previous error
-
index bebd8286de9fec2060420df8abaadb25aec45aac..14ac688806bda2a6da34b5bc1bbe90c182125ef2 100644 (file)
@@ -7,7 +7,7 @@ fn main() {
 fn test<T: Display>(t: T, recurse: bool) -> impl Display {
     let f = || {
         let i: u32 = test::<i32>(-1, false);
-        //~^ ERROR mismatched types
+        //~^ ERROR concrete type differs from previous defining opaque type use
         println!("{i}");
     };
     if recurse {
index c1e4b823c08e7873bb4a5ba5618cba50e5e66f99..913bc8f5674acf1915d349a13f9b4b1f9585be6a 100644 (file)
@@ -1,15 +1,14 @@
-error[E0308]: mismatched types
+error: concrete type differs from previous defining opaque type use
   --> $DIR/issue-99073-2.rs:9:22
    |
-LL | fn test<T: Display>(t: T, recurse: bool) -> impl Display {
-   |                                             ------------ the expected opaque type
-LL |     let f = || {
 LL |         let i: u32 = test::<i32>(-1, false);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^ types differ
+   |                      ^^^^^^^^^^^^^^^^^^^^^^ expected `T`, got `u32`
    |
-   = note: expected opaque type `impl std::fmt::Display`
-                     found type `u32`
+note: previous use here
+  --> $DIR/issue-99073-2.rs:16:5
+   |
+LL |     t
+   |     ^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
index 1d75f6086664fd6db66f24379727b7388495ff86..7798e247df0a2c77ade50b3d0a054404ec2e2526 100644 (file)
@@ -1,8 +1,8 @@
 fn main() {
-    let _ = fix(|_: &dyn Fn()| {});
+  let _ = fix(|_: &dyn Fn()| {});
 }
 
 fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
-    move || f(fix(&f))
-    //~^ ERROR mismatched types
+  move || f(fix(&f))
+  //~^ ERROR concrete type differs from previous defining opaque type use
 }
index b35d58093d5fc89c00f20762a201a11db5084879..54636795349688544df9ab794e5f53db0f0d08f1 100644 (file)
@@ -1,14 +1,14 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-99073.rs:6:13
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/issue-99073.rs:6:11
    |
-LL | fn fix<F: Fn(G), G: Fn()>(f: F) -> impl Fn() {
-   |                                    --------- the expected opaque type
-LL |     move || f(fix(&f))
-   |             ^^^^^^^^^^ types differ
+LL |   move || f(fix(&f))
+   |           ^^^^^^^^^^ expected `[closure@$DIR/issue-99073.rs:6:3: 6:10]`, got `G`
    |
-   = note: expected opaque type `impl Fn()`
-           found type parameter `G`
+note: previous use here
+  --> $DIR/issue-99073.rs:6:3
+   |
+LL |   move || f(fix(&f))
+   |   ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0308`.
index 6103d6c6e3a6ffa1c582553b31eb8629c0002f07..d65818234ef97193dabf362725ef58395c3a40b9 100644 (file)
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]: ~const FnOnce<()>` is not satisfied
+error[E0277]: the trait bound `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]: FnOnce<()>` is not satisfied
   --> $DIR/const-eval-select-bad.rs:7:27
    |
 LL |     const_eval_select((), || {}, || {});
@@ -19,7 +19,7 @@ note: required by a bound in `const_eval_select`
 LL |     F: ~const FnOnce<ARG, Output = RET>,
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `const_eval_select`
 
-error[E0277]: the trait bound `{integer}: ~const FnOnce<()>` is not satisfied
+error[E0277]: the trait bound `{integer}: FnOnce<()>` is not satisfied
   --> $DIR/const-eval-select-bad.rs:9:27
    |
 LL |     const_eval_select((), 42, 0xDEADBEEF);
index bfe7bb2e10dccf7d9cd14252eb430fc64a0cc78c..1ced1433fe955c395c2760262ce1559f88e96a88 100644 (file)
@@ -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
index 58521b95cf637c39a887f160997bfcf1af8e0859..a1ae9a36bc1d728f6ae99d9bad3727d48b70204a 100644 (file)
@@ -1,6 +1,5 @@
 // run-pass
 #![allow(unreachable_code)]
-#![allow(unused_mut)] // rust-lang/rust#54586
 #![deny(unused_variables)]
 
 fn main() {
index 8df68225d44cd34c1b448fbfb39e0ea2c2ec5ff1..2bc5ee512c52fd1c77672e55b8c89926409a3756 100644 (file)
@@ -3,7 +3,6 @@
 pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
     *t == *t
     //~^ ERROR can't compare
-    //~| ERROR cannot call non-const
 }
 
 fn main() {}
index cf114334cc39187dbbbe1cbc5461cb8fa40bbd55..83d395dda196ae6af7abaa9a1680e05246dcbd98 100644 (file)
@@ -1,28 +1,16 @@
-error[E0277]: can't compare `T` with `T` in const contexts
-  --> $DIR/call-generic-method-fail.rs:4:5
+error[E0277]: can't compare `T` with `_` in const contexts
+  --> $DIR/call-generic-method-fail.rs:4:8
    |
 LL |     *t == *t
-   |     ^^^^^^^^ no implementation for `T == T`
+   |        ^^ no implementation for `T == _`
    |
-note: the trait `PartialEq` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/call-generic-method-fail.rs:4:5
+note: the trait `PartialEq<_>` is implemented for `T`, but that implementation is not `const`
+  --> $DIR/call-generic-method-fail.rs:4:8
    |
 LL |     *t == *t
-   |     ^^^^^^^^
+   |        ^^
+   = help: the trait `PartialEq<&B>` is implemented for `&A`
 
-error[E0015]: cannot call non-const operator in constant functions
-  --> $DIR/call-generic-method-fail.rs:4:5
-   |
-LL |     *t == *t
-   |     ^^^^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-help: consider further restricting this bound
-   |
-LL | pub const fn equals_self<T: PartialEq + ~const std::cmp::PartialEq>(t: &T) -> bool {
-   |                                       ++++++++++++++++++++++++++++
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
index 0b981d1621ecaf06f80bf1da905d932455bdc1da..140a06a73ac6d636909b49517ba77a2d4161846a 100644 (file)
@@ -23,7 +23,6 @@ fn b(self) {}
 const fn test() {
     NonConstImpl.a();
     //~^ ERROR the trait bound
-    //~| ERROR cannot call non-const fn
     ConstImpl.a();
 }
 
index fe788b43a5416b4330279af3a43c805930b8dfa9..ec724cc9675f134dc8d422b7209ec448ed4c6cbe 100644 (file)
@@ -2,23 +2,18 @@ error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satis
   --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
-   |                  ^^^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+   |                  ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
    |
 note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
   --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
-   |                  ^^^
-
-error[E0015]: cannot call non-const fn `<NonConstImpl as ConstDefaultFn>::a` in constant functions
-  --> $DIR/const-default-method-bodies.rs:24:18
-   |
-LL |     NonConstImpl.a();
-   |                  ^^^
+   |                  ^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+LL | const fn test() where NonConstImpl: ~const ConstDefaultFn {
+   |                 +++++++++++++++++++++++++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gated.stderr
deleted file mode 100644 (file)
index 3ca9abb..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:15:14
-   |
-LL |     NonConst.func();
-   |              ^^^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
-   |
-note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
-  --> $DIR/cross-crate.rs:15:14
-   |
-LL |     NonConst.func();
-   |              ^^^^^^
-
-error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
-  --> $DIR/cross-crate.rs:15:14
-   |
-LL |     NonConst.func();
-   |              ^^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
new file mode 100644 (file)
index 0000000..174c629
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
+  --> $DIR/cross-crate.rs:17:14
+   |
+LL |     NonConst.func();
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |
+note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
+  --> $DIR/cross-crate.rs:17:14
+   |
+LL |     NonConst.func();
+   |              ^^^^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
+   |                          ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index fa049ab86ff49c0b1016760e0e3618e7cf4b5463..6df47022cc948077b0d64c82871d7e3db3a2ec6c 100644 (file)
@@ -1,5 +1,6 @@
-// revisions: stock gated
-#![cfg_attr(gated, feature(const_trait_impl))]
+// revisions: stock gated stocknc gatednc
+// [gated] check-pass
+#![cfg_attr(any(gated, gatednc), feature(const_trait_impl))]
 
 // aux-build: cross-crate.rs
 extern crate cross_crate;
@@ -12,10 +13,12 @@ fn non_const_context() {
 }
 
 const fn const_context() {
-    NonConst.func(); //~ ERROR: cannot call non-const fn
-    //[gated]~^ ERROR: the trait bound
+    #[cfg(any(stocknc, gatednc))]
+    NonConst.func();
+    //[stocknc]~^ ERROR: the trait bound
+    //[gatednc]~^^ ERROR: the trait bound
     Const.func();
-    //[stock]~^ ERROR: cannot call non-const fn
+    //[stock]~^ ERROR: cannot call
 }
 
 fn main() {}
index ea75ad0aeaf8c2eba9b92532aa86fa856f9a9833..086547542bb095323cd027ca5d7ea5746a1289f3 100644 (file)
@@ -1,19 +1,11 @@
-error[E0015]: cannot call non-const fn `<cross_crate::NonConst as cross_crate::MyTrait>::func` in constant functions
-  --> $DIR/cross-crate.rs:15:14
-   |
-LL |     NonConst.func();
-   |              ^^^^^^
-   |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
 error[E0015]: cannot call non-const fn `<cross_crate::Const as cross_crate::MyTrait>::func` in constant functions
-  --> $DIR/cross-crate.rs:17:11
+  --> $DIR/cross-crate.rs:20:11
    |
 LL |     Const.func();
    |           ^^^^^^
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
new file mode 100644 (file)
index 0000000..4619dd1
--- /dev/null
@@ -0,0 +1,19 @@
+error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied
+  --> $DIR/cross-crate.rs:17:14
+   |
+LL |     NonConst.func();
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |
+note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
+  --> $DIR/cross-crate.rs:17:14
+   |
+LL |     NonConst.func();
+   |              ^^^^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
+   |                          ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
index d798516ff70fd05608449ff0b7e0c44c39d624e7..f70ecbc3746f992c8b4974a4a6dccc3b950e42f5 100644 (file)
@@ -7,7 +7,6 @@ fn a(&self) {}
     fn b(&self) {
         ().a()
         //~^ ERROR the trait bound
-        //~| ERROR cannot call
     }
 }
 
index 8bb7f0141033de1ab601b90c0c39fb0857e25c6c..b229053eb50cfa5e3aaa1bcd6a2aaa10e6bd5499 100644 (file)
@@ -2,23 +2,18 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied
   --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
    |
 LL |         ().a()
-   |            ^^^ the trait `~const Tr` is not implemented for `()`
+   |            ^ the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
   --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
    |
 LL |         ().a()
-   |            ^^^
-
-error[E0015]: cannot call non-const fn `<() as Tr>::a` in constant functions
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
-   |
-LL |         ().a()
-   |            ^^^
+   |            ^
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
+LL | pub trait Tr where (): ~const Tr {
+   |              +++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0015, E0277.
-For more information about an error, try `rustc --explain E0015`.
+For more information about this error, try `rustc --explain E0277`.
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 (file)
index 0000000..15e0af1
--- /dev/null
@@ -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 (file)
index 0000000..5a5079d
--- /dev/null
@@ -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 (file)
index 0000000..38dabc9
--- /dev/null
@@ -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 (file)
index 0000000..67f4ac0
--- /dev/null
@@ -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 (file)
index 0000000..4d96d6c
--- /dev/null
@@ -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 (file)
index 0000000..d92b812
--- /dev/null
@@ -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`.
index d8d30a75376f78bb0fabe3d28ee9d87aa8035309..85b500ccad8cd0b63995fd94a03ddd4b83f7905b 160000 (submodule)
@@ -1 +1 @@
-Subproject commit d8d30a75376f78bb0fabe3d28ee9d87aa8035309
+Subproject commit 85b500ccad8cd0b63995fd94a03ddd4b83f7905b
index c9b1649200d9cb2a8c7a21fd2983f5027f172cf8..a7c78d80ccd768d1cd0484bed46b93a997040cb5 100644 (file)
@@ -348,11 +348,6 @@ fn check(&mut self, file: &Path, report: &mut Report) {
                     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) {