[[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"
[[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",
[[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",
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;
)
.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,
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};
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>(
// 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"));
}
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,
SanitizeMemTag = 34,
NoCfCheck = 35,
ShadowCallStack = 36,
+ AllocSize = 37,
+ AllocatedPointer = 38,
+ AllocAlign = 39,
}
/// LLVMIntPredicate
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;
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 {
}
#[repr(C)]
pub struct Builder<'a>(InvariantOpaque<'a>);
-extern "C" {
- pub type MemoryBuffer;
-}
#[repr(C)]
pub struct PassManager<'a>(InvariantOpaque<'a>);
extern "C" {
}
}
+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;
}
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.
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);
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>(
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;
) -> 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);
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);
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,
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,
}
}
-pub fn UnsetComdat(val: &Value) {
- unsafe {
- LLVMRustUnsetComdat(val);
- }
-}
-
pub fn SetUnnamedAddress(global: &Value, unnamed: UnnamedAddr) {
unsafe {
LLVMSetUnnamedAddress(global, unnamed);
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};
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");
}
}
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
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)
#[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: {
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,
};
}
}
#[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 => {
SanitizeMemTag = 34,
NoCfCheck = 35,
ShadowCallStack = 36,
+ AllocSize = 37,
+ AllocatedPointer = 38,
+ AllocAlign = 39,
};
typedef struct OpaqueRustString *RustStringRef;
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);
#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);
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
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);
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");
}
#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
}
}
-extern "C" void LLVMRustUnsetComdat(LLVMValueRef V) {
- GlobalObject *GV = unwrap<GlobalObject>(V);
- GV->setComdat(nullptr);
-}
-
enum class LLVMRustLinkage {
ExternalLinkage = 0,
AvailableExternallyLinkage = 1,
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
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
}
}
- // 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);
}
/// 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.
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;
}
}
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> {
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()))
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;
_ => {
// 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: "..." },
+ );
+ };
}
}
}
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
}
}
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
}
}
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;
}
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
}
}
) -> 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;
}
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;
}
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 {
}
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
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
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
}
}
_ => {
// 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 },
+ );
}
}
}
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 },
+ );
}
}
}
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;
}
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,
);
}
}
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() {
}
}
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] });
}
}
_ => {
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
}
}
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;
};
(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;
}
};
}
}
- 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(
_ => {
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
}
}
_ => {
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
}
}
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
}
}
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,
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,
+ );
}
_ => {}
}
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,
+ );
}
}
| 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
&& let MetaItemKind::NameValue(_) = &item.kind
&& item.path == sym::reason
{
- format!(
- "attribute `{}` without any lints has no effect",
- attr.name_or_empty()
- )
+ errors::UnusedNote::NoLints { name: attr.name_or_empty() }
} else if attr.name_or_empty() == sym::default_method_body_is_const {
- format!("`default_method_body_is_const` has been replaced with `#[const_trait]` on traits")
+ errors::UnusedNote::DefaultMethodBodyConst
} else {
return;
};
- self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
- lint.build("unused attribute")
- .span_suggestion(
- attr.span,
- "remove this attribute",
- "",
- Applicability::MachineApplicable,
- )
- .note(¬e)
- .emit();
- });
+ self.tcx.emit_spanned_lint(
+ UNUSED_ATTRIBUTES,
+ hir_id,
+ attr.span,
+ errors::Unused { attr_span: attr.span, note },
+ );
}
}
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 });
}
}
}
} 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);
} 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);
use rustc_errors::{Applicability, MultiSpan};
-use rustc_macros::{LintDiagnostic, SessionDiagnostic};
+use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
use rustc_span::{Span, Symbol};
#[derive(LintDiagnostic)]
#[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,
+}
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`,
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,
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() {
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));
}
};
match module.kind {
- ModuleKind::Block(..) => {} // We can see through blocks
+ ModuleKind::Block => {} // We can see through blocks
_ => break,
}
// 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
/// f(); // Resolves to (1)
/// }
/// ```
- Block(NodeId),
+ Block,
/// Any module with a name.
///
/// This could be:
/// Get name of the module.
pub fn name(&self) -> Option<Symbol> {
match self {
- ModuleKind::Block(..) => None,
+ ModuleKind::Block => None,
ModuleKind::Def(.., name) => Some(*name),
}
}
) -> Self {
let is_foreign = match kind {
ModuleKind::Def(_, def_id, _) => !def_id.is_local(),
- ModuleKind::Block(_) => false,
+ ModuleKind::Block => false,
};
ModuleData {
parent,
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,
);
} 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,
{
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,
fn find_similar_impl_candidates(
&self,
- trait_ref: ty::PolyTraitRef<'tcx>,
+ trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Vec<ImplCandidate<'tcx>>;
fn report_similar_impl_candidates(
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()
// 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,
))));
}
}
} 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) {
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(..)
/// 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> {
}
}
+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,
// 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)]
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
+ })
+}
// (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;
}
#![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)]
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};
}
/// 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;
}
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,
#![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)]
use core::alloc::{Allocator, Layout};
+use core::iter::IntoIterator;
use core::ptr::NonNull;
use std::alloc::System;
use std::assert_matches::assert_matches;
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]) {
// & 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 {
///
/// 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
/// 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());
/// 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();
/// 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
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};
/// 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()
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
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).
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
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"
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,
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()
}
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
}
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;
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,
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>";
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| {
}
// 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);
}
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();
/* 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;
.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; }
.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; }
--- /dev/null
+// 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]+.*}})
// compile-flags: -O
+// min-llvm-version: 15.0
#![crate_type="lib"]
use std::mem::MaybeUninit;
// 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" {{.*}} }
--- /dev/null
+// 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]
+}
// compile-flags: -O
// only-x86_64
// ignore-debug
+// min-llvm-version: 15.0
#![crate_type = "lib"]
// 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" {{.*}} }
--- /dev/null
+#![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() {}
+}
// @has type_layout/struct.Foo.html 'Size: '
// @has - ' bytes'
+// @has - '//*[@id="layout"]/a[@href="#layout"]' ''
pub struct Foo {
pub a: usize,
b: Vec<String>,
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
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
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
{
}
-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`.
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
-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`.
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);
}
-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`.
const fn cmp(x: fn(), y: fn()) -> bool {
unsafe { x == y }
- //~^ ERROR pointers cannot be reliably compared
+ //~^ ERROR can't compare
}
fn main() {}
-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`.
#![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;
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
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`.
+++ /dev/null
-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() {
-}
+++ /dev/null
-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
-
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 {
-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`.
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
}
-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`.
-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((), || {}, || {});
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);
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
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
// run-pass
#![allow(unreachable_code)]
-#![allow(unused_mut)] // rust-lang/rust#54586
#![deny(unused_variables)]
fn main() {
pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
*t == *t
//~^ ERROR can't compare
- //~| ERROR cannot call non-const
}
fn main() {}
-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`.
const fn test() {
NonConstImpl.a();
//~^ ERROR the trait bound
- //~| ERROR cannot call non-const fn
ConstImpl.a();
}
--> $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`.
+++ /dev/null
-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`.
--- /dev/null
+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`.
-// 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;
}
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() {}
-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`.
--- /dev/null
+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`.
fn b(&self) {
().a()
//~^ ERROR the trait bound
- //~| ERROR cannot call
}
}
--> $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`.
--- /dev/null
+#![crate_type = "lib"]
+
+extern crate core;
+
+pub mod __private {
+ #[doc(hidden)]
+ pub use core::option::Option::{self, None, Some};
+}
--- /dev/null
+#![crate_type = "lib"]
+
+extern crate core;
+
+#[doc(hidden)]
+pub mod __private {
+ pub use core::option::Option::{self, None, Some};
+}
--- /dev/null
+// 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
+}
--- /dev/null
+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`.
--- /dev/null
+// aux-build:hidden-parent.rs
+
+extern crate hidden_parent;
+
+fn main() {
+ let x: Option<i32> = 1i32; //~ ERROR mismatched types
+}
--- /dev/null
+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`.
-Subproject commit d8d30a75376f78bb0fabe3d28ee9d87aa8035309
+Subproject commit 85b500ccad8cd0b63995fd94a03ddd4b83f7905b
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) {