Auto merge of #147692 - matthiaskrgr:rollup-bqhlwyw, r=matthiaskrgr
Rollup of 12 pull requests Successful merges: - rust-lang/rust#146187 (Unstably constify `ptr::drop_in_place` and related methods) - rust-lang/rust#146503 (std: improve handling of timed condition variable waits on macOS) - rust-lang/rust#147526 (Move computation of allocator shim contents to cg_ssa) - rust-lang/rust#147630 (Bitset cleanups) - rust-lang/rust#147638 (bpf: return results larger than one register indirectly) - rust-lang/rust#147666 (Replace manual implementation with `carrying_mul_add`) - rust-lang/rust#147669 (fix missing link to `std::char` in `std` docs) - rust-lang/rust#147673 (pretty print u128 with display) - rust-lang/rust#147677 (Fewer exceptions in `span()` on parsed attributes) - rust-lang/rust#147680 (Fix ICE caused by associated_item_def_ids on wrong type in resolve diag) - rust-lang/rust#147682 (convert `rustc_main` to the new attribute parsing infrastructure) - rust-lang/rust#147683 (only check duplicates on old/unparsed attributes) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
235a4c083e
63 changed files with 716 additions and 545 deletions
|
|
@ -1,7 +1,5 @@
|
|||
use rustc_span::{Symbol, sym};
|
||||
|
||||
use crate::attr::{self, AttributeExt};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum EntryPointType {
|
||||
/// This function is not an entrypoint.
|
||||
|
|
@ -30,11 +28,11 @@ pub enum EntryPointType {
|
|||
}
|
||||
|
||||
pub fn entry_point_type(
|
||||
attrs: &[impl AttributeExt],
|
||||
has_rustc_main: bool,
|
||||
at_root: bool,
|
||||
name: Option<Symbol>,
|
||||
) -> EntryPointType {
|
||||
if attr::contains_name(attrs, sym::rustc_main) {
|
||||
if has_rustc_main {
|
||||
EntryPointType::RustcMainAttr
|
||||
} else if let Some(name) = name
|
||||
&& name == sym::main
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@ use rustc_span::{Symbol, sym};
|
|||
|
||||
#[derive(Clone, Debug, Copy, Eq, PartialEq, HashStable_Generic)]
|
||||
pub enum AllocatorKind {
|
||||
/// Use `#[global_allocator]` as global allocator.
|
||||
Global,
|
||||
/// Use the default implementation in libstd as global allocator.
|
||||
Default,
|
||||
}
|
||||
|
||||
|
|
@ -15,23 +17,22 @@ pub fn default_fn_name(base: Symbol) -> String {
|
|||
format!("__rdl_{base}")
|
||||
}
|
||||
|
||||
pub fn alloc_error_handler_name(alloc_error_handler_kind: AllocatorKind) -> &'static str {
|
||||
match alloc_error_handler_kind {
|
||||
AllocatorKind::Global => "__rg_oom",
|
||||
AllocatorKind::Default => "__rdl_oom",
|
||||
}
|
||||
}
|
||||
|
||||
pub const ALLOC_ERROR_HANDLER: Symbol = sym::alloc_error_handler;
|
||||
pub const NO_ALLOC_SHIM_IS_UNSTABLE: &str = "__rust_no_alloc_shim_is_unstable_v2";
|
||||
|
||||
/// Argument or return type for methods in the allocator shim
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum AllocatorTy {
|
||||
Layout,
|
||||
Never,
|
||||
Ptr,
|
||||
ResultPtr,
|
||||
Unit,
|
||||
Usize,
|
||||
}
|
||||
|
||||
/// A method that will be codegened in the allocator shim.
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct AllocatorMethod {
|
||||
pub name: Symbol,
|
||||
pub inputs: &'static [AllocatorMethodInput],
|
||||
|
|
|
|||
|
|
@ -1,9 +1,18 @@
|
|||
use super::prelude::*;
|
||||
use super::util::parse_single_integer;
|
||||
|
||||
pub(crate) struct RustcLayoutScalarValidRangeStart;
|
||||
pub(crate) struct RustcMainParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart {
|
||||
impl<S: Stage> NoArgsAttributeParser<S> for RustcMainParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_main];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain;
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLayoutScalarValidRangeStartParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStartParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
|
|
@ -16,9 +25,9 @@ impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct RustcLayoutScalarValidRangeEnd;
|
||||
pub(crate) struct RustcLayoutScalarValidRangeEndParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEnd {
|
||||
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEndParser {
|
||||
const PATH: &'static [Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ use crate::attributes::proc_macro_attrs::{
|
|||
use crate::attributes::prototype::CustomMirParser;
|
||||
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
|
||||
use crate::attributes::rustc_internal::{
|
||||
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
|
||||
RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcMainParser,
|
||||
RustcObjectLifetimeDefaultParser, RustcSimdMonomorphizeLaneLimitParser,
|
||||
};
|
||||
use crate::attributes::semantics::MayDangleParser;
|
||||
|
|
@ -197,8 +197,8 @@ attribute_parsers!(
|
|||
Single<RecursionLimitParser>,
|
||||
Single<RustcBuiltinMacroParser>,
|
||||
Single<RustcForceInlineParser>,
|
||||
Single<RustcLayoutScalarValidRangeEnd>,
|
||||
Single<RustcLayoutScalarValidRangeStart>,
|
||||
Single<RustcLayoutScalarValidRangeEndParser>,
|
||||
Single<RustcLayoutScalarValidRangeStartParser>,
|
||||
Single<RustcObjectLifetimeDefaultParser>,
|
||||
Single<RustcSimdMonomorphizeLaneLimitParser>,
|
||||
Single<SanitizeParser>,
|
||||
|
|
@ -238,6 +238,7 @@ attribute_parsers!(
|
|||
Single<WithoutArgs<ProcMacroParser>>,
|
||||
Single<WithoutArgs<PubTransparentParser>>,
|
||||
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
|
||||
Single<WithoutArgs<RustcMainParser>>,
|
||||
Single<WithoutArgs<SpecializationTraitParser>>,
|
||||
Single<WithoutArgs<StdInternalSymbolParser>>,
|
||||
Single<WithoutArgs<TrackCallerParser>>,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustc_ast::expand::allocator::{ALLOC_ERROR_HANDLER, global_fn_name};
|
||||
use rustc_ast::{
|
||||
self as ast, Fn, FnHeader, FnSig, Generics, ItemKind, Safety, Stmt, StmtKind, TyKind,
|
||||
};
|
||||
|
|
@ -55,7 +56,7 @@ pub(crate) fn expand(
|
|||
}
|
||||
|
||||
// #[rustc_std_internal_symbol]
|
||||
// unsafe fn __rg_oom(size: usize, align: usize) -> ! {
|
||||
// unsafe fn __rust_alloc_error_handler(size: usize, align: usize) -> ! {
|
||||
// handler(core::alloc::Layout::from_size_align_unchecked(size, align))
|
||||
// }
|
||||
fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span) -> Stmt {
|
||||
|
|
@ -84,7 +85,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
|
|||
let kind = ItemKind::Fn(Box::new(Fn {
|
||||
defaultness: ast::Defaultness::Final,
|
||||
sig,
|
||||
ident: Ident::from_str_and_span("__rg_oom", span),
|
||||
ident: Ident::from_str_and_span(&global_fn_name(ALLOC_ERROR_HANDLER), span),
|
||||
generics: Generics::default(),
|
||||
contract: None,
|
||||
body,
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ impl AllocFnFactory<'_, '_> {
|
|||
self.cx.expr_ident(self.span, ident)
|
||||
}
|
||||
|
||||
AllocatorTy::ResultPtr | AllocatorTy::Unit => {
|
||||
AllocatorTy::Never | AllocatorTy::ResultPtr | AllocatorTy::Unit => {
|
||||
panic!("can't convert AllocatorTy to an argument")
|
||||
}
|
||||
}
|
||||
|
|
@ -163,7 +163,7 @@ impl AllocFnFactory<'_, '_> {
|
|||
|
||||
AllocatorTy::Unit => self.cx.ty(self.span, TyKind::Tup(ThinVec::new())),
|
||||
|
||||
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
|
||||
AllocatorTy::Layout | AllocatorTy::Never | AllocatorTy::Usize | AllocatorTy::Ptr => {
|
||||
panic!("can't convert `AllocatorTy` to an output")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
use std::mem;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::attr::contains_name;
|
||||
use rustc_ast::entry::EntryPointType;
|
||||
use rustc_ast::mut_visit::*;
|
||||
use rustc_ast::visit::Visitor;
|
||||
|
|
@ -172,9 +173,11 @@ impl<'a> Visitor<'a> for InnerItemLinter<'_> {
|
|||
|
||||
fn entry_point_type(item: &ast::Item, at_root: bool) -> EntryPointType {
|
||||
match &item.kind {
|
||||
ast::ItemKind::Fn(fn_) => {
|
||||
rustc_ast::entry::entry_point_type(&item.attrs, at_root, Some(fn_.ident.name))
|
||||
}
|
||||
ast::ItemKind::Fn(fn_) => rustc_ast::entry::entry_point_type(
|
||||
contains_name(&item.attrs, sym::rustc_main),
|
||||
at_root,
|
||||
Some(fn_.ident.name),
|
||||
),
|
||||
_ => EntryPointType::None,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@
|
|||
|
||||
use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext};
|
||||
use rustc_ast::expand::allocator::{
|
||||
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
|
||||
alloc_error_handler_name, default_fn_name, global_fn_name,
|
||||
AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name,
|
||||
};
|
||||
use rustc_codegen_ssa::base::allocator_kind_for_codegen;
|
||||
use rustc_codegen_ssa::base::{allocator_kind_for_codegen, allocator_shim_contents};
|
||||
use rustc_session::config::OomStrategy;
|
||||
use rustc_symbol_mangling::mangle_internal_symbol;
|
||||
|
||||
|
|
@ -15,74 +14,56 @@ use crate::prelude::*;
|
|||
/// Returns whether an allocator shim was created
|
||||
pub(crate) fn codegen(tcx: TyCtxt<'_>, module: &mut dyn Module) -> bool {
|
||||
let Some(kind) = allocator_kind_for_codegen(tcx) else { return false };
|
||||
codegen_inner(
|
||||
tcx,
|
||||
module,
|
||||
kind,
|
||||
tcx.alloc_error_handler_kind(()).unwrap(),
|
||||
tcx.sess.opts.unstable_opts.oom,
|
||||
);
|
||||
let methods = allocator_shim_contents(tcx, kind);
|
||||
codegen_inner(tcx, module, &methods, tcx.sess.opts.unstable_opts.oom);
|
||||
true
|
||||
}
|
||||
|
||||
fn codegen_inner(
|
||||
tcx: TyCtxt<'_>,
|
||||
module: &mut dyn Module,
|
||||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
methods: &[AllocatorMethod],
|
||||
oom_strategy: OomStrategy,
|
||||
) {
|
||||
let usize_ty = module.target_config().pointer_type();
|
||||
|
||||
if kind == AllocatorKind::Default {
|
||||
for method in ALLOCATOR_METHODS {
|
||||
let mut arg_tys = Vec::with_capacity(method.inputs.len());
|
||||
for input in method.inputs.iter() {
|
||||
match input.ty {
|
||||
AllocatorTy::Layout => {
|
||||
arg_tys.push(usize_ty); // size
|
||||
arg_tys.push(usize_ty); // align
|
||||
}
|
||||
AllocatorTy::Ptr => arg_tys.push(usize_ty),
|
||||
AllocatorTy::Usize => arg_tys.push(usize_ty),
|
||||
for method in methods {
|
||||
let mut arg_tys = Vec::with_capacity(method.inputs.len());
|
||||
for input in method.inputs.iter() {
|
||||
match input.ty {
|
||||
AllocatorTy::Layout => {
|
||||
arg_tys.push(usize_ty); // size
|
||||
arg_tys.push(usize_ty); // align
|
||||
}
|
||||
AllocatorTy::Ptr => arg_tys.push(usize_ty),
|
||||
AllocatorTy::Usize => arg_tys.push(usize_ty),
|
||||
|
||||
AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
|
||||
AllocatorTy::Never | AllocatorTy::ResultPtr | AllocatorTy::Unit => {
|
||||
panic!("invalid allocator arg")
|
||||
}
|
||||
}
|
||||
let output = match method.output {
|
||||
AllocatorTy::ResultPtr => Some(usize_ty),
|
||||
AllocatorTy::Unit => None,
|
||||
|
||||
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
|
||||
panic!("invalid allocator output")
|
||||
}
|
||||
};
|
||||
|
||||
let sig = Signature {
|
||||
call_conv: module.target_config().default_call_conv,
|
||||
params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
|
||||
returns: output.into_iter().map(AbiParam::new).collect(),
|
||||
};
|
||||
crate::common::create_wrapper_function(
|
||||
module,
|
||||
sig,
|
||||
&mangle_internal_symbol(tcx, &global_fn_name(method.name)),
|
||||
&mangle_internal_symbol(tcx, &default_fn_name(method.name)),
|
||||
);
|
||||
}
|
||||
}
|
||||
let output = match method.output {
|
||||
AllocatorTy::ResultPtr => Some(usize_ty),
|
||||
AllocatorTy::Never | AllocatorTy::Unit => None,
|
||||
|
||||
let sig = Signature {
|
||||
call_conv: module.target_config().default_call_conv,
|
||||
params: vec![AbiParam::new(usize_ty), AbiParam::new(usize_ty)],
|
||||
returns: vec![],
|
||||
};
|
||||
crate::common::create_wrapper_function(
|
||||
module,
|
||||
sig,
|
||||
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
|
||||
&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind)),
|
||||
);
|
||||
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
|
||||
panic!("invalid allocator output")
|
||||
}
|
||||
};
|
||||
|
||||
let sig = Signature {
|
||||
call_conv: module.target_config().default_call_conv,
|
||||
params: arg_tys.iter().cloned().map(AbiParam::new).collect(),
|
||||
returns: output.into_iter().map(AbiParam::new).collect(),
|
||||
};
|
||||
crate::common::create_wrapper_function(
|
||||
module,
|
||||
sig,
|
||||
&mangle_internal_symbol(tcx, &global_fn_name(method.name)),
|
||||
&mangle_internal_symbol(tcx, &default_fn_name(method.name)),
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
let sig = Signature {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,7 @@
|
|||
use gccjit::FnAttribute;
|
||||
use gccjit::{Context, FunctionType, RValue, ToRValue, Type};
|
||||
use rustc_ast::expand::allocator::{
|
||||
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
|
||||
alloc_error_handler_name, default_fn_name, global_fn_name,
|
||||
AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name,
|
||||
};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
|
@ -18,8 +17,7 @@ pub(crate) unsafe fn codegen(
|
|||
tcx: TyCtxt<'_>,
|
||||
mods: &mut GccContext,
|
||||
_module_name: &str,
|
||||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
methods: &[AllocatorMethod],
|
||||
) {
|
||||
let context = &mods.context;
|
||||
let usize = match tcx.sess.target.pointer_width {
|
||||
|
|
@ -31,45 +29,35 @@ pub(crate) unsafe fn codegen(
|
|||
let i8 = context.new_type::<i8>();
|
||||
let i8p = i8.make_pointer();
|
||||
|
||||
if kind == AllocatorKind::Default {
|
||||
for method in ALLOCATOR_METHODS {
|
||||
let mut types = Vec::with_capacity(method.inputs.len());
|
||||
for input in method.inputs.iter() {
|
||||
match input.ty {
|
||||
AllocatorTy::Layout => {
|
||||
types.push(usize);
|
||||
types.push(usize);
|
||||
}
|
||||
AllocatorTy::Ptr => types.push(i8p),
|
||||
AllocatorTy::Usize => types.push(usize),
|
||||
for method in methods {
|
||||
let mut types = Vec::with_capacity(method.inputs.len());
|
||||
for input in method.inputs.iter() {
|
||||
match input.ty {
|
||||
AllocatorTy::Layout => {
|
||||
types.push(usize);
|
||||
types.push(usize);
|
||||
}
|
||||
AllocatorTy::Ptr => types.push(i8p),
|
||||
AllocatorTy::Usize => types.push(usize),
|
||||
|
||||
AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
|
||||
AllocatorTy::Never | AllocatorTy::ResultPtr | AllocatorTy::Unit => {
|
||||
panic!("invalid allocator arg")
|
||||
}
|
||||
}
|
||||
let output = match method.output {
|
||||
AllocatorTy::ResultPtr => Some(i8p),
|
||||
AllocatorTy::Unit => None,
|
||||
|
||||
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
|
||||
panic!("invalid allocator output")
|
||||
}
|
||||
};
|
||||
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
|
||||
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
|
||||
|
||||
create_wrapper_function(tcx, context, &from_name, Some(&to_name), &types, output);
|
||||
}
|
||||
}
|
||||
let output = match method.output {
|
||||
AllocatorTy::ResultPtr => Some(i8p),
|
||||
AllocatorTy::Never | AllocatorTy::Unit => None,
|
||||
|
||||
// FIXME(bjorn3): Add noreturn attribute
|
||||
create_wrapper_function(
|
||||
tcx,
|
||||
context,
|
||||
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
|
||||
Some(&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind))),
|
||||
&[usize, usize],
|
||||
None,
|
||||
);
|
||||
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
|
||||
panic!("invalid allocator output")
|
||||
}
|
||||
};
|
||||
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
|
||||
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
|
||||
|
||||
create_wrapper_function(tcx, context, &from_name, Some(&to_name), &types, output);
|
||||
}
|
||||
|
||||
create_const_value_function(
|
||||
tcx,
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ use back::lto::{ThinBuffer, ThinData};
|
|||
use gccjit::{CType, Context, OptimizationLevel};
|
||||
#[cfg(feature = "master")]
|
||||
use gccjit::{TargetInfo, Version};
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_ast::expand::allocator::AllocatorMethod;
|
||||
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule};
|
||||
use rustc_codegen_ssa::back::write::{
|
||||
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn,
|
||||
|
|
@ -284,8 +284,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
|
|||
&self,
|
||||
tcx: TyCtxt<'_>,
|
||||
module_name: &str,
|
||||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
methods: &[AllocatorMethod],
|
||||
) -> Self::Module {
|
||||
let mut mods = GccContext {
|
||||
context: Arc::new(SyncContext::new(new_context(tcx))),
|
||||
|
|
@ -295,7 +294,7 @@ impl ExtraBackendMethods for GccCodegenBackend {
|
|||
};
|
||||
|
||||
unsafe {
|
||||
allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind);
|
||||
allocator::codegen(tcx, &mut mods, module_name, methods);
|
||||
}
|
||||
mods
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
use libc::c_uint;
|
||||
use rustc_ast::expand::allocator::{
|
||||
ALLOCATOR_METHODS, AllocatorKind, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE,
|
||||
alloc_error_handler_name, default_fn_name, global_fn_name,
|
||||
AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name,
|
||||
};
|
||||
use rustc_codegen_ssa::traits::BaseTypeCodegenMethods as _;
|
||||
use rustc_middle::bug;
|
||||
|
|
@ -21,8 +20,7 @@ pub(crate) unsafe fn codegen(
|
|||
tcx: TyCtxt<'_>,
|
||||
cx: SimpleCx<'_>,
|
||||
module_name: &str,
|
||||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
methods: &[AllocatorMethod],
|
||||
) {
|
||||
let usize = match tcx.sess.target.pointer_width {
|
||||
16 => cx.type_i16(),
|
||||
|
|
@ -33,91 +31,85 @@ pub(crate) unsafe fn codegen(
|
|||
let i8 = cx.type_i8();
|
||||
let i8p = cx.type_ptr();
|
||||
|
||||
if kind == AllocatorKind::Default {
|
||||
for method in ALLOCATOR_METHODS {
|
||||
let mut args = Vec::with_capacity(method.inputs.len());
|
||||
for input in method.inputs.iter() {
|
||||
match input.ty {
|
||||
AllocatorTy::Layout => {
|
||||
args.push(usize); // size
|
||||
args.push(usize); // align
|
||||
}
|
||||
AllocatorTy::Ptr => args.push(i8p),
|
||||
AllocatorTy::Usize => args.push(usize),
|
||||
for method in methods {
|
||||
let mut args = Vec::with_capacity(method.inputs.len());
|
||||
for input in method.inputs.iter() {
|
||||
match input.ty {
|
||||
AllocatorTy::Layout => {
|
||||
args.push(usize); // size
|
||||
args.push(usize); // align
|
||||
}
|
||||
AllocatorTy::Ptr => args.push(i8p),
|
||||
AllocatorTy::Usize => args.push(usize),
|
||||
|
||||
AllocatorTy::ResultPtr | AllocatorTy::Unit => panic!("invalid allocator arg"),
|
||||
AllocatorTy::Never | AllocatorTy::ResultPtr | AllocatorTy::Unit => {
|
||||
panic!("invalid allocator arg")
|
||||
}
|
||||
}
|
||||
let output = match method.output {
|
||||
AllocatorTy::ResultPtr => Some(i8p),
|
||||
AllocatorTy::Unit => None,
|
||||
|
||||
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
|
||||
panic!("invalid allocator output")
|
||||
}
|
||||
};
|
||||
|
||||
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
|
||||
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
|
||||
|
||||
let alloc_attr_flag = match method.name {
|
||||
sym::alloc => CodegenFnAttrFlags::ALLOCATOR,
|
||||
sym::dealloc => CodegenFnAttrFlags::DEALLOCATOR,
|
||||
sym::realloc => CodegenFnAttrFlags::REALLOCATOR,
|
||||
sym::alloc_zeroed => CodegenFnAttrFlags::ALLOCATOR_ZEROED,
|
||||
_ => unreachable!("Unknown allocator method!"),
|
||||
};
|
||||
|
||||
let mut attrs = CodegenFnAttrs::new();
|
||||
attrs.flags |= alloc_attr_flag;
|
||||
create_wrapper_function(
|
||||
tcx,
|
||||
&cx,
|
||||
&from_name,
|
||||
Some(&to_name),
|
||||
&args,
|
||||
output,
|
||||
false,
|
||||
&attrs,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// rust alloc error handler
|
||||
create_wrapper_function(
|
||||
tcx,
|
||||
&cx,
|
||||
&mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
|
||||
Some(&mangle_internal_symbol(tcx, alloc_error_handler_name(alloc_error_handler_kind))),
|
||||
&[usize, usize], // size, align
|
||||
None,
|
||||
true,
|
||||
&CodegenFnAttrs::new(),
|
||||
);
|
||||
let mut no_return = false;
|
||||
let output = match method.output {
|
||||
AllocatorTy::ResultPtr => Some(i8p),
|
||||
AllocatorTy::Unit => None,
|
||||
AllocatorTy::Never => {
|
||||
no_return = true;
|
||||
None
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// __rust_alloc_error_handler_should_panic_v2
|
||||
create_const_value_function(
|
||||
tcx,
|
||||
&cx,
|
||||
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
|
||||
&i8,
|
||||
&llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, FALSE),
|
||||
);
|
||||
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
|
||||
panic!("invalid allocator output")
|
||||
}
|
||||
};
|
||||
|
||||
// __rust_no_alloc_shim_is_unstable_v2
|
||||
let from_name = mangle_internal_symbol(tcx, &global_fn_name(method.name));
|
||||
let to_name = mangle_internal_symbol(tcx, &default_fn_name(method.name));
|
||||
|
||||
let alloc_attr_flag = match method.name {
|
||||
sym::alloc => CodegenFnAttrFlags::ALLOCATOR,
|
||||
sym::dealloc => CodegenFnAttrFlags::DEALLOCATOR,
|
||||
sym::realloc => CodegenFnAttrFlags::REALLOCATOR,
|
||||
sym::alloc_zeroed => CodegenFnAttrFlags::ALLOCATOR_ZEROED,
|
||||
_ => CodegenFnAttrFlags::empty(),
|
||||
};
|
||||
|
||||
let mut attrs = CodegenFnAttrs::new();
|
||||
attrs.flags |= alloc_attr_flag;
|
||||
create_wrapper_function(
|
||||
tcx,
|
||||
&cx,
|
||||
&mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
|
||||
None,
|
||||
&[],
|
||||
None,
|
||||
false,
|
||||
&CodegenFnAttrs::new(),
|
||||
&from_name,
|
||||
Some(&to_name),
|
||||
&args,
|
||||
output,
|
||||
no_return,
|
||||
&attrs,
|
||||
);
|
||||
}
|
||||
|
||||
// __rust_alloc_error_handler_should_panic_v2
|
||||
create_const_value_function(
|
||||
tcx,
|
||||
&cx,
|
||||
&mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
|
||||
&i8,
|
||||
unsafe {
|
||||
llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, FALSE)
|
||||
},
|
||||
);
|
||||
|
||||
// __rust_no_alloc_shim_is_unstable_v2
|
||||
create_wrapper_function(
|
||||
tcx,
|
||||
&cx,
|
||||
&mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
|
||||
None,
|
||||
&[],
|
||||
None,
|
||||
false,
|
||||
&CodegenFnAttrs::new(),
|
||||
);
|
||||
|
||||
if tcx.sess.opts.debuginfo != DebugInfo::None {
|
||||
let dbg_cx = debuginfo::CodegenUnitDebugContext::new(cx.llmod);
|
||||
debuginfo::metadata::build_compile_unit_di_node(tcx, module_name, &dbg_cx);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ use back::write::{create_informational_target_machine, create_target_machine};
|
|||
use context::SimpleCx;
|
||||
use errors::ParseTargetMachineConfig;
|
||||
use llvm_util::target_config;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_ast::expand::allocator::AllocatorMethod;
|
||||
use rustc_codegen_ssa::back::lto::{SerializedModule, ThinModule};
|
||||
use rustc_codegen_ssa::back::write::{
|
||||
CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
|
||||
|
|
@ -109,14 +109,13 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
|||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
module_name: &str,
|
||||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
methods: &[AllocatorMethod],
|
||||
) -> ModuleLlvm {
|
||||
let module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
|
||||
let cx =
|
||||
SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size());
|
||||
unsafe {
|
||||
allocator::codegen(tcx, cx, module_name, kind, alloc_error_handler_kind);
|
||||
allocator::codegen(tcx, cx, module_name, methods);
|
||||
}
|
||||
module_llvm
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
use std::collections::hash_map::Entry::*;
|
||||
|
||||
use rustc_abi::{CanonAbi, X86Call};
|
||||
use rustc_ast::expand::allocator::{ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name};
|
||||
use rustc_ast::expand::allocator::{
|
||||
ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, NO_ALLOC_SHIM_IS_UNSTABLE, global_fn_name,
|
||||
};
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE, LocalDefId};
|
||||
|
|
@ -498,7 +500,7 @@ pub(crate) fn allocator_shim_symbols(
|
|||
.iter()
|
||||
.map(move |method| mangle_internal_symbol(tcx, global_fn_name(method.name).as_str()))
|
||||
.chain([
|
||||
mangle_internal_symbol(tcx, "__rust_alloc_error_handler"),
|
||||
mangle_internal_symbol(tcx, global_fn_name(ALLOC_ERROR_HANDLER).as_str()),
|
||||
mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
|
||||
mangle_internal_symbol(tcx, NO_ALLOC_SHIM_IS_UNSTABLE),
|
||||
])
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@ use std::time::{Duration, Instant};
|
|||
use itertools::Itertools;
|
||||
use rustc_abi::FIRST_VARIANT;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_ast::expand::allocator::{
|
||||
ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorMethod, AllocatorTy,
|
||||
};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
|
||||
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
|
||||
|
|
@ -655,6 +657,26 @@ pub(crate) fn needs_allocator_shim_for_linking(
|
|||
!any_dynamic_crate
|
||||
}
|
||||
|
||||
pub fn allocator_shim_contents(tcx: TyCtxt<'_>, kind: AllocatorKind) -> Vec<AllocatorMethod> {
|
||||
let mut methods = Vec::new();
|
||||
|
||||
if kind == AllocatorKind::Default {
|
||||
methods.extend(ALLOCATOR_METHODS.into_iter().copied());
|
||||
}
|
||||
|
||||
// If the return value of allocator_kind_for_codegen is Some then
|
||||
// alloc_error_handler_kind must also be Some.
|
||||
if tcx.alloc_error_handler_kind(()).unwrap() == AllocatorKind::Default {
|
||||
methods.push(AllocatorMethod {
|
||||
name: ALLOC_ERROR_HANDLER,
|
||||
inputs: &[],
|
||||
output: AllocatorTy::Never,
|
||||
});
|
||||
}
|
||||
|
||||
methods
|
||||
}
|
||||
|
||||
pub fn codegen_crate<B: ExtraBackendMethods>(
|
||||
backend: B,
|
||||
tcx: TyCtxt<'_>,
|
||||
|
|
@ -699,14 +721,8 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
|
||||
|
||||
tcx.sess.time("write_allocator_module", || {
|
||||
let module = backend.codegen_allocator(
|
||||
tcx,
|
||||
&llmod_id,
|
||||
kind,
|
||||
// If allocator_kind is Some then alloc_error_handler_kind must
|
||||
// also be Some.
|
||||
tcx.alloc_error_handler_kind(()).unwrap(),
|
||||
);
|
||||
let module =
|
||||
backend.codegen_allocator(tcx, &llmod_id, &allocator_shim_contents(tcx, kind));
|
||||
Some(ModuleCodegen::new_allocator(llmod_id, module))
|
||||
})
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ fn process_builtin_attrs(
|
|||
AttributeKind::StdInternalSymbol(_) => {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
|
||||
}
|
||||
AttributeKind::Linkage(linkage, _) => {
|
||||
AttributeKind::Linkage(linkage, span) => {
|
||||
let linkage = Some(*linkage);
|
||||
|
||||
if tcx.is_foreign_item(did) {
|
||||
|
|
@ -287,7 +287,7 @@ fn process_builtin_attrs(
|
|||
|
||||
if tcx.is_mutable_static(did.into()) {
|
||||
let mut diag = tcx.dcx().struct_span_err(
|
||||
attr.span(),
|
||||
*span,
|
||||
"extern mutable statics are not allowed with `#[linkage]`",
|
||||
);
|
||||
diag.note(
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use std::any::Any;
|
||||
use std::hash::Hash;
|
||||
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_ast::expand::allocator::AllocatorMethod;
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_data_structures::sync::{DynSend, DynSync};
|
||||
use rustc_metadata::EncodedMetadata;
|
||||
|
|
@ -116,8 +116,7 @@ pub trait ExtraBackendMethods:
|
|||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
module_name: &str,
|
||||
kind: AllocatorKind,
|
||||
alloc_error_handler_kind: AllocatorKind,
|
||||
methods: &[AllocatorMethod],
|
||||
) -> Self::Module;
|
||||
|
||||
/// This generates the codegen unit and returns it along with
|
||||
|
|
|
|||
|
|
@ -670,6 +670,9 @@ pub enum AttributeKind {
|
|||
/// Represents `#[rustc_layout_scalar_valid_range_start]`.
|
||||
RustcLayoutScalarValidRangeStart(Box<u128>, Span),
|
||||
|
||||
/// Represents `#[rustc_main]`.
|
||||
RustcMain,
|
||||
|
||||
/// Represents `#[rustc_object_lifetime_default]`.
|
||||
RustcObjectLifetimeDefault,
|
||||
|
||||
|
|
|
|||
|
|
@ -88,6 +88,7 @@ impl AttributeKind {
|
|||
RustcCoherenceIsCore(..) => No,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
RustcMain => No,
|
||||
RustcObjectLifetimeDefault => No,
|
||||
RustcSimdMonomorphizeLaneLimit(..) => Yes, // Affects layout computation, which needs to work cross-crate
|
||||
Sanitize { .. } => No,
|
||||
|
|
|
|||
|
|
@ -26,16 +26,6 @@ pub trait PrintAttribute {
|
|||
fn print_attribute(&self, p: &mut Printer);
|
||||
}
|
||||
|
||||
impl PrintAttribute for u128 {
|
||||
fn should_render(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn print_attribute(&self, p: &mut Printer) {
|
||||
p.word(self.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: PrintAttribute> PrintAttribute for &T {
|
||||
fn should_render(&self) -> bool {
|
||||
T::should_render(self)
|
||||
|
|
@ -148,7 +138,7 @@ macro_rules! print_tup {
|
|||
|
||||
print_tup!(A B C D E F G H);
|
||||
print_skip!(Span, (), ErrorGuaranteed);
|
||||
print_disp!(u16, bool, NonZero<u32>, Limit);
|
||||
print_disp!(u16, u128, bool, NonZero<u32>, Limit);
|
||||
print_debug!(
|
||||
Symbol,
|
||||
Ident,
|
||||
|
|
|
|||
|
|
@ -1315,8 +1315,6 @@ impl AttributeExt for Attribute {
|
|||
// FIXME: should not be needed anymore when all attrs are parsed
|
||||
Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span,
|
||||
Attribute::Parsed(AttributeKind::Deprecation { span, .. }) => *span,
|
||||
Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span)) => *span,
|
||||
Attribute::Parsed(AttributeKind::Linkage(_, span)) => *span,
|
||||
a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ impl<T: Idx> DenseBitSet<T> {
|
|||
|
||||
/// Count the number of set bits in the set.
|
||||
pub fn count(&self) -> usize {
|
||||
self.words.iter().map(|e| e.count_ones() as usize).sum()
|
||||
count_ones(&self.words)
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` contains `elem`.
|
||||
|
|
@ -786,7 +786,7 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
|
|||
|
||||
match (&mut self_chunk, &other_chunk) {
|
||||
(_, Zeros) | (Ones, _) => {}
|
||||
(Zeros, Ones) | (Mixed(..), Ones) | (Zeros, Mixed(..)) => {
|
||||
(Zeros, _) | (Mixed(..), Ones) => {
|
||||
// `other_chunk` fully overwrites `self_chunk`
|
||||
*self_chunk = other_chunk.clone();
|
||||
changed = true;
|
||||
|
|
@ -814,10 +814,8 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
|
|||
op,
|
||||
);
|
||||
debug_assert!(has_changed);
|
||||
*self_chunk_count = self_chunk_words[0..num_words]
|
||||
.iter()
|
||||
.map(|w| w.count_ones() as ChunkSize)
|
||||
.sum();
|
||||
*self_chunk_count =
|
||||
count_ones(&self_chunk_words[0..num_words]) as ChunkSize;
|
||||
if *self_chunk_count == chunk_domain_size {
|
||||
*self_chunk = Ones;
|
||||
}
|
||||
|
|
@ -850,7 +848,7 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
|
|||
|
||||
match (&mut self_chunk, &other_chunk) {
|
||||
(Zeros, _) | (_, Zeros) => {}
|
||||
(Ones | Mixed(_, _), Ones) => {
|
||||
(Ones | Mixed(..), Ones) => {
|
||||
changed = true;
|
||||
*self_chunk = Zeros;
|
||||
}
|
||||
|
|
@ -868,10 +866,7 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
|
|||
let self_chunk_count = chunk_domain_size - *other_chunk_count;
|
||||
debug_assert_eq!(
|
||||
self_chunk_count,
|
||||
self_chunk_words[0..num_words]
|
||||
.iter()
|
||||
.map(|w| w.count_ones() as ChunkSize)
|
||||
.sum()
|
||||
count_ones(&self_chunk_words[0..num_words]) as ChunkSize
|
||||
);
|
||||
*self_chunk = Mixed(self_chunk_count, Rc::new(self_chunk_words));
|
||||
}
|
||||
|
|
@ -894,10 +889,8 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
|
|||
op,
|
||||
);
|
||||
debug_assert!(has_changed);
|
||||
*self_chunk_count = self_chunk_words[0..num_words]
|
||||
.iter()
|
||||
.map(|w| w.count_ones() as ChunkSize)
|
||||
.sum();
|
||||
*self_chunk_count =
|
||||
count_ones(&self_chunk_words[0..num_words]) as ChunkSize;
|
||||
if *self_chunk_count == 0 {
|
||||
*self_chunk = Zeros;
|
||||
}
|
||||
|
|
@ -953,10 +946,8 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
|
|||
op,
|
||||
);
|
||||
debug_assert!(has_changed);
|
||||
*self_chunk_count = self_chunk_words[0..num_words]
|
||||
.iter()
|
||||
.map(|w| w.count_ones() as ChunkSize)
|
||||
.sum();
|
||||
*self_chunk_count =
|
||||
count_ones(&self_chunk_words[0..num_words]) as ChunkSize;
|
||||
if *self_chunk_count == 0 {
|
||||
*self_chunk = Zeros;
|
||||
}
|
||||
|
|
@ -970,48 +961,6 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Idx> BitRelations<ChunkedBitSet<T>> for DenseBitSet<T> {
|
||||
fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
|
||||
sequential_update(|elem| self.insert(elem), other.iter())
|
||||
}
|
||||
|
||||
fn subtract(&mut self, _other: &ChunkedBitSet<T>) -> bool {
|
||||
unimplemented!("implement if/when necessary");
|
||||
}
|
||||
|
||||
fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
|
||||
assert_eq!(self.domain_size(), other.domain_size);
|
||||
let mut changed = false;
|
||||
for (i, chunk) in other.chunks.iter().enumerate() {
|
||||
let mut words = &mut self.words[i * CHUNK_WORDS..];
|
||||
if words.len() > CHUNK_WORDS {
|
||||
words = &mut words[..CHUNK_WORDS];
|
||||
}
|
||||
match chunk {
|
||||
Zeros => {
|
||||
for word in words {
|
||||
if *word != 0 {
|
||||
changed = true;
|
||||
*word = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ones => (),
|
||||
Mixed(_, data) => {
|
||||
for (i, word) in words.iter_mut().enumerate() {
|
||||
let new_val = *word & data[i];
|
||||
if new_val != *word {
|
||||
changed = true;
|
||||
*word = new_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
changed
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Clone for ChunkedBitSet<T> {
|
||||
fn clone(&self) -> Self {
|
||||
ChunkedBitSet {
|
||||
|
|
@ -1085,21 +1034,12 @@ impl Chunk {
|
|||
assert!(0 < count && count < chunk_domain_size);
|
||||
|
||||
// Check the number of set bits matches `count`.
|
||||
assert_eq!(
|
||||
words.iter().map(|w| w.count_ones() as ChunkSize).sum::<ChunkSize>(),
|
||||
count
|
||||
);
|
||||
assert_eq!(count_ones(words.as_slice()) as ChunkSize, count);
|
||||
|
||||
// Check the not-in-use words are all zeroed.
|
||||
let num_words = num_words(chunk_domain_size as usize);
|
||||
if num_words < CHUNK_WORDS {
|
||||
assert_eq!(
|
||||
words[num_words..]
|
||||
.iter()
|
||||
.map(|w| w.count_ones() as ChunkSize)
|
||||
.sum::<ChunkSize>(),
|
||||
0
|
||||
);
|
||||
assert_eq!(count_ones(&words[num_words..]) as ChunkSize, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1122,15 +1062,6 @@ enum ChunkIter<'a> {
|
|||
Finished,
|
||||
}
|
||||
|
||||
// Applies a function to mutate a bitset, and returns true if any
|
||||
// of the applications return true
|
||||
fn sequential_update<T: Idx>(
|
||||
mut self_update: impl FnMut(T) -> bool,
|
||||
it: impl Iterator<Item = T>,
|
||||
) -> bool {
|
||||
it.fold(false, |changed, elem| self_update(elem) | changed)
|
||||
}
|
||||
|
||||
impl<T: Idx> fmt::Debug for ChunkedBitSet<T> {
|
||||
fn fmt(&self, w: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
w.debug_list().entries(self.iter()).finish()
|
||||
|
|
@ -1590,7 +1521,7 @@ impl<R: Idx, C: Idx> BitMatrix<R, C> {
|
|||
/// Returns the number of elements in `row`.
|
||||
pub fn count(&self, row: R) -> usize {
|
||||
let (start, end) = self.range(row);
|
||||
self.words[start..end].iter().map(|e| e.count_ones() as usize).sum()
|
||||
count_ones(&self.words[start..end])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1801,6 +1732,11 @@ fn max_bit(word: Word) -> usize {
|
|||
WORD_BITS - 1 - word.leading_zeros() as usize
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count_ones(words: &[Word]) -> usize {
|
||||
words.iter().map(|word| word.count_ones() as usize).sum()
|
||||
}
|
||||
|
||||
/// Integral type used to represent the bit set.
|
||||
pub trait FiniteBitSetTy:
|
||||
BitAnd<Output = Self>
|
||||
|
|
|
|||
|
|
@ -306,34 +306,6 @@ fn with_elements_chunked(elements: &[usize], domain_size: usize) -> ChunkedBitSe
|
|||
s
|
||||
}
|
||||
|
||||
fn with_elements_standard(elements: &[usize], domain_size: usize) -> DenseBitSet<usize> {
|
||||
let mut s = DenseBitSet::new_empty(domain_size);
|
||||
for &e in elements {
|
||||
assert!(s.insert(e));
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chunked_bitset_into_bitset_operations() {
|
||||
let a = vec![1, 5, 7, 11, 15, 2000, 3000];
|
||||
let b = vec![3, 4, 11, 3000, 4000];
|
||||
let aub = vec![1, 3, 4, 5, 7, 11, 15, 2000, 3000, 4000];
|
||||
let aib = vec![11, 3000];
|
||||
|
||||
let b = with_elements_chunked(&b, 9876);
|
||||
|
||||
let mut union = with_elements_standard(&a, 9876);
|
||||
assert!(union.union(&b));
|
||||
assert!(!union.union(&b));
|
||||
assert!(union.iter().eq(aub.iter().copied()));
|
||||
|
||||
let mut intersection = with_elements_standard(&a, 9876);
|
||||
assert!(intersection.intersect(&b));
|
||||
assert!(!intersection.intersect(&b));
|
||||
assert!(intersection.iter().eq(aib.iter().copied()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn chunked_bitset_iter() {
|
||||
fn check_iter(bit: &ChunkedBitSet<usize>, vec: &Vec<usize>) {
|
||||
|
|
|
|||
|
|
@ -310,15 +310,17 @@ impl EarlyLintPass for UnsafeCode {
|
|||
}
|
||||
|
||||
ast::ItemKind::MacroDef(..) => {
|
||||
if let Some(attr) = AttributeParser::parse_limited(
|
||||
cx.builder.sess(),
|
||||
&it.attrs,
|
||||
sym::allow_internal_unsafe,
|
||||
it.span,
|
||||
DUMMY_NODE_ID,
|
||||
Some(cx.builder.features()),
|
||||
) {
|
||||
self.report_unsafe(cx, attr.span(), BuiltinUnsafe::AllowInternalUnsafe);
|
||||
if let Some(hir::Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span))) =
|
||||
AttributeParser::parse_limited(
|
||||
cx.builder.sess(),
|
||||
&it.attrs,
|
||||
sym::allow_internal_unsafe,
|
||||
it.span,
|
||||
DUMMY_NODE_ID,
|
||||
Some(cx.builder.features()),
|
||||
)
|
||||
{
|
||||
self.report_unsafe(cx, span, BuiltinUnsafe::AllowInternalUnsafe);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use std::str::FromStr;
|
|||
use std::time::Duration;
|
||||
use std::{cmp, env, iter};
|
||||
|
||||
use rustc_ast::expand::allocator::{AllocatorKind, alloc_error_handler_name, global_fn_name};
|
||||
use rustc_ast::expand::allocator::{ALLOC_ERROR_HANDLER, AllocatorKind, global_fn_name};
|
||||
use rustc_ast::{self as ast, *};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::owned_slice::OwnedSlice;
|
||||
|
|
@ -1087,10 +1087,8 @@ impl CStore {
|
|||
}
|
||||
spans => !spans.is_empty(),
|
||||
};
|
||||
self.has_alloc_error_handler = match &*fn_spans(
|
||||
krate,
|
||||
Symbol::intern(alloc_error_handler_name(AllocatorKind::Global)),
|
||||
) {
|
||||
let alloc_error_handler = Symbol::intern(&global_fn_name(ALLOC_ERROR_HANDLER));
|
||||
self.has_alloc_error_handler = match &*fn_spans(krate, alloc_error_handler) {
|
||||
[span1, span2, ..] => {
|
||||
tcx.dcx()
|
||||
.emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
|
||||
|
|
|
|||
|
|
@ -34,9 +34,6 @@ passes_attr_crate_level =
|
|||
.suggestion = to apply to the crate, use an inner attribute
|
||||
.note = read <https://doc.rust-lang.org/nightly/rustdoc/the-doc-attribute.html#at-the-crate-level> for more information
|
||||
|
||||
passes_attr_only_in_functions =
|
||||
`{$attr}` attribute can only be used on functions
|
||||
|
||||
passes_autodiff_attr =
|
||||
`#[autodiff]` should be applied to a function
|
||||
.label = not a function
|
||||
|
|
|
|||
|
|
@ -283,6 +283,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::ObjcSelector { .. }
|
||||
| AttributeKind::RustcCoherenceIsCore(..)
|
||||
| AttributeKind::DebuggerVisualizer(..)
|
||||
| AttributeKind::RustcMain,
|
||||
) => { /* do nothing */ }
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
|
|
@ -394,8 +395,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
let builtin = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
|
||||
|
||||
if hir_id != CRATE_HIR_ID {
|
||||
match attr {
|
||||
Attribute::Parsed(_) => { /* Already validated. */ }
|
||||
|
|
@ -441,8 +440,18 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
if let Some(BuiltinAttribute { duplicates, .. }) = builtin {
|
||||
check_duplicates(self.tcx, attr, hir_id, *duplicates, &mut seen);
|
||||
if let Attribute::Unparsed(unparsed_attr) = attr
|
||||
&& let Some(BuiltinAttribute { duplicates, .. }) =
|
||||
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
|
||||
{
|
||||
check_duplicates(
|
||||
self.tcx,
|
||||
unparsed_attr.span,
|
||||
attr,
|
||||
hir_id,
|
||||
*duplicates,
|
||||
&mut seen,
|
||||
);
|
||||
}
|
||||
|
||||
self.check_unused_attribute(hir_id, attr, style)
|
||||
|
|
@ -2397,14 +2406,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
|
|||
// Check for builtin attributes at the crate level
|
||||
// which were unsuccessfully resolved due to cannot determine
|
||||
// resolution for the attribute macro error.
|
||||
const ATTRS_TO_CHECK: &[Symbol] = &[
|
||||
sym::rustc_main,
|
||||
sym::derive,
|
||||
sym::test,
|
||||
sym::test_case,
|
||||
sym::global_allocator,
|
||||
sym::bench,
|
||||
];
|
||||
const ATTRS_TO_CHECK: &[Symbol] =
|
||||
&[sym::derive, sym::test, sym::test_case, sym::global_allocator, sym::bench];
|
||||
|
||||
for attr in attrs {
|
||||
// FIXME(jdonszelmann): all attrs should be combined here cleaning this up some day.
|
||||
|
|
@ -2483,6 +2486,7 @@ pub(crate) fn provide(providers: &mut Providers) {
|
|||
// FIXME(jdonszelmann): remove, check during parsing
|
||||
fn check_duplicates(
|
||||
tcx: TyCtxt<'_>,
|
||||
attr_span: Span,
|
||||
attr: &Attribute,
|
||||
hir_id: HirId,
|
||||
duplicates: AttributeDuplicates,
|
||||
|
|
@ -2499,10 +2503,10 @@ fn check_duplicates(
|
|||
match seen.entry(attr_name) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
let (this, other) = if matches!(duplicates, FutureWarnPreceding) {
|
||||
let to_remove = entry.insert(attr.span());
|
||||
(to_remove, attr.span())
|
||||
let to_remove = entry.insert(attr_span);
|
||||
(to_remove, attr_span)
|
||||
} else {
|
||||
(attr.span(), *entry.get())
|
||||
(attr_span, *entry.get())
|
||||
};
|
||||
tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
|
|
@ -2519,22 +2523,22 @@ fn check_duplicates(
|
|||
);
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(attr.span());
|
||||
entry.insert(attr_span);
|
||||
}
|
||||
}
|
||||
}
|
||||
ErrorFollowing | ErrorPreceding => match seen.entry(attr_name) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
let (this, other) = if matches!(duplicates, ErrorPreceding) {
|
||||
let to_remove = entry.insert(attr.span());
|
||||
(to_remove, attr.span())
|
||||
let to_remove = entry.insert(attr_span);
|
||||
(to_remove, attr_span)
|
||||
} else {
|
||||
(attr.span(), *entry.get())
|
||||
(attr_span, *entry.get())
|
||||
};
|
||||
tcx.dcx().emit_err(errors::UnusedMultiple { this, other, name: attr_name });
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(attr.span());
|
||||
entry.insert(attr_span);
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,16 @@
|
|||
use rustc_ast::attr;
|
||||
use rustc_ast::entry::EntryPointType;
|
||||
use rustc_errors::codes::*;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::{CRATE_HIR_ID, ItemId, Node};
|
||||
use rustc_hir::{CRATE_HIR_ID, ItemId, Node, find_attr};
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::RemapFileNameExt;
|
||||
use rustc_session::config::{CrateType, EntryFnType, RemapPathScopeComponents, sigpipe};
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
use rustc_span::{Span, sym};
|
||||
|
||||
use crate::errors::{AttrOnlyInFunctions, ExternMain, MultipleRustcMain, NoMainErr};
|
||||
use crate::errors::{ExternMain, MultipleRustcMain, NoMainErr};
|
||||
|
||||
struct EntryContext<'tcx> {
|
||||
tcx: TyCtxt<'tcx>,
|
||||
|
|
@ -44,26 +44,12 @@ fn entry_fn(tcx: TyCtxt<'_>, (): ()) -> Option<(DefId, EntryFnType)> {
|
|||
configure_main(tcx, &ctxt)
|
||||
}
|
||||
|
||||
fn attr_span_by_symbol(ctxt: &EntryContext<'_>, id: ItemId, sym: Symbol) -> Option<Span> {
|
||||
let attrs = ctxt.tcx.hir_attrs(id.hir_id());
|
||||
attr::find_by_name(attrs, sym).map(|attr| attr.span())
|
||||
}
|
||||
|
||||
fn check_and_search_item(id: ItemId, ctxt: &mut EntryContext<'_>) {
|
||||
if !matches!(ctxt.tcx.def_kind(id.owner_id), DefKind::Fn) {
|
||||
for attr in [sym::rustc_main] {
|
||||
if let Some(span) = attr_span_by_symbol(ctxt, id, attr) {
|
||||
ctxt.tcx.dcx().emit_err(AttrOnlyInFunctions { span, attr });
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let at_root = ctxt.tcx.opt_local_parent(id.owner_id.def_id) == Some(CRATE_DEF_ID);
|
||||
|
||||
let attrs = ctxt.tcx.hir_attrs(id.hir_id());
|
||||
let entry_point_type = rustc_ast::entry::entry_point_type(
|
||||
attrs,
|
||||
find_attr!(attrs, AttributeKind::RustcMain),
|
||||
at_root,
|
||||
ctxt.tcx.opt_item_name(id.owner_id.to_def_id()),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -843,14 +843,6 @@ pub(crate) struct FeaturePreviouslyDeclared<'a> {
|
|||
pub prev_declared: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_attr_only_in_functions)]
|
||||
pub(crate) struct AttrOnlyInFunctions {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub attr: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_multiple_rustc_main, code = E0137)]
|
||||
pub(crate) struct MultipleRustcMain {
|
||||
|
|
|
|||
|
|
@ -2332,30 +2332,44 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
|
|||
fn field_idents(&self, def_id: DefId) -> Option<Vec<Ident>> {
|
||||
match def_id.as_local() {
|
||||
Some(def_id) => self.field_names.get(&def_id).cloned(),
|
||||
None => Some(
|
||||
self.tcx
|
||||
.associated_item_def_ids(def_id)
|
||||
.iter()
|
||||
.map(|&def_id| {
|
||||
Ident::new(self.tcx.item_name(def_id), self.tcx.def_span(def_id))
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
None if matches!(
|
||||
self.tcx.def_kind(def_id),
|
||||
DefKind::Struct | DefKind::Union | DefKind::Variant
|
||||
) =>
|
||||
{
|
||||
Some(
|
||||
self.tcx
|
||||
.associated_item_def_ids(def_id)
|
||||
.iter()
|
||||
.map(|&def_id| {
|
||||
Ident::new(self.tcx.item_name(def_id), self.tcx.def_span(def_id))
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn field_defaults(&self, def_id: DefId) -> Option<Vec<Symbol>> {
|
||||
match def_id.as_local() {
|
||||
Some(def_id) => self.field_defaults.get(&def_id).cloned(),
|
||||
None => Some(
|
||||
self.tcx
|
||||
.associated_item_def_ids(def_id)
|
||||
.iter()
|
||||
.filter_map(|&def_id| {
|
||||
self.tcx.default_field(def_id).map(|_| self.tcx.item_name(def_id))
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
None if matches!(
|
||||
self.tcx.def_kind(def_id),
|
||||
DefKind::Struct | DefKind::Union | DefKind::Variant
|
||||
) =>
|
||||
{
|
||||
Some(
|
||||
self.tcx
|
||||
.associated_item_def_ids(def_id)
|
||||
.iter()
|
||||
.filter_map(|&def_id| {
|
||||
self.tcx.default_field(def_id).map(|_| self.tcx.item_name(def_id))
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,3 +29,9 @@ pub(crate) fn compute_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
|
|||
classify_arg(arg);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn compute_rust_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
|
||||
if !fn_abi.ret.is_ignore() {
|
||||
classify_ret(&mut fn_abi.ret);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -715,6 +715,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
|
|||
"riscv32" | "riscv64" => riscv::compute_rust_abi_info(cx, self),
|
||||
"loongarch32" | "loongarch64" => loongarch::compute_rust_abi_info(cx, self),
|
||||
"aarch64" => aarch64::compute_rust_abi_info(cx, self),
|
||||
"bpf" => bpf::compute_rust_abi_info(self),
|
||||
_ => {}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -139,9 +139,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.175"
|
||||
version = "0.2.177"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -361,7 +361,7 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
|
|||
unsafe extern "Rust" {
|
||||
// This is the magic symbol to call the global alloc error handler. rustc generates
|
||||
// it to call `__rg_oom` if there is a `#[alloc_error_handler]`, or to call the
|
||||
// default implementations below (`__rdl_oom`) otherwise.
|
||||
// default implementations below (`__rdl_alloc_error_handler`) otherwise.
|
||||
#[rustc_std_internal_symbol]
|
||||
fn __rust_alloc_error_handler(size: usize, align: usize) -> !;
|
||||
}
|
||||
|
|
@ -425,7 +425,7 @@ pub mod __alloc_error_handler {
|
|||
// called via generated `__rust_alloc_error_handler` if there is no
|
||||
// `#[alloc_error_handler]`.
|
||||
#[rustc_std_internal_symbol]
|
||||
pub unsafe fn __rdl_oom(size: usize, _align: usize) -> ! {
|
||||
pub unsafe fn __rdl_alloc_error_handler(size: usize, _align: usize) -> ! {
|
||||
unsafe extern "Rust" {
|
||||
// This symbol is emitted by rustc next to __rust_alloc_error_handler.
|
||||
// Its value depends on the -Zoom={panic,abort} compiler option.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use crate::marker::Destruct;
|
||||
use crate::ops::{Deref, DerefMut, DerefPure};
|
||||
use crate::ptr;
|
||||
|
||||
|
|
@ -249,7 +250,11 @@ impl<T: ?Sized> ManuallyDrop<T> {
|
|||
/// [pinned]: crate::pin
|
||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||
#[inline]
|
||||
pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
|
||||
#[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")]
|
||||
pub const unsafe fn drop(slot: &mut ManuallyDrop<T>)
|
||||
where
|
||||
T: [const] Destruct,
|
||||
{
|
||||
// SAFETY: we are dropping the value pointed to by a mutable reference
|
||||
// which is guaranteed to be valid for writes.
|
||||
// It is up to the caller to make sure that `slot` isn't dropped again.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use crate::any::type_name;
|
||||
use crate::marker::Destruct;
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::{fmt, intrinsics, ptr, slice};
|
||||
|
||||
|
|
@ -714,7 +715,11 @@ impl<T> MaybeUninit<T> {
|
|||
///
|
||||
/// [`assume_init`]: MaybeUninit::assume_init
|
||||
#[stable(feature = "maybe_uninit_extra", since = "1.60.0")]
|
||||
pub unsafe fn assume_init_drop(&mut self) {
|
||||
#[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")]
|
||||
pub const unsafe fn assume_init_drop(&mut self)
|
||||
where
|
||||
T: [const] Destruct,
|
||||
{
|
||||
// SAFETY: the caller must guarantee that `self` is initialized and
|
||||
// satisfies all invariants of `T`.
|
||||
// Dropping the value in place is safe if that is the case.
|
||||
|
|
@ -1390,7 +1395,11 @@ impl<T> [MaybeUninit<T>] {
|
|||
/// behaviour.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn assume_init_drop(&mut self) {
|
||||
#[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")]
|
||||
pub const unsafe fn assume_init_drop(&mut self)
|
||||
where
|
||||
T: [const] Destruct,
|
||||
{
|
||||
if !self.is_empty() {
|
||||
// SAFETY: the caller must guarantee that every element of `self`
|
||||
// is initialized and satisfies all invariants of `T`.
|
||||
|
|
|
|||
|
|
@ -38,9 +38,8 @@ macro_rules! impl_full_ops {
|
|||
fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) {
|
||||
// This cannot overflow;
|
||||
// the output is between `0` and `2^nbits * (2^nbits - 1)`.
|
||||
let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) +
|
||||
(carry as $bigty);
|
||||
((v >> <$ty>::BITS) as $ty, v as $ty)
|
||||
let (lo, hi) = self.carrying_mul_add(other, other2, carry);
|
||||
(hi, lo)
|
||||
}
|
||||
|
||||
fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
|
||||
|
|
|
|||
|
|
@ -403,7 +403,7 @@
|
|||
|
||||
use crate::cmp::Ordering;
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::marker::{FnPtr, PointeeSized};
|
||||
use crate::marker::{Destruct, FnPtr, PointeeSized};
|
||||
use crate::mem::{self, MaybeUninit, SizedTypeProperties};
|
||||
use crate::num::NonZero;
|
||||
use crate::{fmt, hash, intrinsics, ub_checks};
|
||||
|
|
@ -801,7 +801,11 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
|
|||
#[lang = "drop_in_place"]
|
||||
#[allow(unconditional_recursion)]
|
||||
#[rustc_diagnostic_item = "ptr_drop_in_place"]
|
||||
pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||
#[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")]
|
||||
pub const unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T)
|
||||
where
|
||||
T: [const] Destruct,
|
||||
{
|
||||
// Code here does not matter - this is replaced by the
|
||||
// real drop glue by the compiler.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use super::*;
|
||||
use crate::cmp::Ordering::{Equal, Greater, Less};
|
||||
use crate::intrinsics::const_eval_select;
|
||||
use crate::marker::PointeeSized;
|
||||
use crate::marker::{Destruct, PointeeSized};
|
||||
use crate::mem::{self, SizedTypeProperties};
|
||||
use crate::slice::{self, SliceIndex};
|
||||
|
||||
|
|
@ -1390,8 +1390,12 @@ impl<T: PointeeSized> *mut T {
|
|||
///
|
||||
/// [`ptr::drop_in_place`]: crate::ptr::drop_in_place()
|
||||
#[stable(feature = "pointer_methods", since = "1.26.0")]
|
||||
#[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn drop_in_place(self) {
|
||||
pub const unsafe fn drop_in_place(self)
|
||||
where
|
||||
T: [const] Destruct,
|
||||
{
|
||||
// SAFETY: the caller must uphold the safety contract for `drop_in_place`.
|
||||
unsafe { drop_in_place(self) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
use crate::cmp::Ordering;
|
||||
use crate::marker::{PointeeSized, Unsize};
|
||||
use crate::marker::{Destruct, PointeeSized, Unsize};
|
||||
use crate::mem::{MaybeUninit, SizedTypeProperties};
|
||||
use crate::num::NonZero;
|
||||
use crate::ops::{CoerceUnsized, DispatchFromDyn};
|
||||
|
|
@ -1118,7 +1118,11 @@ impl<T: PointeeSized> NonNull<T> {
|
|||
/// [`ptr::drop_in_place`]: crate::ptr::drop_in_place()
|
||||
#[inline(always)]
|
||||
#[stable(feature = "non_null_convenience", since = "1.80.0")]
|
||||
pub unsafe fn drop_in_place(self) {
|
||||
#[rustc_const_unstable(feature = "const_drop_in_place", issue = "109342")]
|
||||
pub const unsafe fn drop_in_place(self)
|
||||
where
|
||||
T: [const] Destruct,
|
||||
{
|
||||
// SAFETY: the caller must uphold the safety contract for `drop_in_place`.
|
||||
unsafe { ptr::drop_in_place(self.as_ptr()) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#![feature(const_cmp)]
|
||||
#![feature(const_convert)]
|
||||
#![feature(const_destruct)]
|
||||
#![feature(const_drop_in_place)]
|
||||
#![feature(const_eval_select)]
|
||||
#![feature(const_mul_add)]
|
||||
#![feature(const_ops)]
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use core::cell::RefCell;
|
||||
use core::marker::Freeze;
|
||||
use core::mem::MaybeUninit;
|
||||
use core::mem::{ManuallyDrop, MaybeUninit};
|
||||
use core::num::NonZero;
|
||||
use core::ptr;
|
||||
use core::ptr::*;
|
||||
|
|
@ -1045,3 +1045,42 @@ fn test_ptr_default() {
|
|||
let default = PtrMutDefaultTest::default();
|
||||
assert!(default.ptr.is_null());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_const_drop_in_place() {
|
||||
const COUNTER: usize = {
|
||||
let mut counter = 0;
|
||||
let counter_ptr = &raw mut counter;
|
||||
|
||||
// only exists to make `Drop` indirect impl
|
||||
#[allow(dead_code)]
|
||||
struct Test(Dropped);
|
||||
|
||||
struct Dropped(*mut usize);
|
||||
impl const Drop for Dropped {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
*self.0 += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut one = ManuallyDrop::new(Test(Dropped(counter_ptr)));
|
||||
let mut two = ManuallyDrop::new(Test(Dropped(counter_ptr)));
|
||||
let mut three = ManuallyDrop::new(Test(Dropped(counter_ptr)));
|
||||
assert!(counter == 0);
|
||||
unsafe {
|
||||
ManuallyDrop::drop(&mut one);
|
||||
}
|
||||
assert!(counter == 1);
|
||||
unsafe {
|
||||
ManuallyDrop::drop(&mut two);
|
||||
}
|
||||
assert!(counter == 2);
|
||||
unsafe {
|
||||
ManuallyDrop::drop(&mut three);
|
||||
}
|
||||
counter
|
||||
};
|
||||
assert_eq!(COUNTER, 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ miniz_oxide = { version = "0.8.0", optional = true, default-features = false }
|
|||
addr2line = { version = "0.25.0", optional = true, default-features = false }
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
libc = { version = "0.2.172", default-features = false, features = [
|
||||
libc = { version = "0.2.177", default-features = false, features = [
|
||||
'rustc-dep-of-std',
|
||||
], public = true }
|
||||
|
||||
|
|
|
|||
|
|
@ -358,9 +358,10 @@ fn default_alloc_error_hook(layout: Layout) {
|
|||
// This is the default path taken on OOM, and the only path taken on stable with std.
|
||||
// Crucially, it does *not* call any user-defined code, and therefore users do not have to
|
||||
// worry about allocation failure causing reentrancy issues. That makes it different from
|
||||
// the default `__rdl_oom` defined in alloc (i.e., the default alloc error handler that is
|
||||
// called when there is no `#[alloc_error_handler]`), which triggers a regular panic and
|
||||
// thus can invoke a user-defined panic hook, executing arbitrary user-defined code.
|
||||
// the default `__rdl_alloc_error_handler` defined in alloc (i.e., the default alloc error
|
||||
// handler that is called when there is no `#[alloc_error_handler]`), which triggers a
|
||||
// regular panic and thus can invoke a user-defined panic hook, executing arbitrary
|
||||
// user-defined code.
|
||||
rtprintpanic!("memory allocation of {} bytes failed\n", layout.size());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
//! So for example there is a [page for the primitive type
|
||||
//! `char`](primitive::char) that lists all the methods that can be called on
|
||||
//! characters (very useful), and there is a [page for the module
|
||||
//! `std::char`] that documents iterator and error types created by these methods
|
||||
//! `std::char`](crate::char) that documents iterator and error types created by these methods
|
||||
//! (rarely useful).
|
||||
//!
|
||||
//! Note the documentation for the primitives [`str`] and [`[T]`][prim@slice] (also
|
||||
|
|
@ -180,9 +180,6 @@
|
|||
//!
|
||||
//!
|
||||
//! [I/O]: io
|
||||
//! [`MIN`]: i32::MIN
|
||||
//! [`MAX`]: i32::MAX
|
||||
//! [page for the module `std::i32`]: crate::i32
|
||||
//! [TCP]: net::TcpStream
|
||||
//! [The Rust Prelude]: prelude
|
||||
//! [UDP]: net::UdpSocket
|
||||
|
|
|
|||
|
|
@ -1,11 +1,6 @@
|
|||
use super::Mutex;
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::pin::Pin;
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
use crate::sys::pal::time::TIMESPEC_MAX;
|
||||
#[cfg(target_os = "nto")]
|
||||
use crate::sys::pal::time::TIMESPEC_MAX_CAPPED;
|
||||
use crate::sys::pal::time::Timespec;
|
||||
use crate::time::Duration;
|
||||
|
||||
pub struct Condvar {
|
||||
|
|
@ -47,27 +42,29 @@ impl Condvar {
|
|||
let r = unsafe { libc::pthread_cond_wait(self.raw(), mutex.raw()) };
|
||||
debug_assert_eq!(r, 0);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_vendor = "apple"))]
|
||||
impl Condvar {
|
||||
/// # Safety
|
||||
/// * `init` must have been called on this instance.
|
||||
/// * `mutex` must be locked by the current thread.
|
||||
/// * This condition variable may only be used with the same mutex.
|
||||
pub unsafe fn wait_timeout(&self, mutex: Pin<&Mutex>, dur: Duration) -> bool {
|
||||
#[cfg(not(target_os = "nto"))]
|
||||
use crate::sys::pal::time::TIMESPEC_MAX;
|
||||
#[cfg(target_os = "nto")]
|
||||
use crate::sys::pal::time::TIMESPEC_MAX_CAPPED;
|
||||
use crate::sys::pal::time::Timespec;
|
||||
|
||||
let mutex = mutex.raw();
|
||||
|
||||
// OSX implementation of `pthread_cond_timedwait` is buggy
|
||||
// with super long durations. When duration is greater than
|
||||
// 0x100_0000_0000_0000 seconds, `pthread_cond_timedwait`
|
||||
// in macOS Sierra returns error 316.
|
||||
//
|
||||
// This program demonstrates the issue:
|
||||
// https://gist.github.com/stepancheg/198db4623a20aad2ad7cddb8fda4a63c
|
||||
//
|
||||
// To work around this issue, the timeout is clamped to 1000 years.
|
||||
//
|
||||
// Cygwin implementation is based on NT API and a super large timeout
|
||||
// makes the syscall block forever.
|
||||
#[cfg(any(target_vendor = "apple", target_os = "cygwin"))]
|
||||
// Cygwin's implementation is based on the NT API, which measures time
|
||||
// in units of 100 ns. Unfortunately, Cygwin does not properly guard
|
||||
// against overflow when converting the time, hence we clamp the interval
|
||||
// to 1000 years, which will only become a problem in around 27000 years,
|
||||
// when the next rollover is less than 1000 years away...
|
||||
#[cfg(target_os = "cygwin")]
|
||||
let dur = Duration::min(dur, Duration::from_secs(1000 * 365 * 86400));
|
||||
|
||||
let timeout = Timespec::now(Self::CLOCK).checked_add_duration(&dur);
|
||||
|
|
@ -84,6 +81,57 @@ impl Condvar {
|
|||
}
|
||||
}
|
||||
|
||||
// Apple platforms (since macOS version 10.4 and iOS version 2.0) have
|
||||
// `pthread_cond_timedwait_relative_np`, a non-standard extension that
|
||||
// measures timeouts based on the monotonic clock and is thus resilient
|
||||
// against wall-clock changes.
|
||||
#[cfg(target_vendor = "apple")]
|
||||
impl Condvar {
|
||||
/// # Safety
|
||||
/// * `init` must have been called on this instance.
|
||||
/// * `mutex` must be locked by the current thread.
|
||||
/// * This condition variable may only be used with the same mutex.
|
||||
pub unsafe fn wait_timeout(&self, mutex: Pin<&Mutex>, dur: Duration) -> bool {
|
||||
let mutex = mutex.raw();
|
||||
|
||||
// The macOS implementation of `pthread_cond_timedwait` internally
|
||||
// converts the timeout passed to `pthread_cond_timedwait_relative_np`
|
||||
// to nanoseconds. Unfortunately, the "psynch" variant of condvars does
|
||||
// not guard against overflow during the conversion[^1], which means
|
||||
// that `pthread_cond_timedwait_relative_np` will return `ETIMEDOUT`
|
||||
// much earlier than expected if the relative timeout is longer than
|
||||
// `u64::MAX` nanoseconds.
|
||||
//
|
||||
// This can be observed even on newer platforms (by setting the environment
|
||||
// variable PTHREAD_MUTEX_USE_ULOCK to a value other than "1") by calling e.g.
|
||||
// ```
|
||||
// condvar.wait_timeout(..., Duration::from_secs(u64::MAX.div_ceil(1_000_000_000));
|
||||
// ```
|
||||
// (see #37440, especially
|
||||
// https://github.com/rust-lang/rust/issues/37440#issuecomment-3285958326).
|
||||
//
|
||||
// To work around this issue, always clamp the timeout to u64::MAX nanoseconds,
|
||||
// even if the "ulock" variant is used (which does guard against overflow).
|
||||
//
|
||||
// [^1]: https://github.com/apple-oss-distributions/libpthread/blob/1ebf56b3a702df53213c2996e5e128a535d2577e/kern/kern_synch.c#L1269
|
||||
const MAX_DURATION: Duration = Duration::from_nanos(u64::MAX);
|
||||
|
||||
let (dur, clamped) = if dur <= MAX_DURATION { (dur, false) } else { (MAX_DURATION, true) };
|
||||
|
||||
let timeout = libc::timespec {
|
||||
// This cannot overflow because of the clamping above.
|
||||
tv_sec: dur.as_secs() as i64,
|
||||
tv_nsec: dur.subsec_nanos() as i64,
|
||||
};
|
||||
|
||||
let r = unsafe { libc::pthread_cond_timedwait_relative_np(self.raw(), mutex, &timeout) };
|
||||
assert!(r == libc::ETIMEDOUT || r == 0);
|
||||
// Report clamping as a spurious wakeup. Who knows, maybe some
|
||||
// interstellar space probe will rely on this ;-).
|
||||
r == 0 || clamped
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_vendor = "apple",
|
||||
|
|
@ -125,10 +173,23 @@ impl Condvar {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(target_vendor = "apple")]
|
||||
impl Condvar {
|
||||
// `pthread_cond_timedwait_relative_np` measures the timeout
|
||||
// based on the monotonic clock.
|
||||
pub const PRECISE_TIMEOUT: bool = true;
|
||||
|
||||
/// # Safety
|
||||
/// May only be called once per instance of `Self`.
|
||||
pub unsafe fn init(self: Pin<&mut Self>) {
|
||||
// `PTHREAD_COND_INITIALIZER` is fully supported and we don't need to
|
||||
// change clocks, so there's nothing to do here.
|
||||
}
|
||||
}
|
||||
|
||||
// `pthread_condattr_setclock` is unfortunately not supported on these platforms.
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_vendor = "apple",
|
||||
target_os = "espidf",
|
||||
target_os = "horizon",
|
||||
target_os = "l4re",
|
||||
|
|
|
|||
|
|
@ -267,3 +267,35 @@ nonpoison_and_poison_unwrap_test!(
|
|||
}
|
||||
}
|
||||
);
|
||||
|
||||
// Some platforms internally cast the timeout duration into nanoseconds.
|
||||
// If they fail to consider overflow during the conversion (I'm looking
|
||||
// at you, macOS), `wait_timeout` will return immediately and indicate a
|
||||
// timeout for durations that are slightly longer than u64::MAX nanoseconds.
|
||||
// `std` should guard against this by clamping the timeout.
|
||||
// See #37440 for context.
|
||||
nonpoison_and_poison_unwrap_test!(
|
||||
name: timeout_nanoseconds,
|
||||
test_body: {
|
||||
use locks::Mutex;
|
||||
use locks::Condvar;
|
||||
|
||||
let sent = Mutex::new(false);
|
||||
let cond = Condvar::new();
|
||||
|
||||
thread::scope(|s| {
|
||||
s.spawn(|| {
|
||||
thread::sleep(Duration::from_secs(2));
|
||||
maybe_unwrap(sent.set(true));
|
||||
cond.notify_all();
|
||||
});
|
||||
|
||||
let guard = maybe_unwrap(sent.lock());
|
||||
// If there is internal overflow, this call will return almost
|
||||
// immediately, before the other thread has reached the `notify_all`
|
||||
let (guard, res) = maybe_unwrap(cond.wait_timeout(guard, Duration::from_secs(u64::MAX.div_ceil(1_000_000_000))));
|
||||
assert!(!res.timed_out());
|
||||
assert!(*guard);
|
||||
})
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ use std::io::Write;
|
|||
use std::path::Path;
|
||||
|
||||
use rustc_abi::{Align, AlignFromBytesError, CanonAbi, Size};
|
||||
use rustc_ast::expand::allocator::alloc_error_handler_name;
|
||||
use rustc_ast::expand::allocator::AllocatorKind;
|
||||
use rustc_hir::attrs::Linkage;
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::CrateNum;
|
||||
|
|
@ -52,6 +52,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Some shims forward to other MIR bodies.
|
||||
match link_name.as_str() {
|
||||
// This allocator function has forwarding shims synthesized during normal codegen
|
||||
// (see `allocator_shim_contents`); this is where we emulate that behavior.
|
||||
// FIXME should use global_fn_name, but mangle_internal_symbol requires a static str.
|
||||
name if name == this.mangle_internal_symbol("__rust_alloc_error_handler") => {
|
||||
// Forward to the right symbol that implements this function.
|
||||
let Some(handler_kind) = this.tcx.alloc_error_handler_kind(()) else {
|
||||
|
|
@ -60,12 +63,16 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
"`__rust_alloc_error_handler` cannot be called when no alloc error handler is set"
|
||||
);
|
||||
};
|
||||
let name = Symbol::intern(
|
||||
this.mangle_internal_symbol(alloc_error_handler_name(handler_kind)),
|
||||
);
|
||||
let handler =
|
||||
this.lookup_exported_symbol(name)?.expect("missing alloc error handler symbol");
|
||||
return interp_ok(Some(handler));
|
||||
if handler_kind == AllocatorKind::Default {
|
||||
let name =
|
||||
Symbol::intern(this.mangle_internal_symbol("__rdl_alloc_error_handler"));
|
||||
let handler = this
|
||||
.lookup_exported_symbol(name)?
|
||||
.expect("missing alloc error handler symbol");
|
||||
return interp_ok(Some(handler));
|
||||
}
|
||||
// Fall through to the `lookup_exported_symbol` below which should find
|
||||
// a `__rust_alloc_error_handler`.
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -815,7 +815,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
"pthread_cond_timedwait" => {
|
||||
let [cond, mutex, abstime] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
|
||||
this.pthread_cond_timedwait(cond, mutex, abstime, dest)?;
|
||||
this.pthread_cond_timedwait(cond, mutex, abstime, dest, /* macos_relative_np */ false)?;
|
||||
}
|
||||
"pthread_cond_destroy" => {
|
||||
let [cond] = this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
|
||||
|
|
|
|||
|
|
@ -307,6 +307,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
this.os_unfair_lock_assert_not_owner(lock_op)?;
|
||||
}
|
||||
|
||||
"pthread_cond_timedwait_relative_np" => {
|
||||
let [cond, mutex, reltime] =
|
||||
this.check_shim_sig_lenient(abi, CanonAbi::C, link_name, args)?;
|
||||
this.pthread_cond_timedwait(cond, mutex, reltime, dest, /* macos_relative_np */ true)?;
|
||||
}
|
||||
|
||||
_ => return interp_ok(EmulateItemResult::NotSupported),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -834,8 +834,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
&mut self,
|
||||
cond_op: &OpTy<'tcx>,
|
||||
mutex_op: &OpTy<'tcx>,
|
||||
abstime_op: &OpTy<'tcx>,
|
||||
timeout_op: &OpTy<'tcx>,
|
||||
dest: &MPlaceTy<'tcx>,
|
||||
macos_relative_np: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
let this = self.eval_context_mut();
|
||||
|
||||
|
|
@ -844,7 +845,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
|
||||
// Extract the timeout.
|
||||
let duration = match this
|
||||
.read_timespec(&this.deref_pointer_as(abstime_op, this.libc_ty_layout("timespec"))?)?
|
||||
.read_timespec(&this.deref_pointer_as(timeout_op, this.libc_ty_layout("timespec"))?)?
|
||||
{
|
||||
Some(duration) => duration,
|
||||
None => {
|
||||
|
|
@ -853,14 +854,23 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
|
|||
return interp_ok(());
|
||||
}
|
||||
};
|
||||
if data.clock == TimeoutClock::RealTime {
|
||||
this.check_no_isolation("`pthread_cond_timedwait` with `CLOCK_REALTIME`")?;
|
||||
}
|
||||
|
||||
let (clock, anchor) = if macos_relative_np {
|
||||
// `pthread_cond_timedwait_relative_np` always measures time against the
|
||||
// monotonic clock, regardless of the condvar clock.
|
||||
(TimeoutClock::Monotonic, TimeoutAnchor::Relative)
|
||||
} else {
|
||||
if data.clock == TimeoutClock::RealTime {
|
||||
this.check_no_isolation("`pthread_cond_timedwait` with `CLOCK_REALTIME`")?;
|
||||
}
|
||||
|
||||
(data.clock, TimeoutAnchor::Absolute)
|
||||
};
|
||||
|
||||
this.condvar_wait(
|
||||
data.condvar_ref,
|
||||
mutex_ref,
|
||||
Some((data.clock, TimeoutAnchor::Absolute, duration)),
|
||||
Some((clock, anchor, duration)),
|
||||
Scalar::from_i32(0),
|
||||
this.eval_libc("ETIMEDOUT"), // retval_timeout
|
||||
dest.clone(),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ LL | crate::process::abort()
|
|||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `std::alloc::rust_oom` at RUSTLIB/std/src/alloc.rs:LL:CC
|
||||
= note: inside `std::alloc::_::__rg_oom` at RUSTLIB/std/src/alloc.rs:LL:CC
|
||||
= note: inside `std::alloc::_::__rust_alloc_error_handler` at RUSTLIB/std/src/alloc.rs:LL:CC
|
||||
= note: inside `std::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||
= note: inside `std::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||
note: inside `main`
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ LL | core::intrinsics::abort();
|
|||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `alloc_error_handler` at tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC
|
||||
note: inside `_::__rg_oom`
|
||||
note: inside `_::__rust_alloc_error_handler`
|
||||
--> tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC
|
||||
|
|
||||
LL | #[alloc_error_handler]
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ LL | core::intrinsics::abort();
|
|||
|
|
||||
= note: BACKTRACE:
|
||||
= note: inside `panic_handler` at tests/fail/alloc/alloc_error_handler_no_std.rs:LL:CC
|
||||
= note: inside `alloc::alloc::__alloc_error_handler::__rdl_oom` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||
= note: inside `alloc::alloc::__alloc_error_handler::__rdl_alloc_error_handler` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||
= note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||
= note: inside `alloc::alloc::handle_alloc_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
|
||||
note: inside `miri_start`
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
error: Undefined Behavior: trying to retag from <TAG> for Unique permission at ALLOC[0x0], but that tag only grants SharedReadOnly permission for this location
|
||||
--> RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
|
|
||||
LL | pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this error occurs as part of retag at ALLOC[0x0..0x1]
|
||||
LL | / pub const unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T)
|
||||
LL | | where
|
||||
LL | | T: [const] Destruct,
|
||||
| |________________________^ this error occurs as part of retag at ALLOC[0x0..0x1]
|
||||
|
|
||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
|
||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required ALIGN byte alignment but found ALIGN)
|
||||
--> RUSTLIB/core/src/ptr/mod.rs:LL:CC
|
||||
|
|
||||
LL | pub unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
||||
LL | / pub const unsafe fn drop_in_place<T: PointeeSized>(to_drop: *mut T)
|
||||
LL | | where
|
||||
LL | | T: [const] Destruct,
|
||||
| |________________________^ Undefined Behavior occurred here
|
||||
|
|
||||
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
|
||||
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
//@only-target: apple # `pthread_cond_timedwait_relative_np` is a non-standard extension
|
||||
|
||||
use std::time::Instant;
|
||||
|
||||
// FIXME: remove once this is in libc.
|
||||
mod libc {
|
||||
pub use ::libc::*;
|
||||
unsafe extern "C" {
|
||||
pub unsafe fn pthread_cond_timedwait_relative_np(
|
||||
cond: *mut libc::pthread_cond_t,
|
||||
lock: *mut libc::pthread_mutex_t,
|
||||
timeout: *const libc::timespec,
|
||||
) -> libc::c_int;
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
let mut mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
|
||||
let mut cond: libc::pthread_cond_t = libc::PTHREAD_COND_INITIALIZER;
|
||||
|
||||
// Wait for 100 ms.
|
||||
let timeout = libc::timespec { tv_sec: 0, tv_nsec: 100_000_000 };
|
||||
|
||||
assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
|
||||
|
||||
let current_time = Instant::now();
|
||||
assert_eq!(
|
||||
libc::pthread_cond_timedwait_relative_np(&mut cond, &mut mutex, &timeout),
|
||||
libc::ETIMEDOUT
|
||||
);
|
||||
let elapsed_time = current_time.elapsed().as_millis();
|
||||
// This is actually deterministic (since isolation remains enabled),
|
||||
// but can change slightly with Rust updates.
|
||||
assert!(90 <= elapsed_time && elapsed_time <= 110);
|
||||
|
||||
assert_eq!(libc::pthread_mutex_unlock(&mut mutex), 0);
|
||||
assert_eq!(libc::pthread_mutex_destroy(&mut mutex), 0);
|
||||
assert_eq!(libc::pthread_cond_destroy(&mut cond), 0);
|
||||
}
|
||||
}
|
||||
43
tests/codegen-llvm/bpf-abi-indirect-return.rs
Normal file
43
tests/codegen-llvm/bpf-abi-indirect-return.rs
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Checks that results larger than one register are returned indirectly
|
||||
//@ only-bpf
|
||||
//@ needs-llvm-components: bpf
|
||||
//@ compile-flags: --target bpfel-unknown-none
|
||||
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
#[no_mangle]
|
||||
fn outer(a: u64) -> u64 {
|
||||
let v = match inner_res(a) {
|
||||
Ok(v) => v,
|
||||
Err(()) => 0,
|
||||
};
|
||||
|
||||
inner_big(v).a[0] as u64
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @_ZN{{.*}}inner_res{{.*}}E(
|
||||
// CHECK-SAME: ptr{{[^,]*}},
|
||||
// CHECK-SAME: i64{{[^)]*}}
|
||||
#[inline(never)]
|
||||
fn inner_res(a: u64) -> Result<u64, ()> {
|
||||
if a == 0 { Err(()) } else { Ok(a + 1) }
|
||||
}
|
||||
|
||||
struct Big {
|
||||
a: [u16; 32],
|
||||
b: u64,
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @_ZN{{.*}}inner_big{{.*}}E(
|
||||
// CHECK-SAME: ptr{{[^,]*}},
|
||||
// CHECK-SAME: i64{{[^)]*}}
|
||||
#[inline(never)]
|
||||
fn inner_big(a: u64) -> Big {
|
||||
Big { a: [a as u16; 32], b: 42 }
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
|
@ -14,5 +14,5 @@ fn main() {
|
|||
let out = llvm_readobj().input("app.o").arg("--symbols").run();
|
||||
out.assert_stdout_contains("rust_begin_unwind");
|
||||
out.assert_stdout_contains("rust_eh_personality");
|
||||
out.assert_stdout_contains("__rg_oom");
|
||||
out.assert_stdout_contains("__rust_alloc_error_handler");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#![macro_export]
|
||||
//~^ ERROR: `#[macro_export]` attribute cannot be used on crates
|
||||
#![rustc_main]
|
||||
//~^ ERROR: `rustc_main` attribute cannot be used at crate level
|
||||
//~^ ERROR: `#[rustc_main]` attribute cannot be used on crates
|
||||
//~| ERROR: use of an internal attribute [E0658]
|
||||
//~| NOTE: the `#[rustc_main]` attribute is an internal implementation detail that will never be stable
|
||||
//~| NOTE: the `#[rustc_main]` attribute is used internally to specify test entry point function
|
||||
|
|
@ -31,7 +31,6 @@
|
|||
//~^ ERROR attribute cannot be used on
|
||||
mod inline {
|
||||
//~^ NOTE the inner attribute doesn't annotate this module
|
||||
//~| NOTE the inner attribute doesn't annotate this module
|
||||
|
||||
mod inner { #![inline] }
|
||||
//~^ ERROR attribute cannot be used on
|
||||
|
|
|
|||
|
|
@ -16,6 +16,14 @@ LL | #![macro_export]
|
|||
|
|
||||
= help: `#[macro_export]` can only be applied to macro defs
|
||||
|
||||
error: `#[rustc_main]` attribute cannot be used on crates
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1
|
||||
|
|
||||
LL | #![rustc_main]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: `#[rustc_main]` can only be applied to functions
|
||||
|
||||
error: `#[path]` attribute cannot be used on crates
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:19:1
|
||||
|
|
||||
|
|
@ -57,7 +65,7 @@ LL | #[inline]
|
|||
= help: `#[inline]` can only be applied to functions
|
||||
|
||||
error: `#[inline]` attribute cannot be used on modules
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:36:17
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:35:17
|
||||
|
|
||||
LL | mod inner { #![inline] }
|
||||
| ^^^^^^^^^^
|
||||
|
|
@ -65,7 +73,7 @@ LL | mod inner { #![inline] }
|
|||
= help: `#[inline]` can only be applied to functions
|
||||
|
||||
error: `#[inline]` attribute cannot be used on structs
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:45:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:44:5
|
||||
|
|
||||
LL | #[inline] struct S;
|
||||
| ^^^^^^^^^
|
||||
|
|
@ -73,7 +81,7 @@ LL | #[inline] struct S;
|
|||
= help: `#[inline]` can only be applied to functions
|
||||
|
||||
error: `#[inline]` attribute cannot be used on type aliases
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:48:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:47:5
|
||||
|
|
||||
LL | #[inline] type T = S;
|
||||
| ^^^^^^^^^
|
||||
|
|
@ -81,7 +89,7 @@ LL | #[inline] type T = S;
|
|||
= help: `#[inline]` can only be applied to functions
|
||||
|
||||
error: `#[inline]` attribute cannot be used on inherent impl blocks
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:51:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:50:5
|
||||
|
|
||||
LL | #[inline] impl S { }
|
||||
| ^^^^^^^^^
|
||||
|
|
@ -89,7 +97,7 @@ LL | #[inline] impl S { }
|
|||
= help: `#[inline]` can only be applied to functions
|
||||
|
||||
error: `#[export_name]` attribute cannot be used on modules
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:81:1
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:80:1
|
||||
|
|
||||
LL | #[export_name = "2200"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -97,7 +105,7 @@ LL | #[export_name = "2200"]
|
|||
= help: `#[export_name]` can be applied to functions and statics
|
||||
|
||||
error: `#[export_name]` attribute cannot be used on modules
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:84:17
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:83:17
|
||||
|
|
||||
LL | mod inner { #![export_name="2200"] }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -105,7 +113,7 @@ LL | mod inner { #![export_name="2200"] }
|
|||
= help: `#[export_name]` can be applied to functions and statics
|
||||
|
||||
error: `#[export_name]` attribute cannot be used on structs
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:89:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:88:5
|
||||
|
|
||||
LL | #[export_name = "2200"] struct S;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -113,7 +121,7 @@ LL | #[export_name = "2200"] struct S;
|
|||
= help: `#[export_name]` can be applied to functions and statics
|
||||
|
||||
error: `#[export_name]` attribute cannot be used on type aliases
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:92:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:91:5
|
||||
|
|
||||
LL | #[export_name = "2200"] type T = S;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -121,7 +129,7 @@ LL | #[export_name = "2200"] type T = S;
|
|||
= help: `#[export_name]` can be applied to functions and statics
|
||||
|
||||
error: `#[export_name]` attribute cannot be used on inherent impl blocks
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:95:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:94:5
|
||||
|
|
||||
LL | #[export_name = "2200"] impl S { }
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -129,7 +137,7 @@ LL | #[export_name = "2200"] impl S { }
|
|||
= help: `#[export_name]` can be applied to functions and statics
|
||||
|
||||
error: `#[export_name]` attribute cannot be used on required trait methods
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:99:9
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:98:9
|
||||
|
|
||||
LL | #[export_name = "2200"] fn foo();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -137,7 +145,7 @@ LL | #[export_name = "2200"] fn foo();
|
|||
= help: `#[export_name]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks
|
||||
|
||||
error: attribute should be applied to an `extern crate` item
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:55:1
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:54:1
|
||||
|
|
||||
LL | #[no_link]
|
||||
| ^^^^^^^^^^
|
||||
|
|
@ -151,7 +159,7 @@ LL | | }
|
|||
| |_- not an `extern crate` item
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:106:8
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:105:8
|
||||
|
|
||||
LL | #[repr(C)]
|
||||
| ^
|
||||
|
|
@ -164,7 +172,7 @@ LL | | }
|
|||
| |_- not a struct, enum, or union
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:130:8
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:129:8
|
||||
|
|
||||
LL | #[repr(Rust)]
|
||||
| ^^^^
|
||||
|
|
@ -182,21 +190,6 @@ error: attribute should be applied to an `extern crate` item
|
|||
LL | #![no_link]
|
||||
| ^^^^^^^^^^^ not an `extern crate` item
|
||||
|
||||
error: `rustc_main` attribute cannot be used at crate level
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:12:1
|
||||
|
|
||||
LL | #![rustc_main]
|
||||
| ^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | mod inline {
|
||||
| ------ the inner attribute doesn't annotate this module
|
||||
|
|
||||
help: perhaps you meant to use an outer attribute
|
||||
|
|
||||
LL - #![rustc_main]
|
||||
LL + #[rustc_main]
|
||||
|
|
||||
|
||||
error: `repr` attribute cannot be used at crate level
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:17:1
|
||||
|
|
||||
|
|
@ -213,85 +206,85 @@ LL + #[repr()]
|
|||
|
|
||||
|
||||
error: attribute should be applied to an `extern crate` item
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:60:17
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:59:17
|
||||
|
|
||||
LL | mod inner { #![no_link] }
|
||||
| ------------^^^^^^^^^^^-- not an `extern crate` item
|
||||
|
||||
error: attribute should be applied to an `extern crate` item
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:64:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:63:5
|
||||
|
|
||||
LL | #[no_link] fn f() { }
|
||||
| ^^^^^^^^^^ ---------- not an `extern crate` item
|
||||
|
||||
error: attribute should be applied to an `extern crate` item
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:68:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:67:5
|
||||
|
|
||||
LL | #[no_link] struct S;
|
||||
| ^^^^^^^^^^ --------- not an `extern crate` item
|
||||
|
||||
error: attribute should be applied to an `extern crate` item
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:72:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:71:5
|
||||
|
|
||||
LL | #[no_link]type T = S;
|
||||
| ^^^^^^^^^^----------- not an `extern crate` item
|
||||
|
||||
error: attribute should be applied to an `extern crate` item
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:76:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:75:5
|
||||
|
|
||||
LL | #[no_link] impl S { }
|
||||
| ^^^^^^^^^^ ---------- not an `extern crate` item
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:110:25
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:109:25
|
||||
|
|
||||
LL | mod inner { #![repr(C)] }
|
||||
| --------------------^---- not a struct, enum, or union
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:114:12
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:113:12
|
||||
|
|
||||
LL | #[repr(C)] fn f() { }
|
||||
| ^ ---------- not a struct, enum, or union
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:120:12
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:119:12
|
||||
|
|
||||
LL | #[repr(C)] type T = S;
|
||||
| ^ ----------- not a struct, enum, or union
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:124:12
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:123:12
|
||||
|
|
||||
LL | #[repr(C)] impl S { }
|
||||
| ^ ---------- not a struct, enum, or union
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:134:25
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:133:25
|
||||
|
|
||||
LL | mod inner { #![repr(Rust)] }
|
||||
| --------------------^^^^---- not a struct, enum, or union
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:138:12
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:137:12
|
||||
|
|
||||
LL | #[repr(Rust)] fn f() { }
|
||||
| ^^^^ ---------- not a struct, enum, or union
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:144:12
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:143:12
|
||||
|
|
||||
LL | #[repr(Rust)] type T = S;
|
||||
| ^^^^ ----------- not a struct, enum, or union
|
||||
|
||||
error[E0517]: attribute should be applied to a struct, enum, or union
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:148:12
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:147:12
|
||||
|
|
||||
LL | #[repr(Rust)] impl S { }
|
||||
| ^^^^ ---------- not a struct, enum, or union
|
||||
|
||||
error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:39:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:38:5
|
||||
|
|
||||
LL | #[inline = "2100"] fn f() { }
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
@ -306,7 +299,7 @@ Some errors have detailed explanations: E0517, E0658.
|
|||
For more information about an error, try `rustc --explain E0517`.
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:39:5
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:38:5
|
||||
|
|
||||
LL | #[inline = "2100"] fn f() { }
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
|
|||
|
|
@ -490,16 +490,6 @@ fun:__dfso_*=uninstrumented
|
|||
fun:__dfso_*=discard
|
||||
|
||||
# Rust functions.
|
||||
fun:__rdl_alloc=uninstrumented
|
||||
fun:__rdl_alloc_zeroed=uninstrumented
|
||||
fun:__rdl_dealloc=uninstrumented
|
||||
fun:__rdl_realloc=uninstrumented
|
||||
fun:__rg_oom=uninstrumented
|
||||
fun:__rust_alloc=uninstrumented
|
||||
fun:__rust_alloc_error_handler=uninstrumented
|
||||
fun:__rust_alloc_zeroed=uninstrumented
|
||||
fun:__rust_dealloc=uninstrumented
|
||||
fun:__rust_realloc=uninstrumented
|
||||
fun:_ZN4core*=uninstrumented
|
||||
fun:_ZN3std*=uninstrumented
|
||||
fun:rust_eh_personality=uninstrumented
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
// ICE #147325: When the user mistakenly uses struct syntax to construct an enum,
|
||||
// the field_idents and field_defaults functions will trigger an error
|
||||
|
||||
mod m {
|
||||
struct Priv1;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
Option { field1: m::Priv1 } //~ ERROR expected struct, variant or union type, found enum
|
||||
//~^ ERROR unit struct `Priv1` is private
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
error[E0574]: expected struct, variant or union type, found enum `Option`
|
||||
--> $DIR/struct-fields-ice-147325.rs:9:5
|
||||
|
|
||||
LL | Option { field1: m::Priv1 }
|
||||
| ^^^^^^ not a struct, variant or union type
|
||||
|
||||
error[E0603]: unit struct `Priv1` is private
|
||||
--> $DIR/struct-fields-ice-147325.rs:9:25
|
||||
|
|
||||
LL | Option { field1: m::Priv1 }
|
||||
| ^^^^^ private unit struct
|
||||
|
|
||||
note: the unit struct `Priv1` is defined here
|
||||
--> $DIR/struct-fields-ice-147325.rs:5:5
|
||||
|
|
||||
LL | struct Priv1;
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0574, E0603.
|
||||
For more information about an error, try `rustc --explain E0574`.
|
||||
Loading…
Add table
Add a link
Reference in a new issue