[[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",
span: Span,
/// The hidden type.
hidden_ty: Ty<'tcx>,
+ /// The opaque type.
+ key: ty::OpaqueTypeKey<'tcx>,
/// The unexpected region.
member_region: ty::Region<'tcx>,
},
}
}
- RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, member_region } => {
+ RegionErrorKind::UnexpectedHiddenRegion { span, hidden_ty, key, member_region } => {
let named_ty = self.regioncx.name_regions(self.infcx.tcx, hidden_ty);
+ let named_key = self.regioncx.name_regions(self.infcx.tcx, key);
let named_region = self.regioncx.name_regions(self.infcx.tcx, member_region);
self.buffer_error(unexpected_hidden_region_diagnostic(
self.infcx.tcx,
span,
named_ty,
named_region,
+ named_key,
));
}
/// The hidden type in which `R0` appears. (Used in error reporting.)
pub(crate) hidden_ty: Ty<'tcx>,
+ pub(crate) key: ty::OpaqueTypeKey<'tcx>,
+
/// The region `R0`.
pub(crate) member_region_vid: ty::RegionVid,
member_region_vid,
definition_span: m_c.definition_span,
hidden_ty: m_c.hidden_ty,
+ key: m_c.key,
start_index,
end_index,
});
errors_buffer.push(RegionErrorKind::UnexpectedHiddenRegion {
span: m_c.definition_span,
hidden_ty: m_c.hidden_ty,
+ key: m_c.key,
member_region,
});
}
// after producing an error for each of them.
let definition_ty = instantiated_ty.ty.fold_with(&mut ReverseMapper::new(
self.tcx,
- def_id,
+ opaque_type_key,
map,
instantiated_ty.ty,
instantiated_ty.span,
struct ReverseMapper<'tcx> {
tcx: TyCtxt<'tcx>,
- opaque_type_def_id: LocalDefId,
+ key: ty::OpaqueTypeKey<'tcx>,
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
map_missing_regions_to_empty: bool,
impl<'tcx> ReverseMapper<'tcx> {
fn new(
tcx: TyCtxt<'tcx>,
- opaque_type_def_id: LocalDefId,
+ key: ty::OpaqueTypeKey<'tcx>,
map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>>,
hidden_ty: Ty<'tcx>,
span: Span,
) -> Self {
Self {
tcx,
- opaque_type_def_id,
+ key,
map,
map_missing_regions_to_empty: false,
hidden_ty: Some(hidden_ty),
}
}
- let generics = self.tcx().generics_of(self.opaque_type_def_id);
+ let generics = self.tcx().generics_of(self.key.def_id);
match self.map.get(&r.into()).map(|k| k.unpack()) {
Some(GenericArgKind::Lifetime(r1)) => r1,
Some(u) => panic!("region mapped to unexpected kind: {:?}", u),
if let Some(hidden_ty) = self.hidden_ty.take() {
unexpected_hidden_region_diagnostic(
self.tcx,
- self.tcx.def_span(self.opaque_type_def_id),
+ self.tcx.def_span(self.key.def_id),
hidden_ty,
r,
+ self.key,
)
.emit();
}
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 rustc_hir::def_id::DefId;
use rustc_middle::mir::{
self,
- interpret::{ConstValue, GlobalId, InterpResult, Scalar},
+ interpret::{ConstValue, GlobalId, InterpResult, PointerArithmetic, Scalar},
BinOp,
};
use rustc_middle::ty;
// We managed to find a valid allocation for one pointer, but not the other.
// That means they are definitely not pointing to the same allocation.
throw_ub_format!(
- "{} called on pointers into different allocations",
+ "`{}` called on pointers into different allocations",
intrinsic_name
);
}
// Found allocation for both. They must be into the same allocation.
if a_alloc_id != b_alloc_id {
throw_ub_format!(
- "{} called on pointers into different allocations",
+ "`{}` called on pointers into different allocations",
intrinsic_name
);
}
};
// Compute distance.
- let distance = {
- // The subtraction is always done in `isize` to enforce
- // the "no more than `isize::MAX` apart" requirement.
- let a_offset = ImmTy::from_uint(a_offset, isize_layout);
- let b_offset = ImmTy::from_uint(b_offset, isize_layout);
- let (val, overflowed, _ty) =
- self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?;
+ let dist = {
+ // Addresses are unsigned, so this is a `usize` computation. We have to do the
+ // overflow check separately anyway.
+ let (val, overflowed, _ty) = {
+ let a_offset = ImmTy::from_uint(a_offset, usize_layout);
+ let b_offset = ImmTy::from_uint(b_offset, usize_layout);
+ self.overflowing_binary_op(BinOp::Sub, &a_offset, &b_offset)?
+ };
if overflowed {
- throw_ub_format!("pointers were too far apart for {}", intrinsic_name);
+ // a < b
+ if intrinsic_name == sym::ptr_offset_from_unsigned {
+ throw_ub_format!(
+ "`{}` called when first pointer has smaller offset than second: {} < {}",
+ intrinsic_name,
+ a_offset,
+ b_offset,
+ );
+ }
+ // The signed form of the intrinsic allows this. If we interpret the
+ // difference as isize, we'll get the proper signed difference. If that
+ // seems *positive*, they were more than isize::MAX apart.
+ let dist = val.to_machine_isize(self)?;
+ if dist >= 0 {
+ throw_ub_format!(
+ "`{}` called when first pointer is too far before second",
+ intrinsic_name
+ );
+ }
+ dist
+ } else {
+ // b >= a
+ let dist = val.to_machine_isize(self)?;
+ // If converting to isize produced a *negative* result, we had an overflow
+ // because they were more than isize::MAX apart.
+ if dist < 0 {
+ throw_ub_format!(
+ "`{}` called when first pointer is too far ahead of second",
+ intrinsic_name
+ );
+ }
+ dist
}
- val.to_machine_isize(self)?
};
// Check that the range between them is dereferenceable ("in-bounds or one past the
// end of the same allocation"). This is like the check in ptr_offset_inbounds.
- let min_ptr = if distance >= 0 { b } else { a };
+ let min_ptr = if dist >= 0 { b } else { a };
self.check_ptr_access_align(
min_ptr,
- Size::from_bytes(distance.unsigned_abs()),
+ Size::from_bytes(dist.unsigned_abs()),
Align::ONE,
CheckInAllocMsg::OffsetFromTest,
)?;
- if intrinsic_name == sym::ptr_offset_from_unsigned && distance < 0 {
- throw_ub_format!(
- "{} called when first pointer has smaller offset than second: {} < {}",
- intrinsic_name,
- a_offset,
- b_offset,
- );
- }
-
// Perform division by size to compute return value.
let ret_layout = if intrinsic_name == sym::ptr_offset_from_unsigned {
+ assert!(0 <= dist && dist <= self.machine_isize_max());
usize_layout
} else {
+ assert!(self.machine_isize_min() <= dist && dist <= self.machine_isize_max());
isize_layout
};
let pointee_layout = self.layout_of(substs.type_at(0))?;
// If ret_layout is unsigned, we checked that so is the distance, so we are good.
- let val = ImmTy::from_int(distance, ret_layout);
+ let val = ImmTy::from_int(dist, ret_layout);
let size = ImmTy::from_int(pointee_layout.size.bytes(), ret_layout);
self.exact_div(&val, &size, dest)?;
}
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)
span: Span,
hidden_ty: Ty<'tcx>,
hidden_region: ty::Region<'tcx>,
+ opaque_ty: ty::OpaqueTypeKey<'tcx>,
) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> {
+ let opaque_ty = tcx.mk_opaque(opaque_ty.def_id.to_def_id(), opaque_ty.substs);
let mut err = struct_span_err!(
tcx.sess,
span,
E0700,
- "hidden type for `impl Trait` captures lifetime that does not appear in bounds",
+ "hidden type for `{opaque_ty}` captures lifetime that does not appear in bounds",
);
// Explain the region we are capturing.
#[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,
};
}
use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind, ToType};
use rustc_middle::mir::interpret::{ErrorHandled, EvalToValTreeResult};
use rustc_middle::traits::select;
-use rustc_middle::ty::abstract_const::AbstractConst;
+use rustc_middle::ty::abstract_const::{AbstractConst, FailureKind};
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::relate::RelateResult;
#[instrument(skip(self), level = "debug")]
pub fn member_constraint(
&self,
- opaque_type_def_id: LocalDefId,
+ key: ty::OpaqueTypeKey<'tcx>,
definition_span: Span,
hidden_ty: Ty<'tcx>,
region: ty::Region<'tcx>,
in_regions: &Lrc<Vec<ty::Region<'tcx>>>,
) {
self.inner.borrow_mut().unwrap_region_constraints().member_constraint(
- opaque_type_def_id,
+ key,
definition_span,
hidden_ty,
region,
#[instrument(skip(self), level = "debug")]
pub fn const_eval_resolve(
&self,
- param_env: ty::ParamEnv<'tcx>,
+ mut param_env: ty::ParamEnv<'tcx>,
unevaluated: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToValTreeResult<'tcx> {
// variables
if substs.has_infer_types_or_consts() {
let ac = AbstractConst::new(self.tcx, unevaluated.shrink());
- if let Ok(None) = ac {
- substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
- } else {
- return Err(ErrorHandled::TooGeneric);
+ match ac {
+ Ok(None) => {
+ substs = InternalSubsts::identity_for_item(self.tcx, unevaluated.def.did);
+ param_env = self.tcx.param_env(unevaluated.def.did);
+ }
+ Ok(Some(ct)) => {
+ if ct.unify_failure_kind(self.tcx) == FailureKind::Concrete {
+ substs = replace_param_and_infer_substs_with_placeholder(self.tcx, substs);
+ } else {
+ return Err(ErrorHandled::TooGeneric);
+ }
+ }
+ Err(guar) => return Err(ErrorHandled::Reported(guar)),
}
}
)
}
}
+
+/// Replaces substs that reference param or infer variables with suitable
+/// placeholders. This function is meant to remove these param and infer
+/// substs when they're not actually needed to evaluate a constant.
+fn replace_param_and_infer_substs_with_placeholder<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ substs: SubstsRef<'tcx>,
+) -> SubstsRef<'tcx> {
+ tcx.mk_substs(substs.iter().enumerate().map(|(idx, arg)| {
+ match arg.unpack() {
+ GenericArgKind::Type(_)
+ if arg.has_param_types_or_consts() || arg.has_infer_types_or_consts() =>
+ {
+ tcx.mk_ty(ty::Placeholder(ty::PlaceholderType {
+ universe: ty::UniverseIndex::ROOT,
+ name: ty::BoundVar::from_usize(idx),
+ }))
+ .into()
+ }
+ GenericArgKind::Const(ct)
+ if ct.has_infer_types_or_consts() || ct.has_param_types_or_consts() =>
+ {
+ let ty = ct.ty();
+ // If the type references param or infer, replace that too...
+ if ty.has_param_types_or_consts() || ty.has_infer_types_or_consts() {
+ bug!("const `{ct}`'s type should not reference params or types");
+ }
+ tcx.mk_const(ty::ConstS {
+ ty,
+ kind: ty::ConstKind::Placeholder(ty::PlaceholderConst {
+ universe: ty::UniverseIndex::ROOT,
+ name: ty::BoundConst { ty, var: ty::BoundVar::from_usize(idx) },
+ }),
+ })
+ .into()
+ }
+ _ => arg,
+ }
+ }))
+}
);
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
- op: |r| {
- self.member_constraint(
- opaque_type_key.def_id,
- span,
- concrete_ty,
- r,
- &choice_regions,
- )
- },
+ op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions),
});
}
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::undo_log::UndoLogs;
use rustc_data_structures::unify as ut;
-use rustc_hir::def_id::LocalDefId;
use rustc_index::vec::IndexVec;
use rustc_middle::infer::unify_key::{RegionVidKey, UnifiedRegion};
use rustc_middle::ty::ReStatic;
pub fn member_constraint(
&mut self,
- opaque_type_def_id: LocalDefId,
+ key: ty::OpaqueTypeKey<'tcx>,
definition_span: Span,
hidden_ty: Ty<'tcx>,
member_region: ty::Region<'tcx>,
}
self.data.member_constraints.push(MemberConstraint {
- opaque_type_def_id,
+ key,
definition_span,
hidden_ty,
member_region,
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::iter::TrustedLen;
use std::mem;
use std::num::NonZeroUsize;
-use std::path::PathBuf;
+use std::path::Path;
use tracing::debug;
pub(super) use cstore_impl::provide;
/// Proc macro crates don't currently export spans, so this function does not have
/// to work for them.
fn imported_source_files(self, sess: &Session) -> &'a [ImportedSourceFile] {
+ fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
+ path.filter(|_| {
+ // Only spend time on further checks if we have what to translate *to*.
+ sess.opts.real_rust_source_base_dir.is_some()
+ // Some tests need the translation to be always skipped.
+ && sess.opts.unstable_opts.translate_remapped_path_to_local_path
+ })
+ .filter(|virtual_dir| {
+ // Don't translate away `/rustc/$hash` if we're still remapping to it,
+ // since that means we're still building `std`/`rustc` that need it,
+ // and we don't want the real path to leak into codegen/debuginfo.
+ !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
+ })
+ }
+
// Translate the virtual `/rustc/$hash` prefix back to a real directory
// that should hold actual sources, where possible.
//
// NOTE: if you update this, you might need to also update bootstrap's code for generating
// the `rust-src` component in `Src::run` in `src/bootstrap/dist.rs`.
let virtual_rust_source_base_dir = [
- option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(PathBuf::from),
- sess.opts.unstable_opts.simulate_remapped_rust_src_base.clone(),
- ]
- .into_iter()
- .filter(|_| {
- // Only spend time on further checks if we have what to translate *to*.
- sess.opts.real_rust_source_base_dir.is_some()
- // Some tests need the translation to be always skipped.
- && sess.opts.unstable_opts.translate_remapped_path_to_local_path
- })
- .flatten()
- .filter(|virtual_dir| {
- // Don't translate away `/rustc/$hash` if we're still remapping to it,
- // since that means we're still building `std`/`rustc` that need it,
- // and we don't want the real path to leak into codegen/debuginfo.
- !sess.opts.remap_path_prefix.iter().any(|(_from, to)| to == virtual_dir)
- })
- .collect::<Vec<_>>();
+ filter(sess, option_env!("CFG_VIRTUAL_RUST_SOURCE_BASE_DIR").map(Path::new)),
+ filter(sess, sess.opts.unstable_opts.simulate_remapped_rust_src_base.as_deref()),
+ ];
let try_to_translate_virtual_to_real = |name: &mut rustc_span::FileName| {
debug!(
name, virtual_rust_source_base_dir, sess.opts.real_rust_source_base_dir,
);
- for virtual_dir in &virtual_rust_source_base_dir {
+ for virtual_dir in virtual_rust_source_base_dir.iter().flatten() {
if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
if let rustc_span::FileName::Real(old_name) = name {
if let rustc_span::RealFileName::Remapped { local_path: _, virtual_name } =
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);
}
pub mod unify_key;
use crate::ty::Region;
-use crate::ty::Ty;
+use crate::ty::{OpaqueTypeKey, Ty};
use rustc_data_structures::sync::Lrc;
-use rustc_hir::def_id::LocalDefId;
use rustc_span::Span;
/// Requires that `region` must be equal to one of the regions in `choice_regions`.
/// ```
#[derive(Debug, Clone, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct MemberConstraint<'tcx> {
- /// The `DefId` of the opaque type causing this constraint: used for error reporting.
- pub opaque_type_def_id: LocalDefId,
+ /// The `DefId` and substs of the opaque type causing this constraint.
+ /// Used for error reporting.
+ pub key: OpaqueTypeKey<'tcx>,
/// The span where the hidden type was instantiated.
pub definition_span: Span,
/// 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;
}
}
"that does not derive `Copy`"
};
let message = format!(
- "`{}` can't be derived on this `#[repr(packed)]` struct {} (error E0133)",
+ "`{}` can't be derived on this `#[repr(packed)]` struct {}",
tcx.item_name(tcx.trait_id_of_impl(def_id.to_def_id()).expect("derived trait name")),
extra
);
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,
}
}
ty::Error(_) => ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty)),
- ty::Opaque(..) | ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => {
+ ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => {
self.tcx.sess.delay_span_bug(
DUMMY_SP,
format!("ty_is_local invoked on closure or generator: {:?}", ty),
);
ControlFlow::Break(OrphanCheckEarlyExit::LocalTy(ty))
}
+ ty::Opaque(..) => {
+ // This merits some explanation.
+ // Normally, opaque types are not involved when performing
+ // coherence checking, since it is illegal to directly
+ // implement a trait on an opaque type. However, we might
+ // end up looking at an opaque type during coherence checking
+ // if an opaque type gets used within another type (e.g. as
+ // the type of a field) when checking for auto trait or `Sized`
+ // impls. This requires us to decide whether or not an opaque
+ // type should be considered 'local' or not.
+ //
+ // We choose to treat all opaque types as non-local, even
+ // those that appear within the same crate. This seems
+ // somewhat surprising at first, but makes sense when
+ // you consider that opaque types are supposed to hide
+ // the underlying type *within the same crate*. When an
+ // opaque type is used from outside the module
+ // where it is declared, it should be impossible to observe
+ // anything about it other than the traits that it implements.
+ //
+ // The alternative would be to look at the underlying type
+ // to determine whether or not the opaque type itself should
+ // be considered local. However, this could make it a breaking change
+ // to switch the underlying ('defining') type from a local type
+ // to a remote type. This would violate the rule that opaque
+ // types should be completely opaque apart from the traits
+ // that they implement, so we don't use this behavior.
+ self.found_non_local_ty(ty)
+ }
};
// A bit of a hack, the `OrphanChecker` is only used to visit a `TraitRef`, so
// the first type we visit is always the self type.
}
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
match concrete {
- Err(ErrorHandled::TooGeneric) => Err(if uv.has_infer_types_or_consts() {
- NotConstEvaluatable::MentionsInfer
- } else if uv.has_param_types_or_consts() {
- infcx
- .tcx
- .sess
- .delay_span_bug(span, &format!("unexpected `TooGeneric` for {:?}", uv));
- NotConstEvaluatable::MentionsParam
- } else {
- let guar = infcx.tcx.sess.delay_span_bug(
+ Err(ErrorHandled::TooGeneric) => {
+ Err(NotConstEvaluatable::Error(infcx.tcx.sess.delay_span_bug(
span,
format!("Missing value for constant, but no error reported?"),
- );
- NotConstEvaluatable::Error(guar)
- }),
+ )))
+ }
Err(ErrorHandled::Linted) => {
let reported = infcx
.tcx
}
} 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) {
// 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]) {
///
/// 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
/// }
///
/// // This would be incorrect, as the pointers are not correctly ordered:
- /// // ptr1.offset_from(ptr2)
+ /// // ptr1.sub_ptr(ptr2)
/// ```
#[unstable(feature = "ptr_sub_ptr", issue = "95892")]
#[rustc_const_unstable(feature = "const_ptr_sub_ptr", issue = "95892")]
/// 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()
panic!("Cannot use and generate PGO profiles at the same time");
}
+ // With LLD, we can use ICF (identical code folding) to reduce the executable size
+ // of librustc_driver/rustc and to improve i-cache utilization.
+ if builder.config.use_lld {
+ cargo.rustflag("-Clink-args=-Wl,--icf=all");
+ }
+
let is_collecting = if let Some(path) = &builder.config.rust_profile_generate {
if compiler.stage == 1 {
cargo.rustflag(&format!("-Cprofile-generate={}", path));
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
--set target.x86_64-unknown-linux-gnu.ranlib=/rustroot/bin/llvm-ranlib \
--set llvm.thin-lto=true \
--set llvm.ninja=false \
- --set rust.jemalloc
+ --set rust.jemalloc \
+ --set rust.use-lld=true
ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \
--host $HOSTS --target $HOSTS \
--include-default-paths \
$@ \
--rust-profile-use=${RUSTC_PROFILE_MERGED_FILE} \
--llvm-profile-use=${LLVM_PROFILE_MERGED_FILE}
+
+echo "Rustc binary size"
+ls -la ./build/$PGO_HOST/stage2/bin
+ls -la ./build/$PGO_HOST/stage2/lib
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
|
= help: consider adding the following bound: `'a: 'b`
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Trait<'a>` captures lifetime that does not appear in bounds
--> $DIR/ret-impl-trait-one.rs:16:80
|
LL | async fn async_ret_impl_trait1<'a, 'b>(a: &'a u8, b: &'b u8) -> impl Trait<'a> {
--- /dev/null
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+struct Outer<T: ?Sized> {
+ i: InnerSend<T>,
+}
+
+type InnerSend<T: ?Sized> = impl Send;
+
+fn constrain<T: ?Sized>() -> InnerSend<T> {
+ ()
+}
+
+trait SendMustNotImplDrop {}
+
+#[allow(drop_bounds)]
+impl<T: ?Sized + Send + Drop> SendMustNotImplDrop for T {}
+
+impl<T: ?Sized> SendMustNotImplDrop for Outer<T> {}
+
+fn main() {}
--- /dev/null
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+struct Send<T> {
+ i: InnerSend<T>,
+}
+
+type InnerSend<T> = impl Sized;
+
+fn constrain<T>() -> InnerSend<T> {
+ ()
+}
+
+trait SendMustNotImplDrop {}
+
+#[allow(drop_bounds)]
+impl<T: Drop> SendMustNotImplDrop for T {}
+
+impl<T> SendMustNotImplDrop for Send<T> {}
+
+fn main() {}
+// check-pass
+
#![feature(generic_const_exprs)]
#![allow(incomplete_features)]
}
fn main() {
- // FIXME(generic_const_exprs): We can't correctly infer `T` which requires
- // evaluating `{ N + 1 }` which has substs containing an inference var
let mut _q = Default::default();
- //~^ ERROR type annotations needed
-
_q = foo::<_, 2>(_q);
- //~^ ERROR type annotations needed
}
+++ /dev/null
-error[E0282]: type annotations needed
- --> $DIR/const_eval_resolve_canonical.rs:26:9
- |
-LL | let mut _q = Default::default();
- | ^^^^^^
- |
-help: consider giving `_q` an explicit type
- |
-LL | let mut _q: _ = Default::default();
- | +++
-
-error[E0283]: type annotations needed
- --> $DIR/const_eval_resolve_canonical.rs:29:10
- |
-LL | _q = foo::<_, 2>(_q);
- | ^^^^^^^^^^^ cannot infer the value of the constant `{ N + 1 }`
- |
-note: multiple `impl`s satisfying `(): Foo<{ N + 1 }>` found
- --> $DIR/const_eval_resolve_canonical.rs:8:1
- |
-LL | impl Foo<0> for () {
- | ^^^^^^^^^^^^^^^^^^
-...
-LL | impl Foo<3> for () {
- | ^^^^^^^^^^^^^^^^^^
-note: required by a bound in `foo`
- --> $DIR/const_eval_resolve_canonical.rs:18:9
- |
-LL | fn foo<T, const N: usize>(_: T) -> <() as Foo<{ N + 1 }>>::Assoc
- | --- required by a bound in this
-LL | where
-LL | (): Foo<{ N + 1 }>,
- | ^^^^^^^^^^^^^^ required by this bound in `foo`
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0282, E0283.
-For more information about an error, try `rustc --explain E0282`.
LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
- | ptr_offset_from_unsigned called on pointers into different allocations
+ | `ptr_offset_from_unsigned` called on pointers into different allocations
| inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
- | ptr_offset_from_unsigned called on pointers into different allocations
+ | `ptr_offset_from_unsigned` called on pointers into different allocations
| inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
- | ptr_offset_from_unsigned called on pointers into different allocations
+ | `ptr_offset_from_unsigned` called on pointers into different allocations
| inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
LL | unsafe { intrinsics::ptr_offset_from_unsigned(self, origin) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
- | ptr_offset_from_unsigned called on pointers into different allocations
+ | `ptr_offset_from_unsigned` called on pointers into different allocations
| inside `ptr::const_ptr::<impl *const u32>::sub_ptr` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
::: $SRC_DIR/core/src/slice/raw.rs:LL:COL
#![feature(core_intrinsics)]
use std::intrinsics::{ptr_offset_from, ptr_offset_from_unsigned};
+use std::ptr;
#[repr(C)]
struct Struct {
let base_ptr: *const Struct = &uninit as *const _ as *const Struct;
let uninit2 = std::mem::MaybeUninit::<Struct>::uninit();
let field_ptr: *const Struct = &uninit2 as *const _ as *const Struct;
- let offset = unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) }; //~ERROR evaluation of constant value failed
+ unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) } //~ERROR evaluation of constant value failed
//~| pointers into different allocations
- offset as usize
+};
+
+pub const TOO_FAR_APART1: isize = {
+ let ptr1 = ptr::null::<u8>();
+ let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
+ unsafe { ptr_offset_from(ptr2, ptr1) } //~ERROR evaluation of constant value failed
+ //~| too far ahead
+};
+pub const TOO_FAR_APART2: isize = {
+ let ptr1 = ptr::null::<u8>();
+ let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
+ unsafe { ptr_offset_from(ptr1, ptr2) } //~ERROR evaluation of constant value failed
+ //~| too far before
};
const WRONG_ORDER_UNSIGNED: usize = {
unsafe { ptr_offset_from_unsigned(p, p.add(2) ) } //~ERROR evaluation of constant value failed
//~| first pointer has smaller offset than second: 0 < 8
};
+pub const TOO_FAR_APART_UNSIGNED: usize = {
+ let ptr1 = ptr::null::<u8>();
+ let ptr2 = ptr1.wrapping_add(isize::MAX as usize + 42);
+ // This would fit into a `usize` but we still don't allow it.
+ unsafe { ptr_offset_from_unsigned(ptr2, ptr1) } //~ERROR evaluation of constant value failed
+ //~| too far ahead
+};
+
+// These do NOT complain that pointers are too far apart; they pass that check (to then fail the
+// next one).
+pub const OFFSET_VERY_FAR1: isize = {
+ let ptr1 = ptr::null::<u8>();
+ let ptr2 = ptr1.wrapping_offset(isize::MAX);
+ unsafe { ptr2.offset_from(ptr1) }
+ //~^ inside
+};
+pub const OFFSET_VERY_FAR2: isize = {
+ let ptr1 = ptr::null::<u8>();
+ let ptr2 = ptr1.wrapping_offset(isize::MAX);
+ unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
+ //~^ inside
+};
fn main() {}
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:17:27
+ --> $DIR/offset_from_ub.rs:18:27
|
LL | let offset = unsafe { ptr_offset_from(field_ptr, base_ptr) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from called on pointers into different allocations
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called on pointers into different allocations
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
- | ptr_offset_from called on pointers into different allocations
+ | `ptr_offset_from` called on pointers into different allocations
| inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
|
- ::: $DIR/offset_from_ub.rs:23:14
+ ::: $DIR/offset_from_ub.rs:24:14
|
LL | unsafe { (42 as *const u8).offset_from(&5u8) as usize }
- | ----------------------------------- inside `NOT_PTR` at $DIR/offset_from_ub.rs:23:14
+ | ----------------------------------- inside `NOT_PTR` at $DIR/offset_from_ub.rs:24:14
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:30:14
+ --> $DIR/offset_from_ub.rs:31:14
|
LL | unsafe { ptr_offset_from(field_ptr, base_ptr as *const u16) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ exact_div: 1_isize cannot be divided by 2_isize without remainder
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:36:14
+ --> $DIR/offset_from_ub.rs:37:14
|
LL | unsafe { ptr_offset_from(ptr, ptr) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:43:14
+ --> $DIR/offset_from_ub.rs:44:14
|
LL | unsafe { ptr_offset_from(ptr2, ptr1) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: 0x8[noalloc] is a dangling pointer (it has no provenance)
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:52:14
+ --> $DIR/offset_from_ub.rs:53:14
|
LL | unsafe { ptr_offset_from(end_ptr, start_ptr) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc18 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:61:14
+ --> $DIR/offset_from_ub.rs:62:14
|
LL | unsafe { ptr_offset_from(start_ptr, end_ptr) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc21 has size 4, so pointer to 10 bytes starting at offset 0 is out-of-bounds
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:69:14
+ --> $DIR/offset_from_ub.rs:70:14
|
LL | unsafe { ptr_offset_from(end_ptr, end_ptr) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds offset_from: alloc24 has size 4, so pointer at offset 10 is out-of-bounds
error[E0080]: evaluation of constant value failed
- --> $DIR/offset_from_ub.rs:78:27
+ --> $DIR/offset_from_ub.rs:79:14
|
-LL | let offset = unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) };
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from_unsigned called on pointers into different allocations
+LL | unsafe { ptr_offset_from_unsigned(field_ptr, base_ptr) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called on pointers into different allocations
error[E0080]: evaluation of constant value failed
--> $DIR/offset_from_ub.rs:86:14
|
+LL | unsafe { ptr_offset_from(ptr2, ptr1) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far ahead of second
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/offset_from_ub.rs:92:14
+ |
+LL | unsafe { ptr_offset_from(ptr1, ptr2) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from` called when first pointer is too far before second
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/offset_from_ub.rs:99:14
+ |
LL | unsafe { ptr_offset_from_unsigned(p, p.add(2) ) }
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ptr_offset_from_unsigned called when first pointer has smaller offset than second: 0 < 8
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer has smaller offset than second: 0 < 8
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/offset_from_ub.rs:106:14
+ |
+LL | unsafe { ptr_offset_from_unsigned(ptr2, ptr1) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `ptr_offset_from_unsigned` called when first pointer is too far ahead of second
+
+error[E0080]: evaluation of constant value failed
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ |
+LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+ | inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ |
+ ::: $DIR/offset_from_ub.rs:115:14
+ |
+LL | unsafe { ptr2.offset_from(ptr1) }
+ | ---------------------- inside `OFFSET_VERY_FAR1` at $DIR/offset_from_ub.rs:115:14
+
+error[E0080]: evaluation of constant value failed
+ --> $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ |
+LL | unsafe { intrinsics::ptr_offset_from(self, origin) }
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | out-of-bounds offset_from: null pointer is a dangling pointer (it has no provenance)
+ | inside `ptr::const_ptr::<impl *const u8>::offset_from` at $SRC_DIR/core/src/ptr/const_ptr.rs:LL:COL
+ |
+ ::: $DIR/offset_from_ub.rs:121:14
+ |
+LL | unsafe { ptr1.offset_from(ptr2.wrapping_offset(1)) }
+ | ----------------------------------------- inside `OFFSET_VERY_FAR2` at $DIR/offset_from_ub.rs:121:14
-error: aborting due to 10 previous errors
+error: aborting due to 15 previous errors
For more information about this error, try `rustc --explain E0080`.
-error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133)
+error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters
--> $DIR/deriving-with-repr-packed.rs:11:16
|
LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133)
+error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters
--> $DIR/deriving-with-repr-packed.rs:11:32
|
LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133)
+error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
--> $DIR/deriving-with-repr-packed.rs:19:19
|
LL | #[derive(Default, Hash)]
= note: for more information, see issue #82523 <https://github.com/rust-lang/rust/issues/82523>
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
-error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133)
+error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
--> $DIR/deriving-with-repr-packed.rs:39:10
|
LL | #[derive(Debug, Default)]
error: aborting due to 4 previous errors
Future incompatibility report: Future breakage diagnostic:
-error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133)
+error: `Clone` can't be derived on this `#[repr(packed)]` struct with type or const parameters
--> $DIR/deriving-with-repr-packed.rs:11:16
|
LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
= note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
-error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters (error E0133)
+error: `PartialEq` can't be derived on this `#[repr(packed)]` struct with type or const parameters
--> $DIR/deriving-with-repr-packed.rs:11:32
|
LL | #[derive(Copy, Clone, Default, PartialEq, Eq)]
= note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
-error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133)
+error: `Hash` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
--> $DIR/deriving-with-repr-packed.rs:19:19
|
LL | #[derive(Default, Hash)]
= note: this error originates in the derive macro `Hash` (in Nightly builds, run with -Z macro-backtrace for more info)
Future breakage diagnostic:
-error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy` (error E0133)
+error: `Debug` can't be derived on this `#[repr(packed)]` struct that does not derive `Copy`
--> $DIR/deriving-with-repr-packed.rs:39:10
|
LL | #[derive(Debug, Default)]
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Swap` captures lifetime that does not appear in bounds
--> $DIR/hidden-lifetimes.rs:29:5
|
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a {
LL | fn hide_ref<'a, 'b, T: 'static>(x: &'a mut &'b T) -> impl Swap + 'a + 'b {
| ++++
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Swap` captures lifetime that does not appear in bounds
--> $DIR/hidden-lifetimes.rs:46:5
|
LL | fn hide_rc_refcell<'a, 'b: 'a, T: 'static>(x: Rc<RefCell<&'b T>>) -> impl Swap + 'a {
let _: &'b i32 = *u.0;
}
u.0
- //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ //~^ ERROR hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds
}
fn main() {}
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds
--> $DIR/error-handling-2.rs:22:5
|
LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
// 'a in ['d, 'e]
// ```
if condition() { a } else { b }
- //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ //~^ ERROR hidden type for `impl Trait<'d, 'e>` captures lifetime that does not appear in bounds
}
fn condition() -> bool {
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Trait<'d, 'e>` captures lifetime that does not appear in bounds
--> $DIR/ordinary-bounds-unrelated.rs:28:33
|
LL | fn upper_bounds<'a, 'b, 'c, 'd, 'e>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'d, 'e>
//
// We are forced to pick that '0 = 'e, because only 'e is outlived by *both* 'a and 'b.
if condition() { a } else { b }
- //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds
+ //~^ ERROR hidden type for `impl Trait<'a, 'b>` captures lifetime that does not appear in bounds
}
fn condition() -> bool {
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Trait<'a, 'b>` captures lifetime that does not appear in bounds
--> $DIR/ordinary-bounds-unsuited.rs:31:33
|
LL | fn upper_bounds<'a, 'b>(a: Ordinary<'a>, b: Ordinary<'b>) -> impl Trait<'a, 'b>
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear in bounds
--> $DIR/must_outlive_least_region_or_bound.rs:3:35
|
LL | fn elided(x: &i32) -> impl Copy { x }
LL | fn elided(x: &i32) -> impl Copy + '_ { x }
| ++++
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Copy` captures lifetime that does not appear in bounds
--> $DIR/must_outlive_least_region_or_bound.rs:6:44
|
LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x }
| ~~~~~~~~~~~~
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Fn(&'a u32)` captures lifetime that does not appear in bounds
--> $DIR/must_outlive_least_region_or_bound.rs:38:5
|
LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
LL | impl AnotherTrait for D<OpaqueType> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `D<OpaqueType>`
|
- = note: downstream crates may implement trait `std::fmt::Debug` for type `OpaqueType`
+ = note: upstream crates may add a new impl of trait `std::fmt::Debug` for type `OpaqueType` in future versions
error: cannot implement trait on type alias impl trait
--> $DIR/negative-reasoning.rs:19:25
where 'x: 'y
{
x
- //~^ ERROR hidden type for `impl Trait` captures lifetime that does not appear in bounds [E0700]
+ //~^ ERROR hidden type for `impl Trait<'y>` captures lifetime that does not appear in bounds [E0700]
}
fn main() { }
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Trait<'y>` captures lifetime that does not appear in bounds
--> $DIR/region-escape-via-bound.rs:17:5
|
LL | fn foo<'x, 'y>(x: Cell<&'x u32>) -> impl Trait<'y>
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
--> $DIR/static-return-lifetime-infered.rs:7:9
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
| ++++
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
--> $DIR/static-return-lifetime-infered.rs:7:9
|
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
LL | fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
| ++++
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
--> $DIR/static-return-lifetime-infered.rs:12:9
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
| ++++
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Iterator<Item = u32>` captures lifetime that does not appear in bounds
--> $DIR/static-return-lifetime-infered.rs:12:9
|
LL | fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
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() {
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Iterator<Item = u8>` captures lifetime that does not appear in bounds
--> $DIR/issue-73159-rpit-static.rs:8:9
|
LL | impl<'a> Foo<'a> {
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `Opaque(DefId(0:11 ~ impl_trait_captures[1afc]::foo::{opaque#0}), [ReStatic, T, ReEarlyBound(0, 'a)])` captures lifetime that does not appear in bounds
--> $DIR/impl-trait-captures.rs:11:5
|
LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> {
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Clone` captures lifetime that does not appear in bounds
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:48
|
LL | async fn f(self: Pin<&Self>) -> impl Clone { self }
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl Clone` captures lifetime that does not appear in bounds
--> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
|
LL | fn f(self: Pin<&Self>) -> impl Clone { self }
--- /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`.
G: Get<T>,
{
move || {
- //~^ ERROR hidden type for `impl Trait` captures lifetime
+ //~^ ERROR hidden type for `impl FnOnce()` captures lifetime
*dest = g.get();
}
}
| |
| help: consider introducing lifetime `'a` here: `'a,`
-error[E0700]: hidden type for `impl Trait` captures lifetime that does not appear in bounds
+error[E0700]: hidden type for `impl FnOnce()` captures lifetime that does not appear in bounds
--> $DIR/missing-lifetimes-in-signature.rs:19:5
|
LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-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) {