Merge from rustc

This commit is contained in:
Ralf Jung 2025-02-16 08:38:29 +01:00
commit 703154d4f0
130 changed files with 4438 additions and 3395 deletions

View file

@ -6195,16 +6195,11 @@ dependencies = [
[[package]]
name = "windows-bindgen"
version = "0.58.0"
version = "0.59.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "91cd28d93c692351f3a6e5615567c56756e330bee1c99c6bdd57bfc5ab15f589"
checksum = "9b7fb600834d7e868f6e5bb748a86101427330fafbf9485c331b9d5f562d54a5"
dependencies = [
"proc-macro2",
"rayon",
"serde",
"serde_json",
"syn 2.0.96",
"windows-metadata",
]
[[package]]
@ -6285,12 +6280,6 @@ dependencies = [
"syn 2.0.96",
]
[[package]]
name = "windows-metadata"
version = "0.58.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e837f3c3012cfe9e7086302a93f441a7999439be1ad4c530d55d2f6d2921809"
[[package]]
name = "windows-result"
version = "0.1.2"

View file

@ -1,3 +1,130 @@
Version 1.85.0 (2025-02-20)
==========================
<a id="1.85.0-Language"></a>
Language
--------
- [The 2024 Edition is now stable.](https://github.com/rust-lang/rust/pull/133349)
See [the edition guide](https://doc.rust-lang.org/nightly/edition-guide/rust-2024/index.html) for more details.
- [Stabilize async closures](https://github.com/rust-lang/rust/pull/132706)
See [RFC 3668](https://rust-lang.github.io/rfcs/3668-async-closures.html) for more details.
- [Stabilize `#[diagnostic::do_not_recommend]`](https://github.com/rust-lang/rust/pull/132056)
- [Add `unpredictable_function_pointer_comparisons` lint to warn against function pointer comparisons](https://github.com/rust-lang/rust/pull/118833)
- [Lint on combining `#[no_mangle]` and `#[export_name]` attributes.](https://github.com/rust-lang/rust/pull/131558)
<a id="1.85.0-Compiler"></a>
Compiler
--------
- [The unstable flag `-Zpolymorphize` has been removed](https://github.com/rust-lang/rust/pull/133883), see https://github.com/rust-lang/compiler-team/issues/810 for some background.
<a id="1.85.0-Platform-Support"></a>
Platform Support
----------------
- [Promote `powerpc64le-unknown-linux-musl` to tier 2 with host tools](https://github.com/rust-lang/rust/pull/133801)
Refer to Rust's [platform support page][platform-support-doc]
for more information on Rust's tiered platform support.
<a id="1.85.0-Libraries"></a>
Libraries
---------
- [Panics in the standard library now have a leading `library/` in their path](https://github.com/rust-lang/rust/pull/132390)
- [`std::env::home_dir()` on Windows now ignores the non-standard `$HOME` environment variable](https://github.com/rust-lang/rust/pull/132515)
It will be un-deprecated in a subsequent release.
- [Add `AsyncFn*` to the prelude in all editions.](https://github.com/rust-lang/rust/pull/132611)
<a id="1.85.0-Stabilized-APIs"></a>
Stabilized APIs
---------------
- [`BuildHasherDefault::new`](https://doc.rust-lang.org/stable/std/hash/struct.BuildHasherDefault.html#method.new)
- [`ptr::fn_addr_eq`](https://doc.rust-lang.org/std/ptr/fn.fn_addr_eq.html)
- [`io::ErrorKind::QuotaExceeded`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.QuotaExceeded)
- [`io::ErrorKind::CrossesDevices`](https://doc.rust-lang.org/stable/std/io/enum.ErrorKind.html#variant.CrossesDevices)
- [`{float}::midpoint`](https://doc.rust-lang.org/core/primitive.f32.html#method.midpoint)
- [Unsigned `{integer}::midpoint`](https://doc.rust-lang.org/std/primitive.u64.html#method.midpoint)
- [`NonZeroU*::midpoint`](https://doc.rust-lang.org/std/num/type.NonZeroU32.html#method.midpoint)
- [impl `std::iter::Extend` for tuples with arity 1 through 12](https://doc.rust-lang.org/stable/std/iter/trait.Extend.html#impl-Extend%3C(A,)%3E-for-(EA,))
- [`FromIterator<(A, ...)>` for tuples with arity 1 through 12](https://doc.rust-lang.org/stable/std/iter/trait.FromIterator.html#impl-FromIterator%3C(EA,)%3E-for-(A,))
- [`std::task::Waker::noop`](https://doc.rust-lang.org/stable/std/task/struct.Waker.html#method.noop)
These APIs are now stable in const contexts:
- [`mem::size_of_val`](https://doc.rust-lang.org/stable/std/mem/fn.size_of_val.html)
- [`mem::align_of_val`](https://doc.rust-lang.org/stable/std/mem/fn.align_of_val.html)
- [`Layout::for_value`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.for_value)
- [`Layout::align_to`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.align_to)
- [`Layout::pad_to_align`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.pad_to_align)
- [`Layout::extend`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.extend)
- [`Layout::array`](https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.array)
- [`std::mem::swap`](https://doc.rust-lang.org/stable/std/mem/fn.swap.html)
- [`std::ptr::swap`](https://doc.rust-lang.org/stable/std/ptr/fn.swap.html)
- [`NonNull::new`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.new)
- [`HashMap::with_hasher`](https://doc.rust-lang.org/stable/std/collections/struct.HashMap.html#method.with_hasher)
- [`HashSet::with_hasher`](https://doc.rust-lang.org/stable/std/collections/struct.HashSet.html#method.with_hasher)
- [`BuildHasherDefault::new`](https://doc.rust-lang.org/stable/std/hash/struct.BuildHasherDefault.html#method.new)
- [`<float>::recip`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.recip)
- [`<float>::to_degrees`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.to_degrees)
- [`<float>::to_radians`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.to_radians)
- [`<float>::max`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.max)
- [`<float>::min`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.min)
- [`<float>::clamp`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.clamp)
- [`<float>::abs`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.abs)
- [`<float>::signum`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.signum)
- [`<float>::copysign`](https://doc.rust-lang.org/stable/std/primitive.f32.html#method.copysign)
- [`MaybeUninit::write`](https://doc.rust-lang.org/stable/std/mem/union.MaybeUninit.html#method.write)
<a id="1.85.0-Cargo"></a>
Cargo
-----
- [Add future-incompatibility warning against keywords in cfgs and add raw-idents](https://github.com/rust-lang/cargo/pull/14671/)
- [Stabilize higher precedence trailing flags](https://github.com/rust-lang/cargo/pull/14900/)
- [Pass `CARGO_CFG_FEATURE` to build scripts](https://github.com/rust-lang/cargo/pull/14902/)
<a id="1.85.0-Rustdoc"></a>
Rustdoc
-----
- [Doc comment on impl blocks shows the first line, even when the impl block is collapsed](https://github.com/rust-lang/rust/pull/132155)
<a id="1.85.0-Compatibility-Notes"></a>
Compatibility Notes
-------------------
- [`rustc` no longer treats the `test` cfg as a well known check-cfg](https://github.com/rust-lang/rust/pull/131729), instead it is up to the build systems and users of `--check-cfg`[^check-cfg] to set it as a well known cfg using `--check-cfg=cfg(test)`.
This is done to enable build systems like Cargo to set it conditionally, as not all source files are suitable for unit tests.
[Cargo (for now) unconditionally sets the `test` cfg as a well known cfg](https://github.com/rust-lang/cargo/pull/14963).
[^check-cfg]: https://doc.rust-lang.org/nightly/rustc/check-cfg.html
- [Disable potentially incorrect type inference if there are trivial and non-trivial where-clauses](https://github.com/rust-lang/rust/pull/132325)
- `std::env::home_dir()` has been deprecated for years, because it can give surprising results in some Windows configurations if the `HOME` environment variable is set (which is not the normal configuration on Windows). We had previously avoided changing its behavior, out of concern for compatibility with code depending on this non-standard configuration. Given how long this function has been deprecated, we're now fixing its behavior as a bugfix. A subsequent release will remove the deprecation for this function.
- [Make `core::ffi::c_char` signedness more closely match that of the platform-default `char`](https://github.com/rust-lang/rust/pull/132975)
This changed `c_char` from an `i8` to `u8` or vice versa on many Tier 2 and 3
targets (mostly Arm and RISC-V embedded targets). The new definition may
result in compilation failures but fixes compatibility issues with C.
The `libc` crate matches this change as of its 0.2.169 release.
- [When compiling a nested `macro_rules` macro from an external crate, the content of the inner `macro_rules` is now built with the edition of the external crate, not the local crate.](https://github.com/rust-lang/rust/pull/133274)
- [Increase `sparcv9-sun-solaris` and `x86_64-pc-solaris` Solaris baseline to 11.4.](https://github.com/rust-lang/rust/pull/133293)
- [Show `abi_unsupported_vector_types` lint in future breakage reports](https://github.com/rust-lang/rust/pull/133374)
- [Error if multiple super-trait instantiations of `dyn Trait` need associated types to be specified but only one is provided](https://github.com/rust-lang/rust/pull/133392)
- [Change `powerpc64-ibm-aix` default `codemodel` to large](https://github.com/rust-lang/rust/pull/133811)
<a id="1.85.0-Internal-Changes"></a>
Internal Changes
----------------
These changes do not affect any public interfaces of Rust, but they represent
significant improvements to the performance or internals of rustc and related
tools.
- [Build `x86_64-unknown-linux-gnu` with LTO for C/C++ code (e.g., `jemalloc`)](https://github.com/rust-lang/rust/pull/134690)
Version 1.84.1 (2025-01-30)
==========================

View file

@ -424,20 +424,23 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.ann_post(ident)
}
fn strsep<T, F>(
fn strsep<'x, T: 'x, F, I>(
&mut self,
sep: &'static str,
space_before: bool,
b: Breaks,
elts: &[T],
elts: I,
mut op: F,
) where
F: FnMut(&mut Self, &T),
I: IntoIterator<Item = &'x T>,
{
let mut it = elts.into_iter();
self.rbox(0, b);
if let Some((first, rest)) = elts.split_first() {
if let Some(first) = it.next() {
op(self, first);
for elt in rest {
for elt in it {
if space_before {
self.space();
}
@ -448,9 +451,10 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
self.end();
}
fn commasep<T, F>(&mut self, b: Breaks, elts: &[T], op: F)
fn commasep<'x, T: 'x, F, I>(&mut self, b: Breaks, elts: I, op: F)
where
F: FnMut(&mut Self, &T),
I: IntoIterator<Item = &'x T>,
{
self.strsep(",", false, b, elts, op)
}

View file

@ -188,8 +188,8 @@ jobs:
fail-fast: false
matrix:
include:
# FIXME update at some point in the future once most distros use a newer glibc
- os: ubuntu-20.04
# Intentionally using an older ubuntu version to lower the glibc requirements of the distributed cg_clif
- os: ubuntu-22.04
env:
TARGET_TRIPLE: x86_64-unknown-linux-gnu
- os: macos-latest

View file

@ -1,4 +1,4 @@
[toolchain]
channel = "nightly-2025-02-07"
channel = "nightly-2025-02-15"
components = ["rust-src", "rustc-dev", "llvm-tools"]
profile = "minimal"

View file

@ -3,8 +3,9 @@ ignore = [
]
# Matches rustfmt.toml of rustc
version = "Two"
style_edition = "2024"
use_small_heuristics = "Max"
merge_derives = false
group_imports = "StdExternalCrate"
imports_granularity = "Module"
use_field_init_shorthand = true

View file

@ -195,7 +195,7 @@ pub(super) fn from_casted_value<'tcx>(
// It may also be smaller for example when the type is a wrapper around an integer with a
// larger alignment than the integer.
std::cmp::max(abi_param_size, layout_size),
u32::try_from(layout.align.pref.bytes()).unwrap(),
u32::try_from(layout.align.abi.bytes()).unwrap(),
);
let mut offset = 0;
let mut block_params_iter = block_params.iter().copied();

View file

@ -382,6 +382,11 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
}
pub(crate) fn create_stack_slot(&mut self, size: u32, align: u32) -> Pointer {
assert!(
size % align == 0,
"size must be a multiple of alignment (size={size}, align={align})"
);
let abi_align = if self.tcx.sess.target.arch == "s390x" { 8 } else { 16 };
if align <= abi_align {
let stack_slot = self.bcx.create_sized_stack_slot(StackSlotData {
@ -403,7 +408,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
align_shift: 4,
});
let base_ptr = self.bcx.ins().stack_addr(self.pointer_type, stack_slot, 0);
let misalign_offset = self.bcx.ins().urem_imm(base_ptr, i64::from(align));
let misalign_offset = self.bcx.ins().band_imm(base_ptr, i64::from(align - 1));
let realign_offset = self.bcx.ins().irsub_imm(misalign_offset, i64::from(align));
Pointer::new(self.bcx.ins().iadd(base_ptr, realign_offset))
}

View file

@ -304,7 +304,7 @@ impl DebugContext {
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(line));
entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.pref.bytes()));
entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(static_layout.align.abi.bytes()));
let mut expr = Expression::new();
expr.op_addr(address_for_data(data_id));

View file

@ -166,7 +166,7 @@ impl DebugContext {
let tuple_entry = self.dwarf.unit.get_mut(tuple_type_id);
tuple_entry.set(gimli::DW_AT_name, AttributeValue::StringRef(self.dwarf.strings.add(name)));
tuple_entry.set(gimli::DW_AT_byte_size, AttributeValue::Udata(layout.size.bytes()));
tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.pref.bytes()));
tuple_entry.set(gimli::DW_AT_alignment, AttributeValue::Udata(layout.align.abi.bytes()));
for (i, (ty, dw_ty)) in components.into_iter().enumerate() {
let member_id = self.dwarf.unit.add(tuple_type_id, gimli::DW_TAG_member);
@ -179,7 +179,7 @@ impl DebugContext {
member_entry.set(
gimli::DW_AT_alignment,
AttributeValue::Udata(
FullyMonomorphizedLayoutCx(tcx).layout_of(ty).align.pref.bytes(),
FullyMonomorphizedLayoutCx(tcx).layout_of(ty).align.abi.bytes(),
),
);
member_entry.set(

View file

@ -871,7 +871,8 @@ fn call_inline_asm<'tcx>(
inputs: Vec<(Size, Value)>,
outputs: Vec<(Size, CPlace<'tcx>)>,
) {
let stack_slot = fx.create_stack_slot(u32::try_from(slot_size.bytes()).unwrap(), 16);
let stack_slot =
fx.create_stack_slot(u32::try_from(slot_size.bytes().next_multiple_of(16)).unwrap(), 16);
let inline_asm_func = fx
.module

View file

@ -101,7 +101,7 @@ impl<'tcx> CValue<'tcx> {
/// The is represented by a dangling pointer of suitable alignment.
pub(crate) fn zst(layout: TyAndLayout<'tcx>) -> CValue<'tcx> {
assert!(layout.is_zst());
CValue::by_ref(crate::Pointer::dangling(layout.align.pref), layout)
CValue::by_ref(crate::Pointer::dangling(layout.align.abi), layout)
}
pub(crate) fn layout(&self) -> TyAndLayout<'tcx> {
@ -392,7 +392,7 @@ impl<'tcx> CPlace<'tcx> {
assert!(layout.is_sized());
if layout.size.bytes() == 0 {
return CPlace {
inner: CPlaceInner::Addr(Pointer::dangling(layout.align.pref), None),
inner: CPlaceInner::Addr(Pointer::dangling(layout.align.abi), None),
layout,
};
}
@ -405,7 +405,7 @@ impl<'tcx> CPlace<'tcx> {
let stack_slot = fx.create_stack_slot(
u32::try_from(layout.size.bytes()).unwrap(),
u32::try_from(layout.align.pref.bytes()).unwrap(),
u32::try_from(layout.align.abi.bytes()).unwrap(),
);
CPlace { inner: CPlaceInner::Addr(stack_slot, None), layout }
}

View file

@ -194,6 +194,12 @@ pub(crate) unsafe fn create_module<'ll>(
target_data_layout = target_data_layout.replace("-i128:128", "");
}
}
if llvm_version < (21, 0, 0) {
if sess.target.arch == "nvptx64" {
// LLVM 21 updated the default layout on nvptx: https://github.com/llvm/llvm-project/pull/124961
target_data_layout = target_data_layout.replace("e-p6:32:32-i64", "e-i64");
}
}
// Ensure the data-layout values hardcoded remain the defaults.
{

View file

@ -1776,6 +1776,7 @@ fn exported_symbols_for_non_proc_macro(tcx: TyCtxt<'_>, crate_type: CrateType) -
symbols.push(symbol_export::exporting_symbol_name_for_instance_in_crate(
tcx, symbol, cnum,
));
symbol_export::extend_exported_symbols(&mut symbols, tcx, symbol, cnum);
}
});

View file

@ -10,9 +10,10 @@ use rustc_middle::middle::exported_symbols::{
ExportedSymbol, SymbolExportInfo, SymbolExportKind, SymbolExportLevel, metadata_symbol_name,
};
use rustc_middle::query::LocalCrate;
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, TyCtxt};
use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, Instance, SymbolName, Ty, TyCtxt};
use rustc_middle::util::Providers;
use rustc_session::config::{CrateType, OomStrategy};
use rustc_target::callconv::Conv;
use rustc_target::spec::{SanitizerSet, TlsModel};
use tracing::debug;
@ -584,6 +585,42 @@ pub(crate) fn symbol_name_for_instance_in_crate<'tcx>(
}
}
fn calling_convention_for_symbol<'tcx>(
tcx: TyCtxt<'tcx>,
symbol: ExportedSymbol<'tcx>,
) -> (Conv, &'tcx [rustc_target::callconv::ArgAbi<'tcx, Ty<'tcx>>]) {
let instance = match symbol {
ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _)
if tcx.is_static(def_id) =>
{
None
}
ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)),
ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)),
// DropGlue always use the Rust calling convention and thus follow the target's default
// symbol decoration scheme.
ExportedSymbol::DropGlue(..) => None,
// AsyncDropGlueCtorShim always use the Rust calling convention and thus follow the
// target's default symbol decoration scheme.
ExportedSymbol::AsyncDropGlueCtorShim(..) => None,
// NoDefId always follow the target's default symbol decoration scheme.
ExportedSymbol::NoDefId(..) => None,
// ThreadLocalShim always follow the target's default symbol decoration scheme.
ExportedSymbol::ThreadLocalShim(..) => None,
};
instance
.map(|i| {
tcx.fn_abi_of_instance(
ty::TypingEnv::fully_monomorphized().as_query_input((i, ty::List::empty())),
)
.unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed"))
})
.map(|fnabi| (fnabi.conv, &fnabi.args[..]))
// FIXME(workingjubilee): why don't we know the convention here?
.unwrap_or((Conv::Rust, &[]))
}
/// This is the symbol name of the given instance as seen by the linker.
///
/// On 32-bit Windows symbols are decorated according to their calling conventions.
@ -592,8 +629,6 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
symbol: ExportedSymbol<'tcx>,
instantiating_crate: CrateNum,
) -> String {
use rustc_target::callconv::Conv;
let mut undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
// thread local will not be a function call,
@ -617,35 +652,7 @@ pub(crate) fn linking_symbol_name_for_instance_in_crate<'tcx>(
_ => return undecorated,
};
let instance = match symbol {
ExportedSymbol::NonGeneric(def_id) | ExportedSymbol::Generic(def_id, _)
if tcx.is_static(def_id) =>
{
None
}
ExportedSymbol::NonGeneric(def_id) => Some(Instance::mono(tcx, def_id)),
ExportedSymbol::Generic(def_id, args) => Some(Instance::new(def_id, args)),
// DropGlue always use the Rust calling convention and thus follow the target's default
// symbol decoration scheme.
ExportedSymbol::DropGlue(..) => None,
// AsyncDropGlueCtorShim always use the Rust calling convention and thus follow the
// target's default symbol decoration scheme.
ExportedSymbol::AsyncDropGlueCtorShim(..) => None,
// NoDefId always follow the target's default symbol decoration scheme.
ExportedSymbol::NoDefId(..) => None,
// ThreadLocalShim always follow the target's default symbol decoration scheme.
ExportedSymbol::ThreadLocalShim(..) => None,
};
let (conv, args) = instance
.map(|i| {
tcx.fn_abi_of_instance(
ty::TypingEnv::fully_monomorphized().as_query_input((i, ty::List::empty())),
)
.unwrap_or_else(|_| bug!("fn_abi_of_instance({i:?}) failed"))
})
.map(|fnabi| (fnabi.conv, &fnabi.args[..]))
.unwrap_or((Conv::Rust, &[]));
let (conv, args) = calling_convention_for_symbol(tcx, symbol);
// Decorate symbols with prefixes, suffixes and total number of bytes of arguments.
// Reference: https://docs.microsoft.com/en-us/cpp/build/reference/decorated-names?view=msvc-170
@ -677,6 +684,27 @@ pub(crate) fn exporting_symbol_name_for_instance_in_crate<'tcx>(
maybe_emutls_symbol_name(tcx, symbol, &undecorated).unwrap_or(undecorated)
}
/// On amdhsa, `gpu-kernel` functions have an associated metadata object with a `.kd` suffix.
/// Add it to the symbols list for all kernel functions, so that it is exported in the linked
/// object.
pub(crate) fn extend_exported_symbols<'tcx>(
symbols: &mut Vec<String>,
tcx: TyCtxt<'tcx>,
symbol: ExportedSymbol<'tcx>,
instantiating_crate: CrateNum,
) {
let (conv, _) = calling_convention_for_symbol(tcx, symbol);
if conv != Conv::GpuKernel || tcx.sess.target.os != "amdhsa" {
return;
}
let undecorated = symbol_name_for_instance_in_crate(tcx, symbol, instantiating_crate);
// Add the symbol for the kernel descriptor (with .kd suffix)
symbols.push(format!("{undecorated}.kd"));
}
fn maybe_emutls_symbol_name<'tcx>(
tcx: TyCtxt<'tcx>,
symbol: ExportedSymbol<'tcx>,

View file

@ -241,7 +241,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
interp_ok(caller == callee)
}
fn check_argument_compat(
/// Returns a `bool` saying whether the two arguments are ABI-compatible.
pub fn check_argument_compat(
&self,
caller_abi: &ArgAbi<'tcx, Ty<'tcx>>,
callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,

View file

@ -667,11 +667,12 @@ fn print_crate_info(
return Compilation::Continue;
};
let t_outputs = rustc_interface::util::build_output_filenames(attrs, sess);
let id = rustc_session::output::find_crate_name(sess, attrs);
let crate_name = passes::get_crate_name(sess, attrs);
let crate_types = collect_crate_types(sess, attrs);
for &style in &crate_types {
let fname =
rustc_session::output::filename_for_input(sess, style, id, &t_outputs);
let fname = rustc_session::output::filename_for_input(
sess, style, crate_name, &t_outputs,
);
println_info!("{}", fname.as_path().file_name().unwrap().to_string_lossy());
}
}
@ -680,8 +681,7 @@ fn print_crate_info(
// no crate attributes, print out an error and exit
return Compilation::Continue;
};
let id = rustc_session::output::find_crate_name(sess, attrs);
println_info!("{id}");
println_info!("{}", passes::get_crate_name(sess, attrs));
}
Cfg => {
let mut cfgs = sess

View file

@ -183,12 +183,12 @@ pub(crate) fn mod_file_path_from_attr(
let first_path = attrs.iter().find(|at| at.has_name(sym::path))?;
let Some(path_sym) = first_path.value_str() else {
// This check is here mainly to catch attempting to use a macro,
// such as #[path = concat!(...)]. This isn't currently supported
// because otherwise the InvocationCollector would need to defer
// loading a module until the #[path] attribute was expanded, and
// it doesn't support that (and would likely add a bit of
// complexity). Usually bad forms are checked in AstValidator (via
// `check_builtin_attribute`), but by the time that runs the macro
// such as `#[path = concat!(...)]`. This isn't supported because
// otherwise the `InvocationCollector` would need to defer loading
// a module until the `#[path]` attribute was expanded, and it
// doesn't support that (and would likely add a bit of complexity).
// Usually bad forms are checked during semantic analysis via
// `TyCtxt::check_mod_attrs`), but by the time that runs the macro
// is expanded, and it doesn't give an error.
validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, first_path, sym::path);
};

View file

@ -18,7 +18,8 @@ use rustc_ast_pretty::pprust::state::MacHeader;
use rustc_ast_pretty::pprust::{Comments, PrintState};
use rustc_hir::{
BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TyPatKind,
HirId, ImplicitSelfKind, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
TyPatKind,
};
use rustc_span::source_map::SourceMap;
use rustc_span::{FileName, Ident, Span, Symbol, kw};
@ -2086,6 +2087,28 @@ impl<'a> State<'a> {
self.print_pat(arg.pat);
}
fn print_implicit_self(&mut self, implicit_self_kind: &hir::ImplicitSelfKind) {
match implicit_self_kind {
ImplicitSelfKind::Imm => {
self.word("self");
}
ImplicitSelfKind::Mut => {
self.print_mutability(hir::Mutability::Mut, false);
self.word("self");
}
ImplicitSelfKind::RefImm => {
self.word("&");
self.word("self");
}
ImplicitSelfKind::RefMut => {
self.word("&");
self.print_mutability(hir::Mutability::Mut, false);
self.word("self");
}
ImplicitSelfKind::None => unreachable!(),
}
}
fn print_arm(&mut self, arm: &hir::Arm<'_>) {
// I have no idea why this check is necessary, but here it
// is :(
@ -2151,27 +2174,33 @@ impl<'a> State<'a> {
// Make sure we aren't supplied *both* `arg_names` and `body_id`.
assert!(arg_names.is_empty() || body_id.is_none());
let mut i = 0;
let mut print_arg = |s: &mut Self| {
if let Some(arg_name) = arg_names.get(i) {
s.word(arg_name.to_string());
s.word(":");
s.space();
} else if let Some(body_id) = body_id {
s.ann.nested(s, Nested::BodyParamPat(body_id, i));
s.word(":");
s.space();
let mut print_arg = |s: &mut Self, ty: Option<&hir::Ty<'_>>| {
if i == 0 && decl.implicit_self.has_implicit_self() {
s.print_implicit_self(&decl.implicit_self);
} else {
if let Some(arg_name) = arg_names.get(i) {
s.word(arg_name.to_string());
s.word(":");
s.space();
} else if let Some(body_id) = body_id {
s.ann.nested(s, Nested::BodyParamPat(body_id, i));
s.word(":");
s.space();
}
if let Some(ty) = ty {
s.print_type(ty);
}
}
i += 1;
};
self.commasep(Inconsistent, decl.inputs, |s, ty| {
s.ibox(INDENT_UNIT);
print_arg(s);
s.print_type(ty);
print_arg(s, Some(ty));
s.end();
});
if decl.c_variadic {
self.word(", ");
print_arg(self);
print_arg(self, None);
self.word("...");
}
self.pclose();
@ -2284,7 +2313,9 @@ impl<'a> State<'a> {
GenericBound::Use(args, _) => {
self.word("use <");
self.commasep(Inconsistent, args, |s, arg| s.print_precise_capturing_arg(*arg));
self.commasep(Inconsistent, *args, |s, arg| {
s.print_precise_capturing_arg(*arg)
});
self.word(">");
}
@ -2300,10 +2331,23 @@ impl<'a> State<'a> {
}
fn print_generic_params(&mut self, generic_params: &[GenericParam<'_>]) {
if !generic_params.is_empty() {
let is_lifetime_elided = |generic_param: &GenericParam<'_>| {
matches!(
generic_param.kind,
GenericParamKind::Lifetime { kind: LifetimeParamKind::Elided(_) }
)
};
// We don't want to show elided lifetimes as they are compiler-inserted and not
// expressible in surface level Rust.
if !generic_params.is_empty() && !generic_params.iter().all(is_lifetime_elided) {
self.word("<");
self.commasep(Inconsistent, generic_params, |s, param| s.print_generic_param(param));
self.commasep(
Inconsistent,
generic_params.iter().filter(|gp| !is_lifetime_elided(gp)),
|s, param| s.print_generic_param(param),
);
self.word(">");
}

View file

@ -117,8 +117,9 @@ use rustc_data_structures::{base_n, flock};
use rustc_fs_util::{LinkOrCopy, link_or_copy, try_canonicalize};
use rustc_middle::bug;
use rustc_session::config::CrateType;
use rustc_session::output::{collect_crate_types, find_crate_name};
use rustc_session::output::collect_crate_types;
use rustc_session::{Session, StableCrateId};
use rustc_span::Symbol;
use tracing::debug;
use crate::errors;
@ -211,7 +212,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu
/// The garbage collection will take care of it.
///
/// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph
pub(crate) fn prepare_session_directory(sess: &Session) {
pub(crate) fn prepare_session_directory(sess: &Session, crate_name: Symbol) {
if sess.opts.incremental.is_none() {
return;
}
@ -221,7 +222,7 @@ pub(crate) fn prepare_session_directory(sess: &Session) {
debug!("prepare_session_directory");
// {incr-comp-dir}/{crate-name-and-disambiguator}
let crate_dir = crate_path(sess);
let crate_dir = crate_path(sess, crate_name);
debug!("crate-dir: {}", crate_dir.display());
create_dir(sess, &crate_dir, "crate");
@ -594,10 +595,9 @@ fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> {
Ok(UNIX_EPOCH + duration)
}
fn crate_path(sess: &Session) -> PathBuf {
fn crate_path(sess: &Session, crate_name: Symbol) -> PathBuf {
let incr_dir = sess.opts.incremental.as_ref().unwrap().clone();
let crate_name = find_crate_name(sess, &[]);
let crate_types = collect_crate_types(sess, &[]);
let stable_crate_id = StableCrateId::new(
crate_name,

View file

@ -11,6 +11,7 @@ use rustc_serialize::Decodable;
use rustc_serialize::opaque::MemDecoder;
use rustc_session::Session;
use rustc_session::config::IncrementalStateAssertion;
use rustc_span::Symbol;
use tracing::{debug, warn};
use super::data::*;
@ -203,9 +204,9 @@ pub fn load_query_result_cache(sess: &Session) -> Option<OnDiskCache> {
/// Setups the dependency graph by loading an existing graph from disk and set up streaming of a
/// new graph to an incremental session directory.
pub fn setup_dep_graph(sess: &Session) -> DepGraph {
pub fn setup_dep_graph(sess: &Session, crate_name: Symbol) -> DepGraph {
// `load_dep_graph` can only be called after `prepare_session_directory`.
prepare_session_directory(sess);
prepare_session_directory(sess, crate_name);
let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess));

View file

@ -6,6 +6,10 @@ interface_abi_required_feature_issue = for more information, see issue #116344 <
interface_cant_emit_mir =
could not emit MIR: {$error}
interface_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$crate_name}` != `{$attr_crate_name}`
interface_crate_name_invalid = crate names cannot start with a `-`, but `{$crate_name}` has a leading hyphen
interface_emoji_identifier =
identifiers cannot contain emoji: `{$ident}`

View file

@ -4,6 +4,21 @@ use std::path::Path;
use rustc_macros::Diagnostic;
use rustc_span::{Span, Symbol};
#[derive(Diagnostic)]
#[diag(interface_crate_name_does_not_match)]
pub(crate) struct CrateNameDoesNotMatch {
#[primary_span]
pub(crate) span: Span,
pub(crate) crate_name: Symbol,
pub(crate) attr_crate_name: Symbol,
}
#[derive(Diagnostic)]
#[diag(interface_crate_name_invalid)]
pub(crate) struct CrateNameInvalid<'a> {
pub(crate) crate_name: &'a str,
}
#[derive(Diagnostic)]
#[diag(interface_ferris_identifier)]
pub struct FerrisIdentifier {

View file

@ -28,10 +28,12 @@ use rustc_passes::{abi_test, input_stats, layout_test};
use rustc_resolve::Resolver;
use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
use rustc_session::cstore::Untracked;
use rustc_session::output::{collect_crate_types, filename_for_input, find_crate_name};
use rustc_session::output::{collect_crate_types, filename_for_input};
use rustc_session::search_paths::PathKind;
use rustc_session::{Limit, Session};
use rustc_span::{ErrorGuaranteed, FileName, SourceFileHash, SourceFileHashAlgorithm, Symbol, sym};
use rustc_span::{
ErrorGuaranteed, FileName, SourceFileHash, SourceFileHashAlgorithm, Span, Symbol, sym,
};
use rustc_target::spec::PanicStrategy;
use rustc_trait_selection::traits;
use tracing::{info, instrument};
@ -725,8 +727,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
let pre_configured_attrs = rustc_expand::config::pre_configure_attrs(sess, &krate.attrs);
// parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches.
let crate_name = find_crate_name(sess, &pre_configured_attrs);
let crate_name = get_crate_name(sess, &pre_configured_attrs);
let crate_types = collect_crate_types(sess, &pre_configured_attrs);
let stable_crate_id = StableCrateId::new(
crate_name,
@ -735,7 +736,7 @@ pub fn create_and_enter_global_ctxt<T, F: for<'tcx> FnOnce(TyCtxt<'tcx>) -> T>(
sess.cfg_version,
);
let outputs = util::build_output_filenames(&pre_configured_attrs, sess);
let dep_graph = setup_dep_graph(sess);
let dep_graph = setup_dep_graph(sess, crate_name);
let cstore =
FreezeLock::new(Box::new(CStore::new(compiler.codegen_backend.metadata_loader())) as _);
@ -1080,23 +1081,85 @@ pub(crate) fn start_codegen<'tcx>(
codegen
}
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
if let Some(attr) = krate_attrs
.iter()
.find(|attr| attr.has_name(sym::recursion_limit) && attr.value_str().is_none())
{
// This is here mainly to check for using a macro, such as
// #![recursion_limit = foo!()]. That is not supported since that
// would require expanding this while in the middle of expansion,
// which needs to know the limit before expanding. Otherwise,
// validation would normally be caught in AstValidator (via
// `check_builtin_attribute`), but by the time that runs the macro
// is expanded, and it doesn't give an error.
validate_attr::emit_fatal_malformed_builtin_attribute(
&sess.psess,
attr,
sym::recursion_limit,
);
/// Compute and validate the crate name.
pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol {
// We validate *all* occurrences of `#![crate_name]`, pick the first find and
// if a crate name was passed on the command line via `--crate-name` we enforce
// that they match.
// We perform the validation step here instead of later to ensure it gets run
// in all code paths that require the crate name very early on, namely before
// macro expansion.
let attr_crate_name =
validate_and_find_value_str_builtin_attr(sym::crate_name, sess, krate_attrs);
let validate = |name, span| {
rustc_session::output::validate_crate_name(sess, name, span);
name
};
if let Some(crate_name) = &sess.opts.crate_name {
let crate_name = Symbol::intern(crate_name);
if let Some((attr_crate_name, span)) = attr_crate_name
&& attr_crate_name != crate_name
{
sess.dcx().emit_err(errors::CrateNameDoesNotMatch {
span,
crate_name,
attr_crate_name,
});
}
return validate(crate_name, None);
}
if let Some((crate_name, span)) = attr_crate_name {
return validate(crate_name, Some(span));
}
if let Input::File(ref path) = sess.io.input
&& let Some(file_stem) = path.file_stem().and_then(|s| s.to_str())
{
if file_stem.starts_with('-') {
sess.dcx().emit_err(errors::CrateNameInvalid { crate_name: file_stem });
} else {
return validate(Symbol::intern(&file_stem.replace('-', "_")), None);
}
}
sym::rust_out
}
fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
// We don't permit macro calls inside of the attribute (e.g., #![recursion_limit = `expand!()`])
// because that would require expanding this while in the middle of expansion, which needs to
// know the limit before expanding.
let _ = validate_and_find_value_str_builtin_attr(sym::recursion_limit, sess, krate_attrs);
rustc_middle::middle::limits::get_recursion_limit(krate_attrs, sess)
}
/// Validate *all* occurrences of the given "[value-str]" built-in attribute and return the first find.
///
/// This validator is intended for built-in attributes whose value needs to be known very early
/// during compilation (namely, before macro expansion) and it mainly exists to reject macro calls
/// inside of the attributes, such as in `#![name = expand!()]`. Normal attribute validation happens
/// during semantic analysis via [`TyCtxt::check_mod_attrs`] which happens *after* macro expansion
/// when such macro calls (here: `expand`) have already been expanded and we can no longer check for
/// their presence.
///
/// [value-str]: ast::Attribute::value_str
fn validate_and_find_value_str_builtin_attr(
name: Symbol,
sess: &Session,
krate_attrs: &[ast::Attribute],
) -> Option<(Symbol, Span)> {
let mut result = None;
// Validate *all* relevant attributes, not just the first occurrence.
for attr in ast::attr::filter_by_name(krate_attrs, name) {
let Some(value) = attr.value_str() else {
validate_attr::emit_fatal_malformed_builtin_attribute(&sess.psess, attr, name)
};
// Choose the first occurrence as our result.
result.get_or_insert((value, attr.span));
}
result
}

View file

@ -433,11 +433,11 @@ pub(crate) fn check_attr_crate_type(
}
} else {
// This is here mainly to check for using a macro, such as
// #![crate_type = foo!()]. That is not supported since the
// `#![crate_type = foo!()]`. That is not supported since the
// crate type needs to be known very early in compilation long
// before expansion. Otherwise, validation would normally be
// caught in AstValidator (via `check_builtin_attribute`), but
// by the time that runs the macro is expanded, and it doesn't
// caught during semantic analysis via `TyCtxt::check_mod_attrs`,
// but by the time that runs the macro is expanded, and it doesn't
// give an error.
validate_attr::emit_fatal_malformed_builtin_attribute(
&sess.psess,

View file

@ -1,5 +1,4 @@
use std::iter;
use std::ops::ControlFlow;
use rustc_ast as ast;
use rustc_ast::util::{classify, parser};
@ -781,29 +780,6 @@ trait UnusedDelimLint {
right_pos: Option<BytePos>,
is_kw: bool,
) {
// If `value` has `ExprKind::Err`, unused delim lint can be broken.
// For example, the following code caused ICE.
// This is because the `ExprKind::Call` in `value` has `ExprKind::Err` as its argument
// and this leads to wrong spans. #104897
//
// ```
// fn f(){(print!(á
// ```
use rustc_ast::visit::{Visitor, walk_expr};
struct ErrExprVisitor;
impl<'ast> Visitor<'ast> for ErrExprVisitor {
type Result = ControlFlow<()>;
fn visit_expr(&mut self, expr: &'ast ast::Expr) -> ControlFlow<()> {
if let ExprKind::Err(_) = expr.kind {
ControlFlow::Break(())
} else {
walk_expr(self, expr)
}
}
}
if ErrExprVisitor.visit_expr(value).is_break() {
return;
}
let spans = match value.kind {
ast::ExprKind::Block(ref block, None) if let [stmt] = block.stmts.as_slice() => stmt
.span

View file

@ -189,7 +189,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
// Lower the endpoint into a temporary `PatKind` that will then be
// deconstructed to obtain the constant value and other data.
let mut kind: PatKind<'tcx> = self.lower_lit(expr);
let mut kind: PatKind<'tcx> = self.lower_pat_expr(expr);
// Unpeel any ascription or inline-const wrapper nodes.
loop {
@ -353,7 +353,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
hir::PatKind::Never => PatKind::Never,
hir::PatKind::Expr(value) => self.lower_lit(value),
hir::PatKind::Expr(value) => self.lower_pat_expr(value),
hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
@ -638,54 +638,57 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let ty = self.typeck_results.node_type(id);
let res = self.typeck_results.qpath_res(qpath, id);
let pat_from_kind = |kind| Box::new(Pat { span, ty, kind });
let (def_id, user_ty) = match res {
Res::Def(DefKind::Const, def_id) => (def_id, None),
Res::Def(DefKind::AssocConst, def_id) => {
(def_id, self.typeck_results.user_provided_types().get(id))
}
let (def_id, is_associated_const) = match res {
Res::Def(DefKind::Const, def_id) => (def_id, false),
Res::Def(DefKind::AssocConst, def_id) => (def_id, true),
_ => return pat_from_kind(self.lower_variant_or_leaf(res, id, span, ty, vec![])),
_ => {
// The path isn't the name of a constant, so it must actually
// be a unit struct or unit variant (e.g. `Option::None`).
let kind = self.lower_variant_or_leaf(res, id, span, ty, vec![]);
return Box::new(Pat { span, ty, kind });
}
};
// Lower the named constant to a THIR pattern.
let args = self.typeck_results.node_args(id);
let c = ty::Const::new_unevaluated(self.tcx, ty::UnevaluatedConst { def: def_id, args });
let subpattern = self.const_to_pat(c, ty, id, span);
let pattern = Box::new(Pat {
span,
ty,
kind: PatKind::ExpandedConstant { subpattern, def_id, is_inline: false },
});
if !is_associated_const {
return pattern;
}
// Wrap the pattern in a marker node to indicate that it is the result
// of lowering a named constant. This marker is used for improved
// diagnostics in some situations, but has no effect at runtime.
let mut pattern = {
let kind = PatKind::ExpandedConstant { subpattern, def_id, is_inline: false };
Box::new(Pat { span, ty, kind })
};
let user_provided_types = self.typeck_results.user_provided_types();
if let Some(&user_ty) = user_provided_types.get(id) {
// If this is an associated constant with an explicit user-written
// type, add an ascription node (e.g. `<Foo<'a> as MyTrait>::CONST`).
if let Some(&user_ty) = user_ty {
let annotation = CanonicalUserTypeAnnotation {
user_ty: Box::new(user_ty),
span,
inferred_ty: self.typeck_results.node_type(id),
};
Box::new(Pat {
span,
kind: PatKind::AscribeUserType {
subpattern: pattern,
ascription: Ascription {
annotation,
// Note that use `Contravariant` here. See the
// `variance` field documentation for details.
variance: ty::Contravariant,
},
let kind = PatKind::AscribeUserType {
subpattern: pattern,
ascription: Ascription {
annotation,
// Note that we use `Contravariant` here. See the
// `variance` field documentation for details.
variance: ty::Contravariant,
},
ty,
})
} else {
pattern
};
pattern = Box::new(Pat { span, kind, ty });
}
pattern
}
/// Converts inline const patterns.
/// Lowers an inline const block (e.g. `const { 1 + 1 }`) to a pattern.
fn lower_inline_const(
&mut self,
block: &'tcx hir::ConstBlock,
@ -705,14 +708,17 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
let subpattern = self.const_to_pat(ty::Const::new_unevaluated(self.tcx, ct), ty, id, span);
// Wrap the pattern in a marker node to indicate that it is the result
// of lowering an inline const block.
PatKind::ExpandedConstant { subpattern, def_id: def_id.to_def_id(), is_inline: true }
}
/// Converts literals, paths and negation of literals to patterns.
/// The special case for negation exists to allow things like `-128_i8`
/// which would overflow if we tried to evaluate `128_i8` and then negate
/// afterwards.
fn lower_lit(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> {
/// Lowers the kinds of "expression" that can appear in a HIR pattern:
/// - Paths (e.g. `FOO`, `foo::BAR`, `Option::None`)
/// - Inline const blocks (e.g. `const { 1 + 1 }`)
/// - Literals, possibly negated (e.g. `-128u8`, `"hello"`)
fn lower_pat_expr(&mut self, expr: &'tcx hir::PatExpr<'tcx>) -> PatKind<'tcx> {
let (lit, neg) = match &expr.kind {
hir::PatExprKind::Path(qpath) => {
return self.lower_path(qpath, expr.hir_id, expr.span).kind;

View file

@ -1,17 +1,17 @@
monomorphize_abi_error_disabled_vector_type_call =
this function call uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled in the caller
this function call uses SIMD vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled in the caller
.label = function called here
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
monomorphize_abi_error_disabled_vector_type_def =
this function definition uses a SIMD vector type that (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled
this function definition uses SIMD vector type `{$ty}` which (with the chosen ABI) requires the `{$required_feature}` target feature, which is not enabled
.label = function defined here
.help = consider enabling it globally (`-C target-feature=+{$required_feature}`) or locally (`#[target_feature(enable="{$required_feature}")]`)
monomorphize_abi_error_unsupported_vector_type_call =
this function call uses a SIMD vector type that is not currently supported with the chosen ABI
this function call uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI
.label = function called here
monomorphize_abi_error_unsupported_vector_type_def =
this function definition uses a SIMD vector type that is not currently supported with the chosen ABI
this function definition uses SIMD vector type `{$ty}` which is not currently supported with the chosen ABI
.label = function defined here
monomorphize_couldnt_dump_mono_stats =

View file

@ -1,6 +1,7 @@
use std::path::PathBuf;
use rustc_macros::{Diagnostic, LintDiagnostic};
use rustc_middle::ty::Ty;
use rustc_span::{Span, Symbol};
#[derive(Diagnostic)]
@ -75,6 +76,7 @@ pub(crate) struct AbiErrorDisabledVectorTypeDef<'a> {
#[label]
pub span: Span,
pub required_feature: &'a str,
pub ty: Ty<'a>,
}
#[derive(LintDiagnostic)]
@ -84,18 +86,21 @@ pub(crate) struct AbiErrorDisabledVectorTypeCall<'a> {
#[label]
pub span: Span,
pub required_feature: &'a str,
pub ty: Ty<'a>,
}
#[derive(LintDiagnostic)]
#[diag(monomorphize_abi_error_unsupported_vector_type_def)]
pub(crate) struct AbiErrorUnsupportedVectorTypeDef {
pub(crate) struct AbiErrorUnsupportedVectorTypeDef<'a> {
#[label]
pub span: Span,
pub ty: Ty<'a>,
}
#[derive(LintDiagnostic)]
#[diag(monomorphize_abi_error_unsupported_vector_type_call)]
pub(crate) struct AbiErrorUnsupportedVectorTypeCall {
pub(crate) struct AbiErrorUnsupportedVectorTypeCall<'a> {
#[label]
pub span: Span,
pub ty: Ty<'a>,
}

View file

@ -34,7 +34,7 @@ fn do_check_abi<'tcx>(
tcx: TyCtxt<'tcx>,
abi: &FnAbi<'tcx, Ty<'tcx>>,
target_feature_def: DefId,
mut emit_err: impl FnMut(Option<&'static str>),
mut emit_err: impl FnMut(Ty<'tcx>, Option<&'static str>),
) {
let feature_def = tcx.sess.target.features_for_correct_vector_abi();
let codegen_attrs = tcx.codegen_fn_attrs(target_feature_def);
@ -45,7 +45,7 @@ fn do_check_abi<'tcx>(
let feature = match feature_def.iter().find(|(bits, _)| size.bits() <= *bits) {
Some((_, feature)) => feature,
None => {
emit_err(None);
emit_err(arg_abi.layout.ty, None);
continue;
}
};
@ -53,7 +53,7 @@ fn do_check_abi<'tcx>(
if !tcx.sess.unstable_target_features.contains(&feature_sym)
&& !codegen_attrs.target_features.iter().any(|x| x.name == feature_sym)
{
emit_err(Some(&feature));
emit_err(arg_abi.layout.ty, Some(&feature));
}
}
}
@ -69,21 +69,21 @@ fn check_instance_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
// function.
return;
};
do_check_abi(tcx, abi, instance.def_id(), |required_feature| {
do_check_abi(tcx, abi, instance.def_id(), |ty, required_feature| {
let span = tcx.def_span(instance.def_id());
if let Some(required_feature) = required_feature {
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorDisabledVectorTypeDef { span, required_feature },
AbiErrorDisabledVectorTypeDef { span, required_feature, ty },
);
} else {
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorUnsupportedVectorTypeDef { span },
AbiErrorUnsupportedVectorTypeDef { span, ty },
);
}
})
@ -123,20 +123,20 @@ fn check_call_site_abi<'tcx>(
// ABI failed to compute; this will not get through codegen.
return;
};
do_check_abi(tcx, callee_abi, caller.def_id(), |required_feature| {
do_check_abi(tcx, callee_abi, caller.def_id(), |ty, required_feature| {
if let Some(required_feature) = required_feature {
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorDisabledVectorTypeCall { span, required_feature },
AbiErrorDisabledVectorTypeCall { span, required_feature, ty },
);
} else {
tcx.emit_node_span_lint(
ABI_UNSUPPORTED_VECTOR_TYPES,
CRATE_HIR_ID,
span,
AbiErrorUnsupportedVectorTypeCall { span },
AbiErrorUnsupportedVectorTypeCall { span, ty },
);
}
});

View file

@ -743,9 +743,6 @@ parse_single_colon_import_path = expected `::`, found `:`
.suggestion = use double colon
.note = import paths are delimited using `::`
parse_single_colon_struct_type = found single colon in a struct field type path
.suggestion = write a path separator here
parse_static_with_generics = static items may not have generic parameters
parse_struct_literal_body_without_path =

View file

@ -3071,14 +3071,6 @@ pub(crate) struct BadItemKind {
pub help: bool,
}
#[derive(Diagnostic)]
#[diag(parse_single_colon_struct_type)]
pub(crate) struct SingleColonStructType {
#[primary_span]
#[suggestion(code = "::", applicability = "maybe-incorrect", style = "verbose")]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(parse_macro_rules_missing_bang)]
pub(crate) struct MacroRulesMissingBang {

View file

@ -2043,9 +2043,6 @@ impl<'a> Parser<'a> {
}
self.expect_field_ty_separator()?;
let ty = self.parse_ty()?;
if self.token == token::Colon && self.look_ahead(1, |t| *t != token::Colon) {
self.dcx().emit_err(errors::SingleColonStructType { span: self.token.span });
}
let default = if self.token == token::Eq {
self.bump();
let const_expr = self.parse_expr_anon_const()?;

View file

@ -1472,17 +1472,6 @@ impl<'a> Parser<'a> {
let mut last_non_comma_dotdot_span = None;
while self.token != token::CloseDelim(Delimiter::Brace) {
let attrs = match self.parse_outer_attributes() {
Ok(attrs) => attrs,
Err(err) => {
if let Some(delayed) = delayed_err {
delayed.emit();
}
return Err(err);
}
};
let lo = self.token.span;
// check that a comma comes after every field
if !ate_comma {
let err = if self.token == token::At {
@ -1585,6 +1574,17 @@ impl<'a> Parser<'a> {
}
}
let attrs = match self.parse_outer_attributes() {
Ok(attrs) => attrs,
Err(err) => {
if let Some(delayed) = delayed_err {
delayed.emit();
}
return Err(err);
}
};
let lo = self.token.span;
let field = self.collect_tokens(None, attrs, ForceCollect::No, |this, attrs| {
let field = match this.parse_pat_field(lo, attrs) {
Ok(field) => Ok(field),

View file

@ -246,8 +246,19 @@ impl<'a> Parser<'a> {
segments.push(segment);
if self.is_import_coupler() || !self.eat_path_sep() {
if style == PathStyle::Expr
&& self.may_recover()
let ok_for_recovery = self.may_recover()
&& match style {
PathStyle::Expr => true,
PathStyle::Type if let Some((ident, _)) = self.prev_token.ident() => {
self.token == token::Colon
&& ident.as_str().chars().all(|c| c.is_lowercase())
&& self.token.span.lo() == self.prev_token.span.hi()
&& self
.look_ahead(1, |token| self.token.span.hi() == token.span.lo())
}
_ => false,
};
if ok_for_recovery
&& self.token == token::Colon
&& self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident())
{

View file

@ -8,12 +8,8 @@ session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible
session_cli_feature_diagnostic_help =
add `-Zcrate-attr="feature({$feature})"` to the command-line options to enable
session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}`
session_crate_name_empty = crate name must not be empty
session_crate_name_invalid = crate names cannot start with a `-`, but `{$s}` has a leading hyphen
session_embed_source_insufficient_dwarf_version = `-Zembed-source=y` requires at least `-Z dwarf-version=5` but DWARF version is {$dwarf_version}
session_embed_source_requires_debug_info = `-Zembed-source=y` requires debug information to be enabled
@ -52,8 +48,8 @@ session_instrumentation_not_supported = {$us} instrumentation is not supported f
session_int_literal_too_large = integer literal is too large
.note = value exceeds limit of `{$limit}`
session_invalid_character_in_create_name = invalid character `{$character}` in crate name: `{$crate_name}`
session_invalid_character_in_create_name_help = you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name
session_invalid_character_in_crate_name = invalid character {$character} in crate name: `{$crate_name}`
.help = you can either pass `--crate-name` on the command line or add `#![crate_name = "…"]` to set the crate name
session_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
.label = invalid suffix `{$suffix}`

View file

@ -212,21 +212,6 @@ pub(crate) struct FileWriteFail<'a> {
pub(crate) err: String,
}
#[derive(Diagnostic)]
#[diag(session_crate_name_does_not_match)]
pub(crate) struct CrateNameDoesNotMatch {
#[primary_span]
pub(crate) span: Span,
pub(crate) s: Symbol,
pub(crate) name: Symbol,
}
#[derive(Diagnostic)]
#[diag(session_crate_name_invalid)]
pub(crate) struct CrateNameInvalid<'a> {
pub(crate) s: &'a str,
}
#[derive(Diagnostic)]
#[diag(session_crate_name_empty)]
pub(crate) struct CrateNameEmpty {
@ -235,20 +220,14 @@ pub(crate) struct CrateNameEmpty {
}
#[derive(Diagnostic)]
#[diag(session_invalid_character_in_create_name)]
#[diag(session_invalid_character_in_crate_name)]
pub(crate) struct InvalidCharacterInCrateName {
#[primary_span]
pub(crate) span: Option<Span>,
pub(crate) character: char,
pub(crate) crate_name: Symbol,
#[subdiagnostic]
pub(crate) crate_name_help: Option<InvalidCrateNameHelp>,
}
#[derive(Subdiagnostic)]
pub(crate) enum InvalidCrateNameHelp {
#[help(session_invalid_character_in_create_name_help)]
AddCrateName,
#[help]
pub(crate) help: Option<()>,
}
#[derive(Subdiagnostic)]

View file

@ -2,15 +2,12 @@
use std::path::Path;
use rustc_ast::{self as ast, attr};
use rustc_ast as ast;
use rustc_span::{Span, Symbol, sym};
use crate::Session;
use crate::config::{self, CrateType, Input, OutFileName, OutputFilenames, OutputType};
use crate::errors::{
self, CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable,
InvalidCharacterInCrateName, InvalidCrateNameHelp,
};
use crate::config::{self, CrateType, OutFileName, OutputFilenames, OutputType};
use crate::errors::{self, CrateNameEmpty, FileIsNotWriteable, InvalidCharacterInCrateName};
pub fn out_filename(
sess: &Session,
@ -49,69 +46,31 @@ fn is_writeable(p: &Path) -> bool {
}
}
pub fn find_crate_name(sess: &Session, attrs: &[ast::Attribute]) -> Symbol {
let validate = |s: Symbol, span: Option<Span>| {
validate_crate_name(sess, s, span);
s
};
// Look in attributes 100% of the time to make sure the attribute is marked
// as used. After doing this, however, we still prioritize a crate name from
// the command line over one found in the #[crate_name] attribute. If we
// find both we ensure that they're the same later on as well.
let attr_crate_name =
attr::find_by_name(attrs, sym::crate_name).and_then(|at| at.value_str().map(|s| (at, s)));
if let Some(ref s) = sess.opts.crate_name {
let s = Symbol::intern(s);
if let Some((attr, name)) = attr_crate_name {
if name != s {
sess.dcx().emit_err(CrateNameDoesNotMatch { span: attr.span, s, name });
}
}
return validate(s, None);
}
if let Some((attr, s)) = attr_crate_name {
return validate(s, Some(attr.span));
}
if let Input::File(ref path) = sess.io.input {
if let Some(s) = path.file_stem().and_then(|s| s.to_str()) {
if s.starts_with('-') {
sess.dcx().emit_err(CrateNameInvalid { s });
} else {
return validate(Symbol::intern(&s.replace('-', "_")), None);
}
}
}
sym::rust_out
}
pub fn validate_crate_name(sess: &Session, s: Symbol, sp: Option<Span>) {
/// Validate the given crate name.
///
/// Note that this validation is more permissive than identifier parsing. It considers
/// non-empty sequences of alphanumeric and underscore characters to be valid crate names.
/// Most notably, it accepts names starting with a numeric character like `0`!
///
/// Furthermore, this shouldn't be taken as the canonical crate name validator.
/// Other places may use a more restrictive grammar (e.g., identifier or ASCII identifier).
pub fn validate_crate_name(sess: &Session, crate_name: Symbol, span: Option<Span>) {
let mut guar = None;
{
if s.is_empty() {
guar = Some(sess.dcx().emit_err(CrateNameEmpty { span: sp }));
}
for c in s.as_str().chars() {
if c.is_alphanumeric() {
continue;
}
if c == '_' {
continue;
}
guar = Some(sess.dcx().emit_err(InvalidCharacterInCrateName {
span: sp,
character: c,
crate_name: s,
crate_name_help: if sp.is_none() {
Some(InvalidCrateNameHelp::AddCrateName)
} else {
None
},
}));
if crate_name.is_empty() {
guar = Some(sess.dcx().emit_err(CrateNameEmpty { span }));
}
for c in crate_name.as_str().chars() {
if c.is_alphanumeric() || c == '_' {
continue;
}
guar = Some(sess.dcx().emit_err(InvalidCharacterInCrateName {
span,
character: c,
crate_name,
help: span.is_none().then_some(()),
}));
}
if let Some(guar) = guar {

View file

@ -5,7 +5,7 @@ use crate::spec::{
pub(crate) fn target() -> Target {
Target {
arch: "nvptx64".into(),
data_layout: "e-i64:64-i128:128-v16:16-v32:32-n16:32:64".into(),
data_layout: "e-p6:32:32-i64:64-i128:128-v16:16-v32:32-n16:32:64".into(),
llvm_target: "nvptx64-nvidia-cuda".into(),
metadata: crate::spec::TargetMetadata {
description: Some("--emit=asm generates PTX code that runs on NVIDIA GPUs".into()),

View file

@ -187,7 +187,10 @@ fn predicates_reference_self(
fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span; 1]> {
tcx.associated_items(trait_def_id)
.in_definition_order()
// We're only looking at associated type bounds
.filter(|item| item.kind == ty::AssocKind::Type)
// Ignore GATs with `Self: Sized`
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
.flat_map(|item| tcx.explicit_item_bounds(item.def_id).iter_identity_copied())
.filter_map(|(clause, sp)| {
// Item bounds *can* have self projections, since they never get

View file

@ -2442,6 +2442,32 @@ impl<'a> Extend<Cow<'a, str>> for String {
}
}
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "ascii_char", issue = "110998")]
impl Extend<core::ascii::Char> for String {
fn extend<I: IntoIterator<Item = core::ascii::Char>>(&mut self, iter: I) {
self.vec.extend(iter.into_iter().map(|c| c.to_u8()));
}
#[inline]
fn extend_one(&mut self, c: core::ascii::Char) {
self.vec.push(c.to_u8());
}
}
#[cfg(not(no_global_oom_handling))]
#[unstable(feature = "ascii_char", issue = "110998")]
impl<'a> Extend<&'a core::ascii::Char> for String {
fn extend<I: IntoIterator<Item = &'a core::ascii::Char>>(&mut self, iter: I) {
self.extend(iter.into_iter().cloned());
}
#[inline]
fn extend_one(&mut self, c: &'a core::ascii::Char) {
self.vec.push(c.to_u8());
}
}
/// A convenience impl that delegates to the impl for `&str`.
///
/// # Examples

View file

@ -420,14 +420,14 @@ pub use self::adapters::{Intersperse, IntersperseWith};
issue = "42168"
)]
pub use self::range::Step;
#[stable(feature = "iter_empty", since = "1.2.0")]
pub use self::sources::{Empty, empty};
#[unstable(
feature = "iter_from_coroutine",
issue = "43122",
reason = "coroutines are unstable"
)]
pub use self::sources::from_coroutine;
#[stable(feature = "iter_empty", since = "1.2.0")]
pub use self::sources::{Empty, empty};
pub use self::sources::{FromCoroutine, from_coroutine};
#[stable(feature = "iter_from_fn", since = "1.34.0")]
pub use self::sources::{FromFn, from_fn};
#[stable(feature = "iter_once", since = "1.2.0")]

View file

@ -15,7 +15,7 @@ pub use self::empty::{Empty, empty};
issue = "43122",
reason = "coroutines are unstable"
)]
pub use self::from_coroutine::from_coroutine;
pub use self::from_coroutine::{FromCoroutine, from_coroutine};
#[stable(feature = "iter_from_fn", since = "1.34.0")]
pub use self::from_fn::{FromFn, from_fn};
#[stable(feature = "iter_once", since = "1.2.0")]

View file

@ -32,6 +32,16 @@ macro_rules! define_valid_range_type {
};
impl $name {
#[inline]
pub const fn new(val: $int) -> Option<Self> {
if (val as $uint) >= ($low as $uint) && (val as $uint) <= ($high as $uint) {
// SAFETY: just checked the inclusive range
Some(unsafe { $name(val) })
} else {
None
}
}
/// Constructs an instance of this type from the underlying integer
/// primitive without checking whether its zero.
///

View file

@ -26,3 +26,15 @@ fn test_debug_control() {
assert_eq!(want, format!("{chr:?}"), "byte: {byte}");
}
}
/// Tests Extend implementation for ascii::Char.
#[test]
fn test_extend() {
let mut s = String::from("abc");
s.extend_one(Char::SmallD);
assert_eq!(s, String::from("abcd"));
let mut s = String::from("abc");
s.extend(Char::CapitalA..=Char::CapitalC);
assert_eq!(s, String::from("abcABC"));
}

View file

@ -27,6 +27,7 @@
#![feature(duration_constructors)]
#![feature(error_generic_member_access)]
#![feature(exact_size_is_empty)]
#![feature(extend_one)]
#![feature(extern_types)]
#![feature(float_minimum_maximum)]
#![feature(flt2dec)]

View file

@ -1226,6 +1226,7 @@ impl f128 {
#[inline]
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_gamma", issue = "99842")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn gamma(self) -> f128 {
unsafe { cmath::tgammaf128(self) }
@ -1260,10 +1261,83 @@ impl f128 {
#[inline]
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_gamma", issue = "99842")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn ln_gamma(self) -> (f128, i32) {
let mut signgamp: i32 = 0;
let x = unsafe { cmath::lgammaf128_r(self, &mut signgamp) };
(x, signgamp)
}
/// Error function.
///
/// # Unspecified precision
///
/// The precision of this function is non-deterministic. This means it varies by platform,
/// Rust version, and can even differ within the same execution from one invocation to the next.
///
/// This function currently corresponds to the `erff128` from libc on Unix
/// and Windows. Note that this might change in the future.
///
/// # Examples
///
/// ```
/// #![feature(f128)]
/// #![feature(float_erf)]
/// # #[cfg(reliable_f128_math)] {
/// /// The error function relates what percent of a normal distribution lies
/// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
/// fn within_standard_deviations(x: f128) -> f128 {
/// (x * std::f128::consts::FRAC_1_SQRT_2).erf() * 100.0
/// }
///
/// // 68% of a normal distribution is within one standard deviation
/// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.01);
/// // 95% of a normal distribution is within two standard deviations
/// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.01);
/// // 99.7% of a normal distribution is within three standard deviations
/// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.01);
/// # }
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erf(self) -> f128 {
unsafe { cmath::erff128(self) }
}
/// Complementary error function.
///
/// # Unspecified precision
///
/// The precision of this function is non-deterministic. This means it varies by platform,
/// Rust version, and can even differ within the same execution from one invocation to the next.
///
/// This function currently corresponds to the `erfcf128` from libc on Unix
/// and Windows. Note that this might change in the future.
///
/// # Examples
///
/// ```
/// #![feature(f128)]
/// #![feature(float_erf)]
/// # #[cfg(reliable_f128_math)] {
/// let x: f128 = 0.123;
///
/// let one = x.erf() + x.erfc();
/// let abs_difference = (one - 1.0).abs();
///
/// assert!(abs_difference <= f128::EPSILON);
/// # }
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erfc(self) -> f128 {
unsafe { cmath::erfcf128(self) }
}
}

View file

@ -1224,6 +1224,7 @@ impl f16 {
#[inline]
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_gamma", issue = "99842")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn gamma(self) -> f16 {
(unsafe { cmath::tgammaf(self as f32) }) as f16
@ -1258,10 +1259,81 @@ impl f16 {
#[inline]
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_gamma", issue = "99842")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub fn ln_gamma(self) -> (f16, i32) {
let mut signgamp: i32 = 0;
let x = (unsafe { cmath::lgammaf_r(self as f32, &mut signgamp) }) as f16;
(x, signgamp)
}
/// Error function.
///
/// # Unspecified precision
///
/// The precision of this function is non-deterministic. This means it varies by platform,
/// Rust version, and can even differ within the same execution from one invocation to the next.
///
/// This function currently corresponds to the `erff` from libc on Unix
/// and Windows. Note that this might change in the future.
///
/// # Examples
///
/// ```
/// #![feature(f16)]
/// #![feature(float_erf)]
/// # #[cfg(reliable_f16_math)] {
/// /// The error function relates what percent of a normal distribution lies
/// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
/// fn within_standard_deviations(x: f16) -> f16 {
/// (x * std::f16::consts::FRAC_1_SQRT_2).erf() * 100.0
/// }
///
/// // 68% of a normal distribution is within one standard deviation
/// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.1);
/// // 95% of a normal distribution is within two standard deviations
/// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.1);
/// // 99.7% of a normal distribution is within three standard deviations
/// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.1);
/// # }
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erf(self) -> f16 {
(unsafe { cmath::erff(self as f32) }) as f16
}
/// Complementary error function.
///
/// # Unspecified precision
///
/// The precision of this function is non-deterministic. This means it varies by platform,
/// Rust version, and can even differ within the same execution from one invocation to the next.
///
/// This function currently corresponds to the `erfcf` from libc on Unix
/// and Windows. Note that this might change in the future.
///
/// # Examples
///
/// ```
/// #![feature(f16)]
/// #![feature(float_erf)]
/// let x: f16 = 0.123;
///
/// let one = x.erf() + x.erfc();
/// let abs_difference = (one - 1.0).abs();
///
/// assert!(abs_difference <= f16::EPSILON);
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erfc(self) -> f16 {
(unsafe { cmath::erfcf(self as f32) }) as f16
}
}

View file

@ -1151,4 +1151,68 @@ impl f32 {
let x = unsafe { cmath::lgammaf_r(self, &mut signgamp) };
(x, signgamp)
}
/// Error function.
///
/// # Unspecified precision
///
/// The precision of this function is non-deterministic. This means it varies by platform,
/// Rust version, and can even differ within the same execution from one invocation to the next.
///
/// This function currently corresponds to the `erff` from libc on Unix
/// and Windows. Note that this might change in the future.
///
/// # Examples
///
/// ```
/// #![feature(float_erf)]
/// /// The error function relates what percent of a normal distribution lies
/// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
/// fn within_standard_deviations(x: f32) -> f32 {
/// (x * std::f32::consts::FRAC_1_SQRT_2).erf() * 100.0
/// }
///
/// // 68% of a normal distribution is within one standard deviation
/// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.01);
/// // 95% of a normal distribution is within two standard deviations
/// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.01);
/// // 99.7% of a normal distribution is within three standard deviations
/// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.01);
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erf(self) -> f32 {
unsafe { cmath::erff(self) }
}
/// Complementary error function.
///
/// # Unspecified precision
///
/// The precision of this function is non-deterministic. This means it varies by platform,
/// Rust version, and can even differ within the same execution from one invocation to the next.
///
/// This function currently corresponds to the `erfcf` from libc on Unix
/// and Windows. Note that this might change in the future.
///
/// # Examples
///
/// ```
/// #![feature(float_erf)]
/// let x: f32 = 0.123;
///
/// let one = x.erf() + x.erfc();
/// let abs_difference = (one - 1.0).abs();
///
/// assert!(abs_difference <= f32::EPSILON);
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erfc(self) -> f32 {
unsafe { cmath::erfcf(self) }
}
}

View file

@ -1151,4 +1151,68 @@ impl f64 {
let x = unsafe { cmath::lgamma_r(self, &mut signgamp) };
(x, signgamp)
}
/// Error function.
///
/// # Unspecified precision
///
/// The precision of this function is non-deterministic. This means it varies by platform,
/// Rust version, and can even differ within the same execution from one invocation to the next.
///
/// This function currently corresponds to the `erf` from libc on Unix
/// and Windows. Note that this might change in the future.
///
/// # Examples
///
/// ```
/// #![feature(float_erf)]
/// /// The error function relates what percent of a normal distribution lies
/// /// within `x` standard deviations (scaled by `1/sqrt(2)`).
/// fn within_standard_deviations(x: f64) -> f64 {
/// (x * std::f64::consts::FRAC_1_SQRT_2).erf() * 100.0
/// }
///
/// // 68% of a normal distribution is within one standard deviation
/// assert!((within_standard_deviations(1.0) - 68.269).abs() < 0.01);
/// // 95% of a normal distribution is within two standard deviations
/// assert!((within_standard_deviations(2.0) - 95.450).abs() < 0.01);
/// // 99.7% of a normal distribution is within three standard deviations
/// assert!((within_standard_deviations(3.0) - 99.730).abs() < 0.01);
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erf(self) -> f64 {
unsafe { cmath::erf(self) }
}
/// Complementary error function.
///
/// # Unspecified precision
///
/// The precision of this function is non-deterministic. This means it varies by platform,
/// Rust version, and can even differ within the same execution from one invocation to the next.
///
/// This function currently corresponds to the `erfc` from libc on Unix
/// and Windows. Note that this might change in the future.
///
/// # Examples
///
/// ```
/// #![feature(float_erf)]
/// let x: f64 = 0.123;
///
/// let one = x.erf() + x.erfc();
/// let abs_difference = (one - 1.0).abs();
///
/// assert!(abs_difference <= f64::EPSILON);
/// ```
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "float_erf", issue = "136321")]
#[inline]
pub fn erfc(self) -> f64 {
unsafe { cmath::erfc(self) }
}
}

View file

@ -45,6 +45,7 @@ impl<R: Read + ?Sized> Read for &mut R {
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
(**self).read_exact(buf)
}
#[inline]
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
(**self).read_buf_exact(cursor)
@ -77,6 +78,11 @@ impl<W: Write + ?Sized> Write for &mut W {
(**self).write_all(buf)
}
#[inline]
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
(**self).write_all_vectored(bufs)
}
#[inline]
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
(**self).write_fmt(fmt)
@ -89,10 +95,25 @@ impl<S: Seek + ?Sized> Seek for &mut S {
(**self).seek(pos)
}
#[inline]
fn rewind(&mut self) -> io::Result<()> {
(**self).rewind()
}
#[inline]
fn stream_len(&mut self) -> io::Result<u64> {
(**self).stream_len()
}
#[inline]
fn stream_position(&mut self) -> io::Result<u64> {
(**self).stream_position()
}
#[inline]
fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
(**self).seek_relative(offset)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead + ?Sized> BufRead for &mut B {
@ -106,11 +127,21 @@ impl<B: BufRead + ?Sized> BufRead for &mut B {
(**self).consume(amt)
}
#[inline]
fn has_data_left(&mut self) -> io::Result<bool> {
(**self).has_data_left()
}
#[inline]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
(**self).read_until(byte, buf)
}
#[inline]
fn skip_until(&mut self, byte: u8) -> io::Result<usize> {
(**self).skip_until(byte)
}
#[inline]
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
(**self).read_line(buf)
@ -153,6 +184,7 @@ impl<R: Read + ?Sized> Read for Box<R> {
fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
(**self).read_exact(buf)
}
#[inline]
fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
(**self).read_buf_exact(cursor)
@ -185,6 +217,11 @@ impl<W: Write + ?Sized> Write for Box<W> {
(**self).write_all(buf)
}
#[inline]
fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
(**self).write_all_vectored(bufs)
}
#[inline]
fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
(**self).write_fmt(fmt)
@ -197,10 +234,25 @@ impl<S: Seek + ?Sized> Seek for Box<S> {
(**self).seek(pos)
}
#[inline]
fn rewind(&mut self) -> io::Result<()> {
(**self).rewind()
}
#[inline]
fn stream_len(&mut self) -> io::Result<u64> {
(**self).stream_len()
}
#[inline]
fn stream_position(&mut self) -> io::Result<u64> {
(**self).stream_position()
}
#[inline]
fn seek_relative(&mut self, offset: i64) -> io::Result<()> {
(**self).seek_relative(offset)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead + ?Sized> BufRead for Box<B> {
@ -214,11 +266,21 @@ impl<B: BufRead + ?Sized> BufRead for Box<B> {
(**self).consume(amt)
}
#[inline]
fn has_data_left(&mut self) -> io::Result<bool> {
(**self).has_data_left()
}
#[inline]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
(**self).read_until(byte, buf)
}
#[inline]
fn skip_until(&mut self, byte: u8) -> io::Result<usize> {
(**self).skip_until(byte)
}
#[inline]
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
(**self).read_line(buf)

View file

@ -67,13 +67,11 @@ impl BorrowedFd<'_> {
/// The resource pointed to by `fd` must remain open for the duration of
/// the returned `BorrowedFd`, and it must not have the value `-1`.
#[inline]
#[track_caller]
#[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
#[stable(feature = "io_safety", since = "1.63.0")]
pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
assert!(fd != u32::MAX as RawFd);
// SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
let fd = unsafe { ValidRawFd::new_unchecked(fd) };
Self { fd, _phantom: PhantomData }
Self { fd: ValidRawFd::new(fd).expect("fd != -1"), _phantom: PhantomData }
}
}
@ -154,11 +152,9 @@ impl FromRawFd for OwnedFd {
///
/// [io-safety]: io#io-safety
#[inline]
#[track_caller]
unsafe fn from_raw_fd(fd: RawFd) -> Self {
assert_ne!(fd, u32::MAX as RawFd);
// SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
let fd = unsafe { ValidRawFd::new_unchecked(fd) };
Self { fd }
Self { fd: ValidRawFd::new(fd).expect("fd != -1") }
}
}

View file

@ -101,12 +101,9 @@ impl BorrowedFd<'_> {
/// the returned `BorrowedFd`, and it must not have the value
/// `SOLID_NET_INVALID_FD`.
#[inline]
#[track_caller]
pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
assert!(fd != -1 as RawFd);
// SAFETY: we just asserted that the value is in the valid range and
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
let fd = unsafe { ValidRawFd::new_unchecked(fd) };
Self { fd, _phantom: PhantomData }
Self { fd: ValidRawFd::new(fd).expect("fd != -1"), _phantom: PhantomData }
}
}
@ -156,12 +153,9 @@ impl FromRawFd for OwnedFd {
/// The resource pointed to by `fd` must be open and suitable for assuming
/// ownership. The resource must not require any cleanup other than `close`.
#[inline]
#[track_caller]
unsafe fn from_raw_fd(fd: RawFd) -> Self {
assert_ne!(fd, -1 as RawFd);
// SAFETY: we just asserted that the value is in the valid range and
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
let fd = unsafe { ValidRawFd::new_unchecked(fd) };
Self { fd }
Self { fd: ValidRawFd::new(fd).expect("fd != -1") }
}
}

View file

@ -58,12 +58,11 @@ impl BorrowedSocket<'_> {
/// the returned `BorrowedSocket`, and it must not have the value
/// `INVALID_SOCKET`.
#[inline]
#[track_caller]
#[rustc_const_stable(feature = "io_safety", since = "1.63.0")]
#[stable(feature = "io_safety", since = "1.63.0")]
pub const unsafe fn borrow_raw(socket: RawSocket) -> Self {
assert!(socket != sys::c::INVALID_SOCKET as RawSocket);
let socket = unsafe { ValidRawSocket::new_unchecked(socket) };
Self { socket, _phantom: PhantomData }
Self { socket: ValidRawSocket::new(socket).expect("socket != -1"), _phantom: PhantomData }
}
}
@ -185,10 +184,9 @@ impl IntoRawSocket for OwnedSocket {
#[stable(feature = "io_safety", since = "1.63.0")]
impl FromRawSocket for OwnedSocket {
#[inline]
#[track_caller]
unsafe fn from_raw_socket(socket: RawSocket) -> Self {
debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket);
let socket = unsafe { ValidRawSocket::new_unchecked(socket) };
Self { socket }
Self { socket: ValidRawSocket::new(socket).expect("socket != -1") }
}
}

View file

@ -28,6 +28,10 @@ unsafe extern "C" {
pub fn lgamma_r(n: f64, s: &mut i32) -> f64;
#[cfg(not(target_os = "aix"))]
pub fn lgammaf_r(n: f32, s: &mut i32) -> f32;
pub fn erf(n: f64) -> f64;
pub fn erff(n: f32) -> f32;
pub fn erfc(n: f64) -> f64;
pub fn erfcf(n: f32) -> f32;
pub fn acosf128(n: f128) -> f128;
pub fn asinf128(n: f128) -> f128;
@ -43,6 +47,8 @@ unsafe extern "C" {
pub fn tanhf128(n: f128) -> f128;
pub fn tgammaf128(n: f128) -> f128;
pub fn lgammaf128_r(n: f128, s: &mut i32) -> f128;
pub fn erff128(n: f128) -> f128;
pub fn erfcf128(n: f128) -> f128;
cfg_if::cfg_if! {
if #[cfg(not(all(target_os = "windows", target_env = "msvc", target_arch = "x86")))] {

View file

@ -22,12 +22,9 @@ struct FileDesc {
impl FileDesc {
#[inline]
#[track_caller]
fn new(fd: c_int) -> FileDesc {
assert_ne!(fd, -1i32);
// Safety: we just asserted that the value is in the valid range and
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
let fd = unsafe { CIntNotMinusOne::new_unchecked(fd) };
FileDesc { fd }
FileDesc { fd: CIntNotMinusOne::new(fd).expect("fd != -1") }
}
#[inline]

File diff suppressed because it is too large Load diff

View file

@ -1,15 +1,14 @@
// Bindings generated by `windows-bindgen` 0.58.0
// Bindings generated by `windows-bindgen` 0.59.0
#![allow(non_snake_case, non_upper_case_globals, non_camel_case_types, dead_code, clippy::all)]
windows_targets::link!("advapi32.dll" "system" fn OpenProcessToken(processhandle : HANDLE, desiredaccess : TOKEN_ACCESS_MASK, tokenhandle : *mut HANDLE) -> BOOL);
windows_targets::link!("advapi32.dll" "system" "SystemFunction036" fn RtlGenRandom(randombuffer : *mut core::ffi::c_void, randombufferlength : u32) -> BOOLEAN);
windows_targets::link!("kernel32.dll" "system" fn AcquireSRWLockExclusive(srwlock : *mut SRWLOCK));
windows_targets::link!("kernel32.dll" "system" fn AcquireSRWLockShared(srwlock : *mut SRWLOCK));
windows_targets::link!("kernel32.dll" "system" fn AddVectoredExceptionHandler(first : u32, handler : PVECTORED_EXCEPTION_HANDLER) -> *mut core::ffi::c_void);
windows_targets::link!("kernel32.dll" "system" fn CancelIo(hfile : HANDLE) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn CloseHandle(hobject : HANDLE) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn CompareStringOrdinal(lpstring1 : PCWSTR, cchcount1 : i32, lpstring2 : PCWSTR, cchcount2 : i32, bignorecase : BOOL) -> COMPARESTRING_RESULT);
windows_targets::link!("kernel32.dll" "system" fn CopyFileExW(lpexistingfilename : PCWSTR, lpnewfilename : PCWSTR, lpprogressroutine : LPPROGRESS_ROUTINE, lpdata : *const core::ffi::c_void, pbcancel : *mut BOOL, dwcopyflags : u32) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn CopyFileExW(lpexistingfilename : PCWSTR, lpnewfilename : PCWSTR, lpprogressroutine : LPPROGRESS_ROUTINE, lpdata : *const core::ffi::c_void, pbcancel : *mut BOOL, dwcopyflags : COPYFILE_FLAGS) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn CreateDirectoryW(lppathname : PCWSTR, lpsecurityattributes : *const SECURITY_ATTRIBUTES) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn CreateEventW(lpeventattributes : *const SECURITY_ATTRIBUTES, bmanualreset : BOOL, binitialstate : BOOL, lpname : PCWSTR) -> HANDLE);
windows_targets::link!("kernel32.dll" "system" fn CreateFileW(lpfilename : PCWSTR, dwdesiredaccess : u32, dwsharemode : FILE_SHARE_MODE, lpsecurityattributes : *const SECURITY_ATTRIBUTES, dwcreationdisposition : FILE_CREATION_DISPOSITION, dwflagsandattributes : FILE_FLAGS_AND_ATTRIBUTES, htemplatefile : HANDLE) -> HANDLE);
@ -17,7 +16,7 @@ windows_targets::link!("kernel32.dll" "system" fn CreateHardLinkW(lpfilename : P
windows_targets::link!("kernel32.dll" "system" fn CreateNamedPipeW(lpname : PCWSTR, dwopenmode : FILE_FLAGS_AND_ATTRIBUTES, dwpipemode : NAMED_PIPE_MODE, nmaxinstances : u32, noutbuffersize : u32, ninbuffersize : u32, ndefaulttimeout : u32, lpsecurityattributes : *const SECURITY_ATTRIBUTES) -> HANDLE);
windows_targets::link!("kernel32.dll" "system" fn CreatePipe(hreadpipe : *mut HANDLE, hwritepipe : *mut HANDLE, lppipeattributes : *const SECURITY_ATTRIBUTES, nsize : u32) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn CreateProcessW(lpapplicationname : PCWSTR, lpcommandline : PWSTR, lpprocessattributes : *const SECURITY_ATTRIBUTES, lpthreadattributes : *const SECURITY_ATTRIBUTES, binherithandles : BOOL, dwcreationflags : PROCESS_CREATION_FLAGS, lpenvironment : *const core::ffi::c_void, lpcurrentdirectory : PCWSTR, lpstartupinfo : *const STARTUPINFOW, lpprocessinformation : *mut PROCESS_INFORMATION) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn CreateSymbolicLinkW(lpsymlinkfilename : PCWSTR, lptargetfilename : PCWSTR, dwflags : SYMBOLIC_LINK_FLAGS) -> BOOLEAN);
windows_targets::link!("kernel32.dll" "system" fn CreateSymbolicLinkW(lpsymlinkfilename : PCWSTR, lptargetfilename : PCWSTR, dwflags : SYMBOLIC_LINK_FLAGS) -> bool);
windows_targets::link!("kernel32.dll" "system" fn CreateThread(lpthreadattributes : *const SECURITY_ATTRIBUTES, dwstacksize : usize, lpstartaddress : LPTHREAD_START_ROUTINE, lpparameter : *const core::ffi::c_void, dwcreationflags : THREAD_CREATION_FLAGS, lpthreadid : *mut u32) -> HANDLE);
windows_targets::link!("kernel32.dll" "system" fn CreateWaitableTimerExW(lptimerattributes : *const SECURITY_ATTRIBUTES, lptimername : PCWSTR, dwflags : u32, dwdesiredaccess : u32) -> HANDLE);
windows_targets::link!("kernel32.dll" "system" fn DeleteFileW(lpfilename : PCWSTR) -> BOOL);
@ -61,6 +60,7 @@ windows_targets::link!("kernel32.dll" "system" fn GetSystemInfo(lpsysteminfo : *
windows_targets::link!("kernel32.dll" "system" fn GetSystemTimeAsFileTime(lpsystemtimeasfiletime : *mut FILETIME));
windows_targets::link!("kernel32.dll" "system" fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime : *mut FILETIME));
windows_targets::link!("kernel32.dll" "system" fn GetTempPathW(nbufferlength : u32, lpbuffer : PWSTR) -> u32);
windows_targets::link!("userenv.dll" "system" fn GetUserProfileDirectoryW(htoken : HANDLE, lpprofiledir : PWSTR, lpcchsize : *mut u32) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn GetWindowsDirectoryW(lpbuffer : PWSTR, usize : u32) -> u32);
windows_targets::link!("kernel32.dll" "system" fn InitOnceBeginInitialize(lpinitonce : *mut INIT_ONCE, dwflags : u32, fpending : *mut BOOL, lpcontext : *mut *mut core::ffi::c_void) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn InitOnceComplete(lpinitonce : *mut INIT_ONCE, dwflags : u32, lpcontext : *const core::ffi::c_void) -> BOOL);
@ -69,6 +69,11 @@ windows_targets::link!("kernel32.dll" "system" fn LocalFree(hmem : HLOCAL) -> HL
windows_targets::link!("kernel32.dll" "system" fn LockFileEx(hfile : HANDLE, dwflags : LOCK_FILE_FLAGS, dwreserved : u32, nnumberofbytestolocklow : u32, nnumberofbytestolockhigh : u32, lpoverlapped : *mut OVERLAPPED) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn MoveFileExW(lpexistingfilename : PCWSTR, lpnewfilename : PCWSTR, dwflags : MOVE_FILE_FLAGS) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn MultiByteToWideChar(codepage : u32, dwflags : MULTI_BYTE_TO_WIDE_CHAR_FLAGS, lpmultibytestr : PCSTR, cbmultibyte : i32, lpwidecharstr : PWSTR, cchwidechar : i32) -> i32);
windows_targets::link!("ntdll.dll" "system" fn NtCreateFile(filehandle : *mut HANDLE, desiredaccess : FILE_ACCESS_RIGHTS, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, allocationsize : *const i64, fileattributes : FILE_FLAGS_AND_ATTRIBUTES, shareaccess : FILE_SHARE_MODE, createdisposition : NTCREATEFILE_CREATE_DISPOSITION, createoptions : NTCREATEFILE_CREATE_OPTIONS, eabuffer : *const core::ffi::c_void, ealength : u32) -> NTSTATUS);
windows_targets::link!("ntdll.dll" "system" fn NtOpenFile(filehandle : *mut HANDLE, desiredaccess : u32, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, shareaccess : u32, openoptions : u32) -> NTSTATUS);
windows_targets::link!("ntdll.dll" "system" fn NtReadFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *mut core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS);
windows_targets::link!("ntdll.dll" "system" fn NtWriteFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *const core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS);
windows_targets::link!("advapi32.dll" "system" fn OpenProcessToken(processhandle : HANDLE, desiredaccess : TOKEN_ACCESS_MASK, tokenhandle : *mut HANDLE) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn QueryPerformanceCounter(lpperformancecount : *mut i64) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn QueryPerformanceFrequency(lpfrequency : *mut i64) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn ReadConsoleW(hconsoleinput : HANDLE, lpbuffer : *mut core::ffi::c_void, nnumberofcharstoread : u32, lpnumberofcharsread : *mut u32, pinputcontrol : *const CONSOLE_READCONSOLE_CONTROL) -> BOOL);
@ -77,6 +82,8 @@ windows_targets::link!("kernel32.dll" "system" fn ReadFileEx(hfile : HANDLE, lpb
windows_targets::link!("kernel32.dll" "system" fn ReleaseSRWLockExclusive(srwlock : *mut SRWLOCK));
windows_targets::link!("kernel32.dll" "system" fn ReleaseSRWLockShared(srwlock : *mut SRWLOCK));
windows_targets::link!("kernel32.dll" "system" fn RemoveDirectoryW(lppathname : PCWSTR) -> BOOL);
windows_targets::link!("advapi32.dll" "system" "SystemFunction036" fn RtlGenRandom(randombuffer : *mut core::ffi::c_void, randombufferlength : u32) -> bool);
windows_targets::link!("ntdll.dll" "system" fn RtlNtStatusToDosError(status : NTSTATUS) -> u32);
windows_targets::link!("kernel32.dll" "system" fn SetCurrentDirectoryW(lppathname : PCWSTR) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn SetEnvironmentVariableW(lpname : PCWSTR, lpvalue : PCWSTR) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn SetFileAttributesW(lpfilename : PCWSTR, dwfileattributes : FILE_FLAGS_AND_ATTRIBUTES) -> BOOL);
@ -96,23 +103,10 @@ windows_targets::link!("kernel32.dll" "system" fn TlsAlloc() -> u32);
windows_targets::link!("kernel32.dll" "system" fn TlsFree(dwtlsindex : u32) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn TlsGetValue(dwtlsindex : u32) -> *mut core::ffi::c_void);
windows_targets::link!("kernel32.dll" "system" fn TlsSetValue(dwtlsindex : u32, lptlsvalue : *const core::ffi::c_void) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn TryAcquireSRWLockExclusive(srwlock : *mut SRWLOCK) -> BOOLEAN);
windows_targets::link!("kernel32.dll" "system" fn TryAcquireSRWLockShared(srwlock : *mut SRWLOCK) -> BOOLEAN);
windows_targets::link!("kernel32.dll" "system" fn TryAcquireSRWLockExclusive(srwlock : *mut SRWLOCK) -> bool);
windows_targets::link!("kernel32.dll" "system" fn TryAcquireSRWLockShared(srwlock : *mut SRWLOCK) -> bool);
windows_targets::link!("kernel32.dll" "system" fn UnlockFile(hfile : HANDLE, dwfileoffsetlow : u32, dwfileoffsethigh : u32, nnumberofbytestounlocklow : u32, nnumberofbytestounlockhigh : u32) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn UpdateProcThreadAttribute(lpattributelist : LPPROC_THREAD_ATTRIBUTE_LIST, dwflags : u32, attribute : usize, lpvalue : *const core::ffi::c_void, cbsize : usize, lppreviousvalue : *mut core::ffi::c_void, lpreturnsize : *const usize) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn WaitForMultipleObjects(ncount : u32, lphandles : *const HANDLE, bwaitall : BOOL, dwmilliseconds : u32) -> WAIT_EVENT);
windows_targets::link!("kernel32.dll" "system" fn WaitForSingleObject(hhandle : HANDLE, dwmilliseconds : u32) -> WAIT_EVENT);
windows_targets::link!("kernel32.dll" "system" fn WakeAllConditionVariable(conditionvariable : *mut CONDITION_VARIABLE));
windows_targets::link!("kernel32.dll" "system" fn WakeConditionVariable(conditionvariable : *mut CONDITION_VARIABLE));
windows_targets::link!("kernel32.dll" "system" fn WideCharToMultiByte(codepage : u32, dwflags : u32, lpwidecharstr : PCWSTR, cchwidechar : i32, lpmultibytestr : PSTR, cbmultibyte : i32, lpdefaultchar : PCSTR, lpuseddefaultchar : *mut BOOL) -> i32);
windows_targets::link!("kernel32.dll" "system" fn WriteConsoleW(hconsoleoutput : HANDLE, lpbuffer : PCWSTR, nnumberofcharstowrite : u32, lpnumberofcharswritten : *mut u32, lpreserved : *const core::ffi::c_void) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn WriteFileEx(hfile : HANDLE, lpbuffer : *const u8, nnumberofbytestowrite : u32, lpoverlapped : *mut OVERLAPPED, lpcompletionroutine : LPOVERLAPPED_COMPLETION_ROUTINE) -> BOOL);
windows_targets::link!("ntdll.dll" "system" fn NtCreateFile(filehandle : *mut HANDLE, desiredaccess : FILE_ACCESS_RIGHTS, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, allocationsize : *const i64, fileattributes : FILE_FLAGS_AND_ATTRIBUTES, shareaccess : FILE_SHARE_MODE, createdisposition : NTCREATEFILE_CREATE_DISPOSITION, createoptions : NTCREATEFILE_CREATE_OPTIONS, eabuffer : *const core::ffi::c_void, ealength : u32) -> NTSTATUS);
windows_targets::link!("ntdll.dll" "system" fn NtOpenFile(filehandle : *mut HANDLE, desiredaccess : u32, objectattributes : *const OBJECT_ATTRIBUTES, iostatusblock : *mut IO_STATUS_BLOCK, shareaccess : u32, openoptions : u32) -> NTSTATUS);
windows_targets::link!("ntdll.dll" "system" fn NtReadFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *mut core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS);
windows_targets::link!("ntdll.dll" "system" fn NtWriteFile(filehandle : HANDLE, event : HANDLE, apcroutine : PIO_APC_ROUTINE, apccontext : *const core::ffi::c_void, iostatusblock : *mut IO_STATUS_BLOCK, buffer : *const core::ffi::c_void, length : u32, byteoffset : *const i64, key : *const u32) -> NTSTATUS);
windows_targets::link!("ntdll.dll" "system" fn RtlNtStatusToDosError(status : NTSTATUS) -> u32);
windows_targets::link!("userenv.dll" "system" fn GetUserProfileDirectoryW(htoken : HANDLE, lpprofiledir : PWSTR, lpcchsize : *mut u32) -> BOOL);
windows_targets::link!("ws2_32.dll" "system" fn WSACleanup() -> i32);
windows_targets::link!("ws2_32.dll" "system" fn WSADuplicateSocketW(s : SOCKET, dwprocessid : u32, lpprotocolinfo : *mut WSAPROTOCOL_INFOW) -> i32);
windows_targets::link!("ws2_32.dll" "system" fn WSAGetLastError() -> WSA_ERROR);
@ -120,6 +114,13 @@ windows_targets::link!("ws2_32.dll" "system" fn WSARecv(s : SOCKET, lpbuffers :
windows_targets::link!("ws2_32.dll" "system" fn WSASend(s : SOCKET, lpbuffers : *const WSABUF, dwbuffercount : u32, lpnumberofbytessent : *mut u32, dwflags : u32, lpoverlapped : *mut OVERLAPPED, lpcompletionroutine : LPWSAOVERLAPPED_COMPLETION_ROUTINE) -> i32);
windows_targets::link!("ws2_32.dll" "system" fn WSASocketW(af : i32, r#type : i32, protocol : i32, lpprotocolinfo : *const WSAPROTOCOL_INFOW, g : u32, dwflags : u32) -> SOCKET);
windows_targets::link!("ws2_32.dll" "system" fn WSAStartup(wversionrequested : u16, lpwsadata : *mut WSADATA) -> i32);
windows_targets::link!("kernel32.dll" "system" fn WaitForMultipleObjects(ncount : u32, lphandles : *const HANDLE, bwaitall : BOOL, dwmilliseconds : u32) -> WAIT_EVENT);
windows_targets::link!("kernel32.dll" "system" fn WaitForSingleObject(hhandle : HANDLE, dwmilliseconds : u32) -> WAIT_EVENT);
windows_targets::link!("kernel32.dll" "system" fn WakeAllConditionVariable(conditionvariable : *mut CONDITION_VARIABLE));
windows_targets::link!("kernel32.dll" "system" fn WakeConditionVariable(conditionvariable : *mut CONDITION_VARIABLE));
windows_targets::link!("kernel32.dll" "system" fn WideCharToMultiByte(codepage : u32, dwflags : u32, lpwidecharstr : PCWSTR, cchwidechar : i32, lpmultibytestr : PSTR, cbmultibyte : i32, lpdefaultchar : PCSTR, lpuseddefaultchar : *mut BOOL) -> i32);
windows_targets::link!("kernel32.dll" "system" fn WriteConsoleW(hconsoleoutput : HANDLE, lpbuffer : PCWSTR, nnumberofcharstowrite : u32, lpnumberofcharswritten : *mut u32, lpreserved : *const core::ffi::c_void) -> BOOL);
windows_targets::link!("kernel32.dll" "system" fn WriteFileEx(hfile : HANDLE, lpbuffer : *const u8, nnumberofbytestowrite : u32, lpoverlapped : *mut OVERLAPPED, lpcompletionroutine : LPOVERLAPPED_COMPLETION_ROUTINE) -> BOOL);
windows_targets::link!("ws2_32.dll" "system" fn accept(s : SOCKET, addr : *mut SOCKADDR, addrlen : *mut i32) -> SOCKET);
windows_targets::link!("ws2_32.dll" "system" fn bind(s : SOCKET, name : *const SOCKADDR, namelen : i32) -> i32);
windows_targets::link!("ws2_32.dll" "system" fn closesocket(s : SOCKET) -> i32);
@ -139,6 +140,15 @@ windows_targets::link!("ws2_32.dll" "system" fn sendto(s : SOCKET, buf : PCSTR,
windows_targets::link!("ws2_32.dll" "system" fn setsockopt(s : SOCKET, level : i32, optname : i32, optval : PCSTR, optlen : i32) -> i32);
windows_targets::link!("ws2_32.dll" "system" fn shutdown(s : SOCKET, how : WINSOCK_SHUTDOWN_HOW) -> i32);
pub const ABOVE_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 32768u32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct ACL {
pub AclRevision: u8,
pub Sbz1: u8,
pub AclSize: u16,
pub AceCount: u16,
pub Sbz2: u16,
}
pub type ADDRESS_FAMILY = u16;
#[repr(C)]
#[derive(Clone, Copy)]
@ -174,7 +184,6 @@ pub struct ARM64_NT_NEON128_0 {
}
pub const BELOW_NORMAL_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 16384u32;
pub type BOOL = i32;
pub type BOOLEAN = u8;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct BY_HANDLE_FILE_INFORMATION {
@ -207,64 +216,34 @@ pub struct CONSOLE_READCONSOLE_CONTROL {
pub dwControlKeyState: u32,
}
#[repr(C)]
#[cfg(target_arch = "aarch64")]
#[cfg(target_arch = "x86")]
#[derive(Clone, Copy)]
pub struct CONTEXT {
pub ContextFlags: CONTEXT_FLAGS,
pub Cpsr: u32,
pub Anonymous: CONTEXT_0,
pub Sp: u64,
pub Pc: u64,
pub V: [ARM64_NT_NEON128; 32],
pub Fpcr: u32,
pub Fpsr: u32,
pub Bcr: [u32; 8],
pub Bvr: [u64; 8],
pub Wcr: [u32; 2],
pub Wvr: [u64; 2],
}
#[repr(C)]
#[cfg(target_arch = "aarch64")]
#[derive(Clone, Copy)]
pub union CONTEXT_0 {
pub Anonymous: CONTEXT_0_0,
pub X: [u64; 31],
}
#[repr(C)]
#[cfg(target_arch = "aarch64")]
#[derive(Clone, Copy)]
pub struct CONTEXT_0_0 {
pub X0: u64,
pub X1: u64,
pub X2: u64,
pub X3: u64,
pub X4: u64,
pub X5: u64,
pub X6: u64,
pub X7: u64,
pub X8: u64,
pub X9: u64,
pub X10: u64,
pub X11: u64,
pub X12: u64,
pub X13: u64,
pub X14: u64,
pub X15: u64,
pub X16: u64,
pub X17: u64,
pub X18: u64,
pub X19: u64,
pub X20: u64,
pub X21: u64,
pub X22: u64,
pub X23: u64,
pub X24: u64,
pub X25: u64,
pub X26: u64,
pub X27: u64,
pub X28: u64,
pub Fp: u64,
pub Lr: u64,
pub Dr0: u32,
pub Dr1: u32,
pub Dr2: u32,
pub Dr3: u32,
pub Dr6: u32,
pub Dr7: u32,
pub FloatSave: FLOATING_SAVE_AREA,
pub SegGs: u32,
pub SegFs: u32,
pub SegEs: u32,
pub SegDs: u32,
pub Edi: u32,
pub Esi: u32,
pub Ebx: u32,
pub Edx: u32,
pub Ecx: u32,
pub Eax: u32,
pub Ebp: u32,
pub Eip: u32,
pub SegCs: u32,
pub EFlags: u32,
pub Esp: u32,
pub SegSs: u32,
pub ExtendedRegisters: [u8; 512],
}
#[repr(C)]
#[cfg(any(target_arch = "arm64ec", target_arch = "x86_64"))]
@ -348,36 +327,68 @@ pub struct CONTEXT_0_0 {
pub Xmm15: M128A,
}
#[repr(C)]
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "aarch64")]
#[derive(Clone, Copy)]
pub struct CONTEXT {
pub ContextFlags: CONTEXT_FLAGS,
pub Dr0: u32,
pub Dr1: u32,
pub Dr2: u32,
pub Dr3: u32,
pub Dr6: u32,
pub Dr7: u32,
pub FloatSave: FLOATING_SAVE_AREA,
pub SegGs: u32,
pub SegFs: u32,
pub SegEs: u32,
pub SegDs: u32,
pub Edi: u32,
pub Esi: u32,
pub Ebx: u32,
pub Edx: u32,
pub Ecx: u32,
pub Eax: u32,
pub Ebp: u32,
pub Eip: u32,
pub SegCs: u32,
pub EFlags: u32,
pub Esp: u32,
pub SegSs: u32,
pub ExtendedRegisters: [u8; 512],
pub Cpsr: u32,
pub Anonymous: CONTEXT_0,
pub Sp: u64,
pub Pc: u64,
pub V: [ARM64_NT_NEON128; 32],
pub Fpcr: u32,
pub Fpsr: u32,
pub Bcr: [u32; 8],
pub Bvr: [u64; 8],
pub Wcr: [u32; 2],
pub Wvr: [u64; 2],
}
#[repr(C)]
#[cfg(target_arch = "aarch64")]
#[derive(Clone, Copy)]
pub union CONTEXT_0 {
pub Anonymous: CONTEXT_0_0,
pub X: [u64; 31],
}
#[repr(C)]
#[cfg(target_arch = "aarch64")]
#[derive(Clone, Copy)]
pub struct CONTEXT_0_0 {
pub X0: u64,
pub X1: u64,
pub X2: u64,
pub X3: u64,
pub X4: u64,
pub X5: u64,
pub X6: u64,
pub X7: u64,
pub X8: u64,
pub X9: u64,
pub X10: u64,
pub X11: u64,
pub X12: u64,
pub X13: u64,
pub X14: u64,
pub X15: u64,
pub X16: u64,
pub X17: u64,
pub X18: u64,
pub X19: u64,
pub X20: u64,
pub X21: u64,
pub X22: u64,
pub X23: u64,
pub X24: u64,
pub X25: u64,
pub X26: u64,
pub X27: u64,
pub X28: u64,
pub Fp: u64,
pub Lr: u64,
}
pub type CONTEXT_FLAGS = u32;
pub type COPYFILE_FLAGS = u32;
pub type COPYPROGRESSROUTINE_PROGRESS = u32;
pub const CP_UTF8: u32 = 65001u32;
pub const CREATE_ALWAYS: FILE_CREATION_DISPOSITION = 2u32;
pub const CREATE_BREAKAWAY_FROM_JOB: PROCESS_CREATION_FLAGS = 16777216u32;
@ -2396,7 +2407,7 @@ pub const FILE_DISPOSITION_FLAG_POSIX_SEMANTICS: FILE_DISPOSITION_INFO_EX_FLAGS
#[repr(C)]
#[derive(Clone, Copy)]
pub struct FILE_DISPOSITION_INFO {
pub DeleteFile: BOOLEAN,
pub DeleteFile: bool,
}
#[repr(C)]
#[derive(Clone, Copy)]
@ -2486,7 +2497,7 @@ pub struct FILE_RENAME_INFO {
#[repr(C)]
#[derive(Clone, Copy)]
pub union FILE_RENAME_INFO_0 {
pub ReplaceIfExists: BOOLEAN,
pub ReplaceIfExists: bool,
pub Flags: u32,
}
pub const FILE_RESERVE_OPFILTER: NTCREATEFILE_CREATE_OPTIONS = 1048576u32;
@ -2503,8 +2514,8 @@ pub struct FILE_STANDARD_INFO {
pub AllocationSize: i64,
pub EndOfFile: i64,
pub NumberOfLinks: u32,
pub DeletePending: BOOLEAN,
pub Directory: BOOLEAN,
pub DeletePending: bool,
pub Directory: bool,
}
pub const FILE_SUPERSEDE: NTCREATEFILE_CREATE_DISPOSITION = 0u32;
pub const FILE_SYNCHRONOUS_IO_ALERT: NTCREATEFILE_CREATE_OPTIONS = 16u32;
@ -2525,20 +2536,6 @@ pub type FINDEX_SEARCH_OPS = i32;
pub type FIND_FIRST_EX_FLAGS = u32;
pub const FIONBIO: i32 = -2147195266i32;
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
pub struct FLOATING_SAVE_AREA {
pub ControlWord: u32,
pub StatusWord: u32,
pub TagWord: u32,
pub ErrorOffset: u32,
pub ErrorSelector: u32,
pub DataOffset: u32,
pub DataSelector: u32,
pub RegisterArea: [u8; 80],
pub Cr0NpxState: u32,
}
#[repr(C)]
#[cfg(target_arch = "x86")]
#[derive(Clone, Copy)]
pub struct FLOATING_SAVE_AREA {
@ -2552,6 +2549,20 @@ pub struct FLOATING_SAVE_AREA {
pub RegisterArea: [u8; 80],
pub Spare0: u32,
}
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
pub struct FLOATING_SAVE_AREA {
pub ControlWord: u32,
pub StatusWord: u32,
pub TagWord: u32,
pub ErrorOffset: u32,
pub ErrorSelector: u32,
pub DataOffset: u32,
pub DataSelector: u32,
pub RegisterArea: [u8; 80],
pub Cr0NpxState: u32,
}
pub const FORMAT_MESSAGE_ALLOCATE_BUFFER: FORMAT_MESSAGE_OPTIONS = 256u32;
pub const FORMAT_MESSAGE_ARGUMENT_ARRAY: FORMAT_MESSAGE_OPTIONS = 8192u32;
pub const FORMAT_MESSAGE_FROM_HMODULE: FORMAT_MESSAGE_OPTIONS = 2048u32;
@ -2618,6 +2629,7 @@ pub type HANDLE_FLAGS = u32;
pub const HANDLE_FLAG_INHERIT: HANDLE_FLAGS = 1u32;
pub const HANDLE_FLAG_PROTECT_FROM_CLOSE: HANDLE_FLAGS = 2u32;
pub const HIGH_PRIORITY_CLASS: PROCESS_CREATION_FLAGS = 128u32;
pub type HINSTANCE = *mut core::ffi::c_void;
pub type HLOCAL = *mut core::ffi::c_void;
pub type HMODULE = *mut core::ffi::c_void;
pub type HRESULT = i32;
@ -2771,7 +2783,7 @@ pub type LPPROGRESS_ROUTINE = Option<
hsourcefile: HANDLE,
hdestinationfile: HANDLE,
lpdata: *const core::ffi::c_void,
) -> u32,
) -> COPYPROGRESSROUTINE_PROGRESS,
>;
pub type LPPROGRESS_ROUTINE_CALLBACK_REASON = u32;
pub type LPTHREAD_START_ROUTINE =
@ -2822,11 +2834,12 @@ pub struct OBJECT_ATTRIBUTES {
pub Length: u32,
pub RootDirectory: HANDLE,
pub ObjectName: *const UNICODE_STRING,
pub Attributes: u32,
pub SecurityDescriptor: *const core::ffi::c_void,
pub SecurityQualityOfService: *const core::ffi::c_void,
pub Attributes: OBJECT_ATTRIBUTE_FLAGS,
pub SecurityDescriptor: *const SECURITY_DESCRIPTOR,
pub SecurityQualityOfService: *const SECURITY_QUALITY_OF_SERVICE,
}
pub const OBJ_DONT_REPARSE: i32 = 4096i32;
pub type OBJECT_ATTRIBUTE_FLAGS = u32;
pub const OBJ_DONT_REPARSE: OBJECT_ATTRIBUTE_FLAGS = 4096u32;
pub const OPEN_ALWAYS: FILE_CREATION_DISPOSITION = 4u32;
pub const OPEN_EXISTING: FILE_CREATION_DISPOSITION = 3u32;
#[repr(C)]
@ -2887,7 +2900,8 @@ pub const PROCESS_MODE_BACKGROUND_END: PROCESS_CREATION_FLAGS = 2097152u32;
pub const PROFILE_KERNEL: PROCESS_CREATION_FLAGS = 536870912u32;
pub const PROFILE_SERVER: PROCESS_CREATION_FLAGS = 1073741824u32;
pub const PROFILE_USER: PROCESS_CREATION_FLAGS = 268435456u32;
pub const PROGRESS_CONTINUE: u32 = 0u32;
pub const PROGRESS_CONTINUE: COPYPROGRESSROUTINE_PROGRESS = 0u32;
pub type PSID = *mut core::ffi::c_void;
pub type PSTR = *mut u8;
pub type PTIMERAPCROUTINE = Option<
unsafe extern "system" fn(
@ -2914,9 +2928,30 @@ pub struct SECURITY_ATTRIBUTES {
}
pub const SECURITY_CONTEXT_TRACKING: FILE_FLAGS_AND_ATTRIBUTES = 262144u32;
pub const SECURITY_DELEGATION: FILE_FLAGS_AND_ATTRIBUTES = 196608u32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SECURITY_DESCRIPTOR {
pub Revision: u8,
pub Sbz1: u8,
pub Control: SECURITY_DESCRIPTOR_CONTROL,
pub Owner: PSID,
pub Group: PSID,
pub Sacl: *mut ACL,
pub Dacl: *mut ACL,
}
pub type SECURITY_DESCRIPTOR_CONTROL = u16;
pub const SECURITY_EFFECTIVE_ONLY: FILE_FLAGS_AND_ATTRIBUTES = 524288u32;
pub const SECURITY_IDENTIFICATION: FILE_FLAGS_AND_ATTRIBUTES = 65536u32;
pub const SECURITY_IMPERSONATION: FILE_FLAGS_AND_ATTRIBUTES = 131072u32;
pub type SECURITY_IMPERSONATION_LEVEL = i32;
#[repr(C)]
#[derive(Clone, Copy)]
pub struct SECURITY_QUALITY_OF_SERVICE {
pub Length: u32,
pub ImpersonationLevel: SECURITY_IMPERSONATION_LEVEL,
pub ContextTrackingMode: u8,
pub EffectiveOnly: bool,
}
pub const SECURITY_SQOS_PRESENT: FILE_FLAGS_AND_ATTRIBUTES = 1048576u32;
pub const SECURITY_VALID_SQOS_FLAGS: FILE_FLAGS_AND_ATTRIBUTES = 2031616u32;
pub type SEND_RECV_FLAGS = i32;
@ -3137,18 +3172,6 @@ pub struct WSABUF {
pub buf: PSTR,
}
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
pub struct WSADATA {
pub wVersion: u16,
pub wHighVersion: u16,
pub iMaxSockets: u16,
pub iMaxUdpDg: u16,
pub lpVendorInfo: PSTR,
pub szDescription: [i8; 257],
pub szSystemStatus: [i8; 129],
}
#[repr(C)]
#[cfg(target_arch = "x86")]
#[derive(Clone, Copy)]
pub struct WSADATA {
@ -3160,6 +3183,18 @@ pub struct WSADATA {
pub iMaxUdpDg: u16,
pub lpVendorInfo: PSTR,
}
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
pub struct WSADATA {
pub wVersion: u16,
pub wHighVersion: u16,
pub iMaxSockets: u16,
pub iMaxUdpDg: u16,
pub lpVendorInfo: PSTR,
pub szDescription: [i8; 257],
pub szSystemStatus: [i8; 129],
}
pub const WSAEACCES: WSA_ERROR = 10013i32;
pub const WSAEADDRINUSE: WSA_ERROR = 10048i32;
pub const WSAEADDRNOTAVAIL: WSA_ERROR = 10049i32;
@ -3293,27 +3328,6 @@ pub const WSA_SECURE_HOST_NOT_FOUND: WSA_ERROR = 11032i32;
pub const WSA_WAIT_EVENT_0: WSA_ERROR = 0i32;
pub const WSA_WAIT_IO_COMPLETION: WSA_ERROR = 192i32;
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
pub struct XSAVE_FORMAT {
pub ControlWord: u16,
pub StatusWord: u16,
pub TagWord: u8,
pub Reserved1: u8,
pub ErrorOpcode: u16,
pub ErrorOffset: u32,
pub ErrorSelector: u16,
pub Reserved2: u16,
pub DataOffset: u32,
pub DataSelector: u16,
pub Reserved3: u16,
pub MxCsr: u32,
pub MxCsr_Mask: u32,
pub FloatRegisters: [M128A; 8],
pub XmmRegisters: [M128A; 16],
pub Reserved4: [u8; 96],
}
#[repr(C)]
#[cfg(target_arch = "x86")]
#[derive(Clone, Copy)]
pub struct XSAVE_FORMAT {
@ -3334,6 +3348,27 @@ pub struct XSAVE_FORMAT {
pub XmmRegisters: [M128A; 8],
pub Reserved4: [u8; 224],
}
#[repr(C)]
#[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_arch = "x86_64"))]
#[derive(Clone, Copy)]
pub struct XSAVE_FORMAT {
pub ControlWord: u16,
pub StatusWord: u16,
pub TagWord: u8,
pub Reserved1: u8,
pub ErrorOpcode: u16,
pub ErrorOffset: u32,
pub ErrorSelector: u16,
pub Reserved2: u16,
pub DataOffset: u32,
pub DataSelector: u16,
pub Reserved3: u16,
pub MxCsr: u32,
pub MxCsr_Mask: u32,
pub FloatRegisters: [M128A; 8],
pub XmmRegisters: [M128A; 16],
pub Reserved4: [u8; 96],
}
#[cfg(target_arch = "arm")]
#[repr(C)]

View file

@ -812,7 +812,7 @@ impl File {
/// will prevent anyone from opening a new handle to the file.
#[allow(unused)]
fn win32_delete(&self) -> Result<(), WinError> {
let info = c::FILE_DISPOSITION_INFO { DeleteFile: c::TRUE as _ };
let info = c::FILE_DISPOSITION_INFO { DeleteFile: true };
api::set_file_information_by_handle(self.handle.as_raw_handle(), &info)
}
@ -1372,7 +1372,7 @@ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
if let Err(err) = result {
if err.raw_os_error() == Some(c::ERROR_INVALID_PARAMETER as _) {
// FileRenameInfoEx and FILE_RENAME_FLAG_POSIX_SEMANTICS were added in Windows 10 1607; retry with FileRenameInfo.
file_rename_info.Anonymous.ReplaceIfExists = 1;
file_rename_info.Anonymous.ReplaceIfExists = true;
cvt(unsafe {
c::SetFileInformationByHandle(

View file

@ -99,16 +99,18 @@ prepare:
# Set of tests that represent around half of the time of the test suite.
# Used to split tests across multiple CI runners.
STAGE_2_TEST_SET1 := test --stage 2 --skip=compiler --skip=src
STAGE_2_TEST_SET2 := test --stage 2 --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest
SKIP_COMPILER := --skip=compiler
SKIP_SRC := --skip=src
TEST_SET1 := $(SKIP_COMPILER) $(SKIP_SRC)
TEST_SET2 := --skip=tests --skip=coverage-map --skip=coverage-run --skip=library --skip=tidyselftest
## MSVC native builders
# this intentionally doesn't use `$(BOOTSTRAP)` so we can test the shebang on Windows
ci-msvc-py:
$(Q)$(CFG_SRC_DIR)/x.py $(STAGE_2_TEST_SET1)
$(Q)$(CFG_SRC_DIR)/x.py test --stage 2 $(TEST_SET1)
ci-msvc-ps1:
$(Q)$(CFG_SRC_DIR)/x.ps1 $(STAGE_2_TEST_SET2)
$(Q)$(CFG_SRC_DIR)/x.ps1 test --stage 2 $(TEST_SET2)
ci-msvc: ci-msvc-py ci-msvc-ps1
## MingW native builders
@ -116,10 +118,14 @@ ci-msvc: ci-msvc-py ci-msvc-ps1
# Set of tests that should represent half of the time of the test suite.
# Used to split tests across multiple CI runners.
# Test both x and bootstrap entrypoints.
ci-mingw-x-1:
$(Q)$(CFG_SRC_DIR)/x test --stage 2 $(SKIP_COMPILER) $(TEST_SET2)
ci-mingw-x-2:
$(Q)$(CFG_SRC_DIR)/x test --stage 2 $(SKIP_SRC) $(TEST_SET2)
ci-mingw-x:
$(Q)$(CFG_SRC_DIR)/x $(STAGE_2_TEST_SET1)
$(Q)$(CFG_SRC_DIR)/x test --stage 2 $(TEST_SET1)
ci-mingw-bootstrap:
$(Q)$(BOOTSTRAP) $(STAGE_2_TEST_SET2)
$(Q)$(BOOTSTRAP) test --stage 2 $(TEST_SET2)
ci-mingw: ci-mingw-x ci-mingw-bootstrap
.PHONY: dist

View file

@ -1051,19 +1051,22 @@ fn test_prebuilt_llvm_config_path_resolution() {
"#,
);
let build = Build::new(config.clone());
let builder = Builder::new(&build);
// CI-LLVM isn't always available; check if it's enabled before testing.
if config.llvm_from_ci {
let build = Build::new(config.clone());
let builder = Builder::new(&build);
let actual = prebuilt_llvm_config(&builder, builder.config.build, false)
.llvm_result()
.llvm_config
.clone();
let expected = builder
.out
.join(builder.config.build)
.join("ci-llvm/bin")
.join(exe("llvm-config", builder.config.build));
assert_eq!(expected, actual);
let actual = prebuilt_llvm_config(&builder, builder.config.build, false)
.llvm_result()
.llvm_config
.clone();
let expected = builder
.out
.join(builder.config.build)
.join("ci-llvm/bin")
.join(exe("llvm-config", builder.config.build));
assert_eq!(expected, actual);
}
}
#[test]

View file

@ -456,6 +456,7 @@ auto:
# Windows Builders #
######################
# x86_64-msvc is split into two jobs to run tests in parallel.
- name: x86_64-msvc-1
env:
RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-sanitizers --enable-profiler
@ -527,13 +528,30 @@ auto:
# came from the mingw-w64 SourceForge download site. Unfortunately
# SourceForge is notoriously flaky, so we mirror it on our own infrastructure.
- name: i686-mingw
# i686-mingw is split into three jobs to run tests in parallel.
- name: i686-mingw-1
env:
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
SCRIPT: make ci-mingw
SCRIPT: make ci-mingw-x-1
# There is no dist-i686-mingw-alt, so there is no prebuilt LLVM with assertions
NO_DOWNLOAD_CI_LLVM: 1
<<: *job-windows-25-8c
<<: *job-windows-25
- name: i686-mingw-2
env:
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
SCRIPT: make ci-mingw-x-2
# There is no dist-i686-mingw-alt, so there is no prebuilt LLVM with assertions
NO_DOWNLOAD_CI_LLVM: 1
<<: *job-windows-25
- name: i686-mingw-3
env:
RUST_CONFIGURE_ARGS: --build=i686-pc-windows-gnu
SCRIPT: make ci-mingw-bootstrap
# There is no dist-i686-mingw-alt, so there is no prebuilt LLVM with assertions
NO_DOWNLOAD_CI_LLVM: 1
<<: *job-windows-25
# x86_64-mingw is split into two jobs to run tests in parallel.
- name: x86_64-mingw-1

View file

@ -52,10 +52,15 @@ access_url="https://ci-artifacts.rust-lang.org/${deploy_dir}/$(ciCommit)"
# to make them easily accessible.
if [ -n "${GITHUB_STEP_SUMMARY}" ]
then
echo "# CI artifacts" >> "${GITHUB_STEP_SUMMARY}"
archives=($(find "${upload_dir}" -maxdepth 1 -name "*.xz"))
for filename in "${upload_dir}"/*.xz; do
filename=$(basename "${filename}")
echo "- [${filename}](${access_url}/${filename})" >> "${GITHUB_STEP_SUMMARY}"
done
# Avoid generating an invalid "*.xz" file if there are no archives
if [ ${#archives[@]} -gt 0 ]; then
echo "# CI artifacts" >> "${GITHUB_STEP_SUMMARY}"
for filename in "${upload_dir}"/*.xz; do
filename=$(basename "${filename}")
echo "- [${filename}](${access_url}/${filename})" >> "${GITHUB_STEP_SUMMARY}"
done
fi
fi

View file

@ -154,6 +154,7 @@ Some examples of `X` in `ignore-X` or `only-X`:
`ignore-coverage-map`, `ignore-coverage-run`
- When testing a dist toolchain: `dist`
- This needs to be enabled with `COMPILETEST_ENABLE_DIST_TESTS=1`
- The `rustc_abi` of the target: e.g. `rustc_abi-x86_64-sse2`
The following directives will check rustc build settings and target
settings:

View file

@ -13,8 +13,8 @@ use rustc_session::parse::ParseSess;
use rustc_span::Span;
use rustc_span::symbol::{Symbol, sym};
use crate::display::Joined as _;
use crate::html::escape::Escape;
use crate::joined::Joined as _;
#[cfg(test)]
mod tests;

View file

@ -1,3 +1,5 @@
//! Various utilities for working with [`fmt::Display`] implementations.
use std::fmt::{self, Display, Formatter};
pub(crate) trait Joined: IntoIterator {
@ -27,3 +29,19 @@ where
Ok(())
}
}
pub(crate) trait MaybeDisplay {
/// For a given `Option<T: Display>`, returns a `Display` implementation that will display `t` if `Some(t)`, or nothing if `None`.
fn maybe_display(self) -> impl Display;
}
impl<T: Display> MaybeDisplay for Option<T> {
fn maybe_display(self) -> impl Display {
fmt::from_fn(move |f| {
if let Some(t) = self.as_ref() {
t.fmt(f)?;
}
Ok(())
})
}
}

View file

@ -30,11 +30,11 @@ use super::url_parts_builder::{UrlPartsBuilder, estimate_item_path_byte_length};
use crate::clean::types::ExternalLocation;
use crate::clean::utils::find_nearest_parent_module;
use crate::clean::{self, ExternalCrate, PrimitiveType};
use crate::display::Joined as _;
use crate::formats::cache::Cache;
use crate::formats::item_type::ItemType;
use crate::html::escape::{Escape, EscapeBodyText};
use crate::html::render::Context;
use crate::joined::Joined as _;
use crate::passes::collect_intra_doc_links::UrlFragment;
pub(crate) fn write_str(s: &mut String, f: fmt::Arguments<'_>) {
@ -709,19 +709,22 @@ fn resolved_path(
if w.alternate() {
write!(w, "{}{:#}", last.name, last.args.print(cx))?;
} else {
let path = if use_absolute {
if let Ok((_, _, fqp)) = href(did, cx) {
format!(
"{path}::{anchor}",
path = join_with_double_colon(&fqp[..fqp.len() - 1]),
anchor = anchor(did, *fqp.last().unwrap(), cx)
)
let path = fmt::from_fn(|f| {
if use_absolute {
if let Ok((_, _, fqp)) = href(did, cx) {
write!(
f,
"{path}::{anchor}",
path = join_with_double_colon(&fqp[..fqp.len() - 1]),
anchor = anchor(did, *fqp.last().unwrap(), cx)
)
} else {
write!(f, "{}", last.name)
}
} else {
last.name.to_string()
write!(f, "{}", anchor(did, last.name, cx))
}
} else {
anchor(did, last.name, cx).to_string()
};
});
write!(w, "{path}{args}", args = last.args.print(cx))?;
}
Ok(())
@ -749,16 +752,20 @@ fn primitive_link_fragment(
match m.primitive_locations.get(&prim) {
Some(&def_id) if def_id.is_local() => {
let len = cx.current.len();
let path = if len == 0 {
let cname_sym = ExternalCrate { crate_num: def_id.krate }.name(cx.tcx());
format!("{cname_sym}/")
} else {
"../".repeat(len - 1)
};
let path = fmt::from_fn(|f| {
if len == 0 {
let cname_sym = ExternalCrate { crate_num: def_id.krate }.name(cx.tcx());
write!(f, "{cname_sym}/")?;
} else {
for _ in 0..(len - 1) {
f.write_str("../")?;
}
}
Ok(())
});
write!(
f,
"<a class=\"primitive\" href=\"{}primitive.{}.html{fragment}\">",
path,
"<a class=\"primitive\" href=\"{path}primitive.{}.html{fragment}\">",
prim.as_sym()
)?;
needs_termination = true;

View file

@ -1,8 +1,9 @@
use std::cell::RefCell;
use std::collections::BTreeMap;
use std::fmt::{self, Write as _};
use std::io;
use std::path::{Path, PathBuf};
use std::sync::mpsc::{Receiver, channel};
use std::{fmt, io};
use rinja::Template;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
@ -265,12 +266,12 @@ impl<'tcx> Context<'tcx> {
// preventing an infinite redirection loop in the generated
// documentation.
let mut path = String::new();
for name in &names[..names.len() - 1] {
path.push_str(name.as_str());
path.push('/');
}
path.push_str(&item_path(ty, names.last().unwrap().as_str()));
let path = fmt::from_fn(|f| {
for name in &names[..names.len() - 1] {
write!(f, "{name}/")?;
}
write!(f, "{}", item_path(ty, names.last().unwrap().as_str()))
});
match self.shared.redirections {
Some(ref redirections) => {
let mut current_path = String::new();
@ -278,8 +279,12 @@ impl<'tcx> Context<'tcx> {
current_path.push_str(name.as_str());
current_path.push('/');
}
current_path.push_str(&item_path(ty, names.last().unwrap().as_str()));
redirections.borrow_mut().insert(current_path, path);
let _ = write!(
current_path,
"{}",
item_path(ty, names.last().unwrap().as_str())
);
redirections.borrow_mut().insert(current_path, path.to_string());
}
None => {
return layout::redirect(&format!(
@ -854,9 +859,9 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
if !buf.is_empty() {
let name = item.name.as_ref().unwrap();
let item_type = item.type_();
let file_name = &item_path(item_type, name.as_str());
let file_name = item_path(item_type, name.as_str()).to_string();
self.shared.ensure_dir(&self.dst)?;
let joint_dst = self.dst.join(file_name);
let joint_dst = self.dst.join(&file_name);
self.shared.fs.write(joint_dst, buf)?;
if !self.info.render_redirect_pages {
@ -873,7 +878,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
format!("{crate_name}/{file_name}"),
);
} else {
let v = layout::redirect(file_name);
let v = layout::redirect(&file_name);
let redir_dst = self.dst.join(redir_name);
self.shared.fs.write(redir_dst, v)?;
}

View file

@ -63,6 +63,7 @@ pub(crate) use self::context::*;
pub(crate) use self::span_map::{LinkFromSrc, collect_spans_and_sources};
pub(crate) use self::write_shared::*;
use crate::clean::{self, ItemId, RenderedLink};
use crate::display::{Joined as _, MaybeDisplay as _};
use crate::error::Error;
use crate::formats::Impl;
use crate::formats::cache::Cache;
@ -568,17 +569,27 @@ fn document_short<'a, 'cx: 'a>(
let (mut summary_html, has_more_content) =
MarkdownSummaryLine(&s, &item.links(cx)).into_string_with_has_more_content();
if has_more_content {
let link = format!(" <a{}>Read more</a>", assoc_href_attr(item, link, cx));
let link = if has_more_content {
let link = fmt::from_fn(|f| {
write!(
f,
" <a{}>Read more</a>",
assoc_href_attr(item, link, cx).maybe_display()
)
});
if let Some(idx) = summary_html.rfind("</p>") {
summary_html.insert_str(idx, &link);
summary_html.insert_str(idx, &link.to_string());
None
} else {
summary_html.push_str(&link);
Some(link)
}
} else {
None
}
.maybe_display();
write!(f, "<div class='docblock'>{summary_html}</div>")?;
write!(f, "<div class='docblock'>{summary_html}{link}</div>")?;
}
Ok(())
})
@ -788,13 +799,23 @@ pub(crate) fn render_impls(
}
/// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item.
fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>) -> String {
fn assoc_href_attr<'a, 'tcx>(
it: &clean::Item,
link: AssocItemLink<'a>,
cx: &Context<'tcx>,
) -> Option<impl fmt::Display + 'a + Captures<'tcx>> {
let name = it.name.unwrap();
let item_type = it.type_();
enum Href<'a> {
AnchorId(&'a str),
Anchor(ItemType),
Url(String, ItemType),
}
let href = match link {
AssocItemLink::Anchor(Some(ref id)) => Some(format!("#{id}")),
AssocItemLink::Anchor(None) => Some(format!("#{item_type}.{name}")),
AssocItemLink::Anchor(Some(ref id)) => Href::AnchorId(id),
AssocItemLink::Anchor(None) => Href::Anchor(item_type),
AssocItemLink::GotoSource(did, provided_methods) => {
// We're creating a link from the implementation of an associated item to its
// declaration in the trait declaration.
@ -814,7 +835,7 @@ fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>)
};
match href(did.expect_def_id(), cx) {
Ok((url, ..)) => Some(format!("{url}#{item_type}.{name}")),
Ok((url, ..)) => Href::Url(url, item_type),
// The link is broken since it points to an external crate that wasn't documented.
// Do not create any link in such case. This is better than falling back to a
// dummy anchor like `#{item_type}.{name}` representing the `id` of *this* impl item
@ -826,15 +847,25 @@ fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>)
// those two items are distinct!
// In this scenario, the actual `id` of this impl item would be
// `#{item_type}.{name}-{n}` for some number `n` (a disambiguator).
Err(HrefError::DocumentationNotBuilt) => None,
Err(_) => Some(format!("#{item_type}.{name}")),
Err(HrefError::DocumentationNotBuilt) => return None,
Err(_) => Href::Anchor(item_type),
}
}
};
let href = fmt::from_fn(move |f| match &href {
Href::AnchorId(id) => write!(f, "#{id}"),
Href::Url(url, item_type) => {
write!(f, "{url}#{item_type}.{name}")
}
Href::Anchor(item_type) => {
write!(f, "#{item_type}.{name}")
}
});
// If there is no `href` for the reason explained above, simply do not render it which is valid:
// https://html.spec.whatwg.org/multipage/links.html#links-created-by-a-and-area-elements
href.map(|href| format!(" href=\"{href}\"")).unwrap_or_default()
Some(fmt::from_fn(move |f| write!(f, " href=\"{href}\"")))
}
#[derive(Debug)]
@ -865,7 +896,7 @@ fn assoc_const(
"{indent}{vis}const <a{href} class=\"constant\">{name}</a>{generics}: {ty}",
indent = " ".repeat(indent),
vis = visibility_print_with_space(it, cx),
href = assoc_href_attr(it, link, cx),
href = assoc_href_attr(it, link, cx).maybe_display(),
name = it.name.as_ref().unwrap(),
generics = generics.print(cx),
ty = ty.print(cx),
@ -905,7 +936,7 @@ fn assoc_type(
"{indent}{vis}type <a{href} class=\"associatedtype\">{name}</a>{generics}",
indent = " ".repeat(indent),
vis = visibility_print_with_space(it, cx),
href = assoc_href_attr(it, link, cx),
href = assoc_href_attr(it, link, cx).maybe_display(),
name = it.name.as_ref().unwrap(),
generics = generics.print(cx),
),
@ -948,7 +979,7 @@ fn assoc_method(
let asyncness = header.asyncness.print_with_space();
let safety = header.safety.print_with_space();
let abi = print_abi_with_space(header.abi).to_string();
let href = assoc_href_attr(meth, link, cx);
let href = assoc_href_attr(meth, link, cx).maybe_display();
// NOTE: `{:#}` does not print HTML formatting, `{}` does. So `g.print` can't be reused between the length calculation and `write!`.
let generics_len = format!("{:#}", g.print(cx)).len();
@ -962,7 +993,7 @@ fn assoc_method(
+ name.as_str().len()
+ generics_len;
let notable_traits = notable_traits_button(&d.output, cx);
let notable_traits = notable_traits_button(&d.output, cx).maybe_display();
let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
header_len += 4;
@ -990,7 +1021,6 @@ fn assoc_method(
name = name,
generics = g.print(cx),
decl = d.full_print(header_len, indent, cx),
notable_traits = notable_traits.unwrap_or_default(),
where_clause = print_where_clause(g, cx, indent, end_newline),
),
);
@ -1438,7 +1468,10 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
}
}
pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Option<String> {
pub(crate) fn notable_traits_button<'a, 'tcx>(
ty: &'a clean::Type,
cx: &'a Context<'tcx>,
) -> Option<impl fmt::Display + 'a + Captures<'tcx>> {
let mut has_notable_trait = false;
if ty.is_unit() {
@ -1480,15 +1513,16 @@ pub(crate) fn notable_traits_button(ty: &clean::Type, cx: &Context<'_>) -> Optio
}
}
if has_notable_trait {
has_notable_trait.then(|| {
cx.types_with_notable_traits.borrow_mut().insert(ty.clone());
Some(format!(
" <a href=\"#\" class=\"tooltip\" data-notable-ty=\"{ty}\">ⓘ</a>",
ty = Escape(&format!("{:#}", ty.print(cx))),
))
} else {
None
}
fmt::from_fn(|f| {
write!(
f,
" <a href=\"#\" class=\"tooltip\" data-notable-ty=\"{ty}\">ⓘ</a>",
ty = Escape(&format!("{:#}", ty.print(cx))),
)
})
})
}
fn notable_traits_decl(ty: &clean::Type, cx: &Context<'_>) -> (String, String) {
@ -2117,11 +2151,11 @@ pub(crate) fn render_impl_summary(
) {
let inner_impl = i.inner_impl();
let id = cx.derive_id(get_id_for_impl(cx.tcx(), i.impl_item.item_id));
let aliases = if aliases.is_empty() {
String::new()
} else {
format!(" data-aliases=\"{}\"", aliases.join(","))
};
let aliases = (!aliases.is_empty())
.then_some(fmt::from_fn(|f| {
write!(f, " data-aliases=\"{}\"", fmt::from_fn(|f| aliases.iter().joined(",", f)))
}))
.maybe_display();
write_str(w, format_args!("<section id=\"{id}\" class=\"impl\"{aliases}>"));
render_rightside(w, cx, &i.impl_item, RenderMode::Normal);
write_str(

View file

@ -1,6 +1,6 @@
use std::cmp::Ordering;
use std::fmt;
use std::fmt::{Display, Write};
use std::fmt::Display;
use itertools::Itertools;
use rinja::Template;
@ -27,6 +27,7 @@ use super::{
};
use crate::clean;
use crate::config::ModuleSorting;
use crate::display::{Joined as _, MaybeDisplay as _};
use crate::formats::Impl;
use crate::formats::item_type::ItemType;
use crate::html::escape::{Escape, EscapeBodyTextWithWbr};
@ -37,7 +38,6 @@ use crate::html::format::{
use crate::html::markdown::{HeadingOffset, MarkdownSummaryLine};
use crate::html::render::{document_full, document_item_info};
use crate::html::url_parts_builder::UrlPartsBuilder;
use crate::joined::Joined as _;
/// Generates a Rinja template struct for rendering items with common methods.
///
@ -619,7 +619,7 @@ fn item_function(w: &mut String, cx: &Context<'_>, it: &clean::Item, f: &clean::
+ name.as_str().len()
+ generics_len;
let notable_traits = notable_traits_button(&f.decl.output, cx);
let notable_traits = notable_traits_button(&f.decl.output, cx).maybe_display();
wrap_item(w, |w| {
w.reserve(header_len);
@ -638,7 +638,6 @@ fn item_function(w: &mut String, cx: &Context<'_>, it: &clean::Item, f: &clean::
generics = f.generics.print(cx),
where_clause = print_where_clause(&f.generics, cx, 0, Ending::Newline),
decl = f.decl.full_print(header_len, 0, cx),
notable_traits = notable_traits.unwrap_or_default(),
),
);
});
@ -2116,34 +2115,33 @@ pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
s
}
pub(super) fn item_path(ty: ItemType, name: &str) -> String {
match ty {
ItemType::Module => format!("{}index.html", ensure_trailing_slash(name)),
_ => format!("{ty}.{name}.html"),
}
pub(super) fn item_path(ty: ItemType, name: &str) -> impl Display + '_ {
fmt::from_fn(move |f| match ty {
ItemType::Module => write!(f, "{}index.html", ensure_trailing_slash(name)),
_ => write!(f, "{ty}.{name}.html"),
})
}
fn bounds(t_bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>) -> String {
let mut bounds = String::new();
if t_bounds.is_empty() {
return bounds;
}
let has_lots_of_bounds = t_bounds.len() > 2;
let inter_str = if has_lots_of_bounds { "\n + " } else { " + " };
if !trait_alias {
if has_lots_of_bounds {
bounds.push_str(":\n ");
} else {
bounds.push_str(": ");
}
}
write!(
bounds,
"{}",
fmt::from_fn(|f| t_bounds.iter().map(|p| p.print(cx)).joined(inter_str, f))
)
.unwrap();
bounds
fn bounds<'a, 'tcx>(
bounds: &'a [clean::GenericBound],
trait_alias: bool,
cx: &'a Context<'tcx>,
) -> impl Display + 'a + Captures<'tcx> {
(!bounds.is_empty())
.then_some(fmt::from_fn(move |f| {
let has_lots_of_bounds = bounds.len() > 2;
let inter_str = if has_lots_of_bounds { "\n + " } else { " + " };
if !trait_alias {
if has_lots_of_bounds {
f.write_str(":\n ")?;
} else {
f.write_str(": ")?;
}
}
bounds.iter().map(|p| p.print(cx)).joined(inter_str, f)
}))
.maybe_display()
}
fn wrap_item<W, F>(w: &mut W, f: F)

View file

@ -2039,7 +2039,10 @@ function preLoadCss(cssUrl) {
// Most page titles are '<Item> in <path::to::module> - Rust', except
// modules (which don't have the first part) and keywords/primitives
// (which don't have a module path)
const [item, module] = document.title.split(" in ");
const titleElement = document.querySelector("title");
const title = titleElement && titleElement.textContent ?
titleElement.textContent.replace(" - Rust", "") : "";
const [item, module] = title.split(" in ");
const path = [item];
if (module !== undefined) {
path.unshift(module);

View file

@ -5318,8 +5318,9 @@ function registerSearchEvents() {
// @ts-expect-error
searchState.input.addEventListener("blur", () => {
// @ts-expect-error
searchState.input.placeholder = searchState.input.origPlaceholder;
if (window.searchState.input) {
window.searchState.input.placeholder = window.searchState.origPlaceholder;
}
});
// Push and pop states are used to add search results to the browser

View file

@ -106,6 +106,7 @@ macro_rules! map {
mod clean;
mod config;
mod core;
mod display;
mod docfs;
mod doctest;
mod error;
@ -114,7 +115,6 @@ mod fold;
mod formats;
// used by the error-index generator, so it needs to be public
pub mod html;
mod joined;
mod json;
pub(crate) mod lint;
mod markdown;

@ -1 +1 @@
Subproject commit 2928e32734b04925ee51e1ae88bea9a83d2fd451
Subproject commit ce948f4616e3d4277e30c75c8bb01e094910df39

View file

@ -517,6 +517,7 @@ pub struct TargetCfgs {
pub all_abis: HashSet<String>,
pub all_families: HashSet<String>,
pub all_pointer_widths: HashSet<String>,
pub all_rustc_abis: HashSet<String>,
}
impl TargetCfgs {
@ -536,6 +537,9 @@ impl TargetCfgs {
let mut all_abis = HashSet::new();
let mut all_families = HashSet::new();
let mut all_pointer_widths = HashSet::new();
// NOTE: for distinction between `abi` and `rustc_abi`, see comment on
// `TargetCfg::rustc_abi`.
let mut all_rustc_abis = HashSet::new();
// If current target is not included in the `--print=all-target-specs-json` output,
// we check whether it is a custom target from the user or a synthetic target from bootstrap.
@ -576,7 +580,9 @@ impl TargetCfgs {
all_families.insert(family.clone());
}
all_pointer_widths.insert(format!("{}bit", cfg.pointer_width));
if let Some(rustc_abi) = &cfg.rustc_abi {
all_rustc_abis.insert(rustc_abi.clone());
}
all_targets.insert(target.clone());
}
@ -590,6 +596,7 @@ impl TargetCfgs {
all_abis,
all_families,
all_pointer_widths,
all_rustc_abis,
}
}
@ -676,6 +683,10 @@ pub struct TargetCfg {
pub(crate) xray: bool,
#[serde(default = "default_reloc_model")]
pub(crate) relocation_model: String,
// NOTE: `rustc_abi` should not be confused with `abi`. `rustc_abi` was introduced in #137037 to
// make SSE2 *required* by the ABI (kind of a hack to make a target feature *required* via the
// target spec).
pub(crate) rustc_abi: Option<String>,
// Not present in target cfg json output, additional derived information.
#[serde(skip)]

View file

@ -87,6 +87,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"ignore-remote",
"ignore-riscv64",
"ignore-rustc-debug-assertions",
"ignore-rustc_abi-x86-sse2",
"ignore-s390x",
"ignore-sgx",
"ignore-sparc64",
@ -198,6 +199,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"only-nvptx64",
"only-powerpc",
"only-riscv64",
"only-rustc_abi-x86-sse2",
"only-s390x",
"only-sparc",
"only-sparc64",

View file

@ -234,6 +234,14 @@ fn parse_cfg_name_directive<'a>(
allowed_names: ["coverage-map", "coverage-run"],
message: "when the test mode is {name}",
}
condition! {
name: target_cfg.rustc_abi.as_ref().map(|abi| format!("rustc_abi-{abi}")).unwrap_or_default(),
allowed_names: ContainsPrefixed {
prefix: "rustc_abi-",
inner: target_cfgs.all_rustc_abis.clone(),
},
message: "when the target `rustc_abi` is {name}",
}
condition! {
name: "dist",

View file

@ -889,3 +889,17 @@ fn test_needs_target_has_atomic() {
assert!(!check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr"));
assert!(check_ignore(&config, "//@ needs-target-has-atomic: 8, ptr, 128"));
}
#[test]
// FIXME: this test will fail against stage 0 until #137037 changes reach beta.
#[cfg_attr(bootstrap, ignore)]
fn test_rustc_abi() {
let config = cfg().target("i686-unknown-linux-gnu").build();
assert_eq!(config.target_cfg().rustc_abi, Some("x86-sse2".to_string()));
assert!(check_ignore(&config, "//@ ignore-rustc_abi-x86-sse2"));
assert!(!check_ignore(&config, "//@ only-rustc_abi-x86-sse2"));
let config = cfg().target("x86_64-unknown-linux-gnu").build();
assert_eq!(config.target_cfg().rustc_abi, None);
assert!(!check_ignore(&config, "//@ ignore-rustc_abi-x86-sse2"));
assert!(check_ignore(&config, "//@ only-rustc_abi-x86-sse2"));
}

View file

@ -4,4 +4,4 @@ version = "0.1.0"
edition = "2021"
[dependencies.windows-bindgen]
version = "0.58.0"
version = "0.59.0"

View file

@ -29,8 +29,7 @@ fn main() -> Result<(), Box<dyn Error>> {
sort_bindings("bindings.txt")?;
let info = windows_bindgen::bindgen(["--etc", "bindings.txt"])?;
println!("{info}");
windows_bindgen::bindgen(["--etc", "bindings.txt"]);
let mut f = std::fs::File::options().append(true).open("windows_sys.rs")?;
f.write_all(ARM32_SHIM.as_bytes())?;

View file

@ -3,6 +3,7 @@
#![feature(cfg_match)]
#![feature(cell_update)]
#![feature(float_gamma)]
#![feature(float_erf)]
#![feature(map_try_insert)]
#![feature(never_type)]
#![feature(try_blocks)]

View file

@ -742,6 +742,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "log1pf"
| "expm1f"
| "tgammaf"
| "erff"
| "erfcf"
=> {
let [f] = this.check_shim(abi, Conv::C , link_name, args)?;
let f = this.read_scalar(f)?.to_f32()?;
@ -759,6 +761,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
"log1pf" => f_host.ln_1p(),
"expm1f" => f_host.exp_m1(),
"tgammaf" => f_host.gamma(),
"erff" => f_host.erf(),
"erfcf" => f_host.erfc(),
_ => bug!(),
};
let res = res.to_soft();
@ -799,6 +803,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
| "log1p"
| "expm1"
| "tgamma"
| "erf"
| "erfc"
=> {
let [f] = this.check_shim(abi, Conv::C , link_name, args)?;
let f = this.read_scalar(f)?.to_f64()?;
@ -816,6 +822,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
"log1p" => f_host.ln_1p(),
"expm1" => f_host.exp_m1(),
"tgamma" => f_host.gamma(),
"erf" => f_host.erf(),
"erfc" => f_host.erfc(),
_ => bug!(),
};
let res = res.to_soft();

View file

@ -1,4 +1,5 @@
#![feature(stmt_expr_attributes)]
#![feature(float_erf)]
#![feature(float_gamma)]
#![feature(core_intrinsics)]
#![feature(f128)]
@ -1076,6 +1077,11 @@ pub fn libm() {
let (val, sign) = (-0.5f64).ln_gamma();
assert_approx_eq!(val, (2.0 * f64::consts::PI.sqrt()).ln());
assert_eq!(sign, -1);
assert_approx_eq!(1.0f32.erf(), 0.84270079294971486934122063508260926f32);
assert_approx_eq!(1.0f64.erf(), 0.84270079294971486934122063508260926f64);
assert_approx_eq!(1.0f32.erfc(), 0.15729920705028513065877936491739074f32);
assert_approx_eq!(1.0f64.erfc(), 0.15729920705028513065877936491739074f64);
}
fn test_fast() {

View file

@ -132,6 +132,7 @@ const EXCEPTIONS_CARGO: ExceptionList = &[
("dunce", "CC0-1.0 OR MIT-0 OR Apache-2.0"),
("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"),
("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"),
("foldhash", "Zlib"),
("im-rc", "MPL-2.0+"),
("normalize-line-endings", "Apache-2.0"),
("openssl", "Apache-2.0"),

View file

@ -1 +1 @@
1.86.0
1.87.0

View file

@ -0,0 +1,11 @@
#![allow(internal_features)]
#![feature(no_core, lang_items, abi_gpu_kernel)]
#![no_core]
#![no_std]
// This is needed because of #![no_core]:
#[lang = "sized"]
trait Sized {}
#[no_mangle]
extern "gpu-kernel" fn kernel() {}

View file

@ -0,0 +1,20 @@
// On the amdhsa OS, the host runtime (HIP or HSA) expects a kernel descriptor object for each
// kernel in the ELF file. The amdgpu LLVM backend generates the object. It is created as a symbol
// with the name of the kernel plus a .kd suffix.
// Check that the produced object has the .kd symbol exported.
//@ needs-llvm-components: amdgpu
//@ needs-rust-lld
use run_make_support::{llvm_readobj, rustc};
fn main() {
rustc()
.crate_name("foo")
.target("amdgcn-amd-amdhsa")
.arg("-Ctarget-cpu=gfx900")
.crate_type("cdylib")
.input("foo.rs")
.run();
llvm_readobj().input("foo.elf").symbols().run().assert_stdout_contains("kernel.kd");
}

View file

@ -0,0 +1,6 @@
// issue: rust-lang/rust#122001
// Ensure we reject macro calls inside `#![crate_name]` as their result wouldn't get honored anyway.
#![crate_name = concat!("my", "crate")] //~ ERROR malformed `crate_name` attribute input
fn main() {}

View file

@ -0,0 +1,8 @@
error: malformed `crate_name` attribute input
--> $DIR/crate-name-macro-call.rs:4:1
|
LL | #![crate_name = concat!("my", "crate")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
error: aborting due to 1 previous error

View file

@ -1,5 +1,5 @@
error: malformed `crate_type` attribute input
--> $DIR/invalid_crate_type_syntax.rs:2:1
--> $DIR/crate-type-delimited.rs:2:1
|
LL | #![crate_type(lib)]
| ^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]`

View file

@ -1,5 +1,5 @@
error: malformed `crate_type` attribute input
--> $DIR/no_crate_type.rs:2:1
--> $DIR/crate-type-empty.rs:2:1
|
LL | #![crate_type]
| ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]`

View file

@ -1,5 +1,5 @@
error: malformed `crate_type` attribute input
--> $DIR/invalid-crate-type-macro.rs:1:1
--> $DIR/crate-type-macro-call.rs:1:1
|
LL | #![crate_type = foo!()]
| ^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_type = "bin|lib|..."]`

View file

@ -1,6 +0,0 @@
error: invalid character `'$'` in crate name: `need_crate_arg_ignore_tidy$x`
|
= help: you can either pass `--crate-name` on the command line or add `#![crate_name="…"]` to set the crate name
error: aborting due to 1 previous error

View file

@ -0,0 +1,14 @@
// Ensure that we properly ignore the `B<Self>` associated type bound on `A::T`
// since that associated type requires `Self: Sized`.
//@ check-pass
struct X(&'static dyn A);
trait A {
type T: B<Self> where Self: Sized;
}
trait B<T> {}
fn main() {}

View file

@ -1,8 +1,6 @@
error: path separator must be a double colon
--> $DIR/single-colon-path-not-const-generics.rs:8:18
|
LL | pub struct Foo {
| --- while parsing this struct
LL | a: Vec<foo::bar:A>,
| ^
|
@ -10,7 +8,7 @@ LL | a: Vec<foo::bar:A>,
help: use a double colon instead
|
LL | a: Vec<foo::bar::A>,
| +
| +
error: aborting due to 1 previous error

View file

@ -0,0 +1,6 @@
error: invalid character '$' in crate name: `need_crate_arg_ignore_tidy$x`
|
= help: you can either pass `--crate-name` on the command line or add `#![crate_name = "…"]` to set the crate name
error: aborting due to 1 previous error

Some files were not shown because too many files have changed in this diff Show more