Merge from rustc
This commit is contained in:
commit
703154d4f0
130 changed files with 4438 additions and 3395 deletions
15
Cargo.lock
15
Cargo.lock
|
|
@ -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"
|
||||
|
|
|
|||
127
RELEASES.md
127
RELEASES.md
|
|
@ -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)
|
||||
==========================
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
[toolchain]
|
||||
channel = "nightly-2025-02-07"
|
||||
channel = "nightly-2025-02-15"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools"]
|
||||
profile = "minimal"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
|
|
|
|||
|
|
@ -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>>,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(">");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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}`
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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>,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()?;
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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}`
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()),
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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")]
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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") }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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") }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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") }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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")))] {
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,4 +4,4 @@ version = "0.1.0"
|
|||
edition = "2021"
|
||||
|
||||
[dependencies.windows-bindgen]
|
||||
version = "0.58.0"
|
||||
version = "0.59.0"
|
||||
|
|
|
|||
|
|
@ -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())?;
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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"),
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
1.86.0
|
||||
1.87.0
|
||||
|
|
|
|||
11
tests/run-make/amdgpu-kd/foo.rs
Normal file
11
tests/run-make/amdgpu-kd/foo.rs
Normal 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() {}
|
||||
20
tests/run-make/amdgpu-kd/rmake.rs
Normal file
20
tests/run-make/amdgpu-kd/rmake.rs
Normal 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");
|
||||
}
|
||||
6
tests/ui/attributes/crate-name-macro-call.rs
Normal file
6
tests/ui/attributes/crate-name-macro-call.rs
Normal 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() {}
|
||||
8
tests/ui/attributes/crate-name-macro-call.stderr
Normal file
8
tests/ui/attributes/crate-name-macro-call.stderr
Normal 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
|
||||
|
||||
|
|
@ -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|..."]`
|
||||
|
|
@ -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|..."]`
|
||||
|
|
@ -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|..."]`
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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() {}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue