Merge pull request #4486 from rust-lang/rustup-2025-07-21

Automatic Rustup
This commit is contained in:
Ralf Jung 2025-07-21 06:09:06 +00:00 committed by GitHub
commit 9ef15d2302
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
100 changed files with 973 additions and 723 deletions

View file

@ -182,11 +182,6 @@ jobs:
- name: install MinGW
run: src/ci/scripts/install-mingw.sh
# Workaround for spurious ci failures after mingw install
# see https://rust-lang.zulipchat.com/#narrow/channel/242791-t-infra/topic/Spurious.20bors.20CI.20failures/near/528915775
- name: ensure home dir exists
run: mkdir -p ~
- name: install ninja
run: src/ci/scripts/install-ninja.sh

View file

@ -216,7 +216,7 @@ dependencies = [
"memchr",
"serde",
"serde_derive",
"winnow 0.7.11",
"winnow 0.7.12",
]
[[package]]
@ -510,23 +510,12 @@ dependencies = [
[[package]]
name = "chrono-tz"
version = "0.10.3"
version = "0.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3"
checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
dependencies = [
"chrono",
"chrono-tz-build",
"phf",
]
[[package]]
name = "chrono-tz-build"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402"
dependencies = [
"parse-zoneinfo",
"phf_codegen",
"phf 0.12.1",
]
[[package]]
@ -541,9 +530,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.40"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
dependencies = [
"clap_builder",
"clap_derive",
@ -561,9 +550,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.40"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
dependencies = [
"anstream",
"anstyle",
@ -573,9 +562,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.40"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
dependencies = [
"heck 0.5.0",
"proc-macro2",
@ -847,9 +836,9 @@ dependencies = [
[[package]]
name = "crc32fast"
version = "1.4.2"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
dependencies = [
"cfg-if",
]
@ -1038,9 +1027,9 @@ dependencies = [
[[package]]
name = "derive_setters"
version = "0.1.7"
version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9c848e86c87e5cc305313041c5677d4d95d60baa71cf95e5f6ea2554bb629ff"
checksum = "ae5c625eda104c228c06ecaf988d1c60e542176bd7a490e60eeda3493244c0c9"
dependencies = [
"darling",
"proc-macro2",
@ -2103,9 +2092,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]]
name = "libredox"
version = "0.1.4"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0"
dependencies = [
"bitflags",
"libc",
@ -2215,7 +2204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
dependencies = [
"log",
"phf",
"phf 0.11.3",
"phf_codegen",
"string_cache",
"string_cache_codegen",
@ -2254,9 +2243,9 @@ dependencies = [
[[package]]
name = "measureme"
version = "12.0.1"
version = "12.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "570a507d8948a66a97f42cbbaf8a6bb9516a51017d4ee949502ad7a10a864395"
checksum = "6ebd1ebda747ae161a4a377bf93f87e18d46faad2331cc0c7d25b84b1d445f49"
dependencies = [
"log",
"memmap2",
@ -2698,15 +2687,6 @@ dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "parse-zoneinfo"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
dependencies = [
"regex",
]
[[package]]
name = "pathdiff"
version = "0.2.3"
@ -2778,7 +2758,16 @@ version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
dependencies = [
"phf_shared",
"phf_shared 0.11.3",
]
[[package]]
name = "phf"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
dependencies = [
"phf_shared 0.12.1",
]
[[package]]
@ -2788,7 +2777,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
dependencies = [
"phf_generator",
"phf_shared",
"phf_shared 0.11.3",
]
[[package]]
@ -2797,7 +2786,7 @@ version = "0.11.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
dependencies = [
"phf_shared",
"phf_shared 0.11.3",
"rand 0.8.5",
]
@ -2810,6 +2799,15 @@ dependencies = [
"siphasher",
]
[[package]]
name = "phf_shared"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
dependencies = [
"siphasher",
]
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@ -4818,15 +4816,15 @@ dependencies = [
[[package]]
name = "rustix"
version = "1.0.7"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
@ -4947,9 +4945,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.140"
version = "1.0.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
dependencies = [
"itoa",
"memchr",
@ -5104,7 +5102,7 @@ checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
dependencies = [
"new_debug_unreachable",
"parking_lot",
"phf_shared",
"phf_shared 0.11.3",
"precomputed-hash",
"serde",
]
@ -5116,7 +5114,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
dependencies = [
"phf_generator",
"phf_shared",
"phf_shared 0.11.3",
"proc-macro2",
"quote",
]
@ -5181,9 +5179,9 @@ dependencies = [
[[package]]
name = "sysinfo"
version = "0.36.0"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aab138f5c1bb35231de19049060a87977ad23e04f2303e953bc5c2947ac7dec4"
checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d"
dependencies = [
"libc",
"objc2-core-foundation",
@ -5488,7 +5486,7 @@ dependencies = [
"serde_spanned",
"toml_datetime",
"toml_write",
"winnow 0.7.11",
"winnow 0.7.12",
]
[[package]]
@ -5886,9 +5884,9 @@ dependencies = [
[[package]]
name = "wasi-preview1-component-adapter-provider"
version = "34.0.1"
version = "34.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aafa1e6af9a954a4bcf6ef420c33355d0ce84ddc6afbcba7bb6f05126f9120ae"
checksum = "33696c5f1ff1e083de9f36c3da471abd736362bc173e093f8b0b1ed5a387e39b"
[[package]]
name = "wasm-bindgen"
@ -6532,9 +6530,9 @@ dependencies = [
[[package]]
name = "winnow"
version = "0.7.11"
version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
dependencies = [
"memchr",
]

View file

@ -39,6 +39,7 @@ impl OwnedTargetMachine {
debug_info_compression: &CStr,
use_emulated_tls: bool,
args_cstr_buff: &[u8],
use_wasm_eh: bool,
) -> Result<Self, LlvmError<'static>> {
assert!(args_cstr_buff.len() > 0);
assert!(
@ -72,6 +73,7 @@ impl OwnedTargetMachine {
use_emulated_tls,
args_cstr_buff.as_ptr() as *const c_char,
args_cstr_buff.len(),
use_wasm_eh,
)
};

View file

@ -15,6 +15,7 @@ use rustc_codegen_ssa::back::write::{
BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig,
TargetMachineFactoryFn,
};
use rustc_codegen_ssa::base::wants_wasm_eh;
use rustc_codegen_ssa::traits::*;
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind};
use rustc_data_structures::profiling::SelfProfilerRef;
@ -285,6 +286,8 @@ pub(crate) fn target_machine_factory(
let file_name_display_preference =
sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
let use_wasm_eh = wants_wasm_eh(sess);
Arc::new(move |config: TargetMachineFactoryConfig| {
let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
let path = path.unwrap_or_default();
@ -321,6 +324,7 @@ pub(crate) fn target_machine_factory(
&debuginfo_compression,
use_emulated_tls,
&args_cstr_buff,
use_wasm_eh,
)
})
}

View file

@ -207,6 +207,11 @@ pub(crate) unsafe fn create_module<'ll>(
// 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");
}
if sess.target.arch == "amdgpu" {
// LLVM 21 adds the address width for address space 8.
// See https://github.com/llvm/llvm-project/pull/139419
target_data_layout = target_data_layout.replace("p8:128:128:128:48", "p8:128:128")
}
}
// Ensure the data-layout values hardcoded remain the defaults.

View file

@ -2425,6 +2425,7 @@ unsafe extern "C" {
UseEmulatedTls: bool,
ArgsCstrBuff: *const c_char,
ArgsCstrBuffLen: usize,
UseWasmEH: bool,
) -> *mut TargetMachine;
pub(crate) fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);

View file

@ -630,7 +630,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
OperandRef { val: OperandValue::Immediate(static_), layout }
}
mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
mir::Rvalue::Repeat(..) => bug!("{rvalue:?} in codegen_rvalue_operand"),
mir::Rvalue::Repeat(ref elem, len_const) => {
// All arrays have `BackendRepr::Memory`, so only the ZST cases
// end up here. Anything else forces the destination local to be
// `Memory`, and thus ends up handled in `codegen_rvalue` instead.
let operand = self.codegen_operand(bx, elem);
let array_ty = Ty::new_array_with_const_len(bx.tcx(), operand.layout.ty, len_const);
let array_ty = self.monomorphize(array_ty);
let array_layout = bx.layout_of(array_ty);
assert!(array_layout.is_zst());
OperandRef { val: OperandValue::ZeroSized, layout: array_layout }
}
mir::Rvalue::Aggregate(ref kind, ref fields) => {
let (variant_index, active_field_index) = match **kind {
mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
@ -1000,12 +1010,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
mir::Rvalue::NullaryOp(..) |
mir::Rvalue::ThreadLocalRef(_) |
mir::Rvalue::Use(..) |
mir::Rvalue::Repeat(..) | // (*)
mir::Rvalue::Aggregate(..) | // (*)
mir::Rvalue::WrapUnsafeBinder(..) => // (*)
true,
// Arrays are always aggregates, so it's not worth checking anything here.
// (If it's really `[(); N]` or `[T; 0]` and we use the place path, fine.)
mir::Rvalue::Repeat(..) => false,
}
// (*) this is only true if the type is suitable

View file

@ -149,14 +149,14 @@ fn parse_rust_feature_flag<'a>(
if let Some(base_feature) = feature.strip_prefix('+') {
// Skip features that are not target features, but rustc features.
if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) {
return;
continue;
}
callback(base_feature, sess.target.implied_target_features(base_feature), true)
} else if let Some(base_feature) = feature.strip_prefix('-') {
// Skip features that are not target features, but rustc features.
if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) {
return;
continue;
}
// If `f1` implies `f2`, then `!f2` implies `!f1` -- this is standard logical

View file

@ -67,8 +67,8 @@ pub enum AllocKind {
LiveData,
/// A function allocation (that fn ptrs point to).
Function,
/// A (symbolic) vtable allocation.
VTable,
/// A "virtual" allocation, used for vtables and TypeId.
Virtual,
/// A dead allocation.
Dead,
}
@ -950,11 +950,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env);
let mutbl = global_alloc.mutability(*self.tcx, self.typing_env);
let kind = match global_alloc {
GlobalAlloc::TypeId { .. }
| GlobalAlloc::Static { .. }
| GlobalAlloc::Memory { .. } => AllocKind::LiveData,
GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"),
GlobalAlloc::VTable { .. } => AllocKind::VTable,
GlobalAlloc::VTable { .. } | GlobalAlloc::TypeId { .. } => AllocKind::Virtual,
};
return AllocInfo::new(size, align, kind, mutbl);
}

View file

@ -2495,6 +2495,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
ty::List::empty(),
PredicateFilter::All,
);
self.add_sizedness_bounds(
&mut bounds,
self_ty,
hir_bounds,
None,
None,
hir_ty.span,
);
self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span);
self_ty
}

View file

@ -160,12 +160,10 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
let (arg_indices, are_zsts_allowed): (&[_], _) = match diag_name {
sym::ptr_read
| sym::ptr_read_unaligned
| sym::ptr_read_volatile
| sym::ptr_replace
| sym::ptr_write
| sym::ptr_write_bytes
| sym::ptr_write_unaligned
| sym::ptr_write_volatile => (&[0], true),
| sym::ptr_write_unaligned => (&[0], true),
sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut => (&[0], false),
sym::ptr_copy
| sym::ptr_copy_nonoverlapping

View file

@ -396,7 +396,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray,
const char *SplitDwarfFile, const char *OutputObjFile,
const char *DebugInfoCompression, bool UseEmulatedTls,
const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) {
const char *ArgsCstrBuff, size_t ArgsCstrBuffLen, bool UseWasmEH) {
auto OptLevel = fromRust(RustOptLevel);
auto RM = fromRust(RustReloc);
@ -462,6 +462,9 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
Options.ThreadModel = ThreadModel::Single;
}
if (UseWasmEH)
Options.ExceptionModel = ExceptionHandling::Wasm;
Options.EmitStackSizeSection = EmitStackSizeSection;
if (ArgsCstrBuff != nullptr) {

View file

@ -1210,30 +1210,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
}
for (assoc_item_def_id, term) in assoc_items {
// Skip printing `<{coroutine@} as Coroutine<_>>::Return` from async blocks,
// unless we can find out what coroutine return type it comes from.
let term = if let Some(ty) = term.skip_binder().as_type()
&& let ty::Alias(ty::Projection, proj) = ty.kind()
&& let Some(assoc) = tcx.opt_associated_item(proj.def_id)
&& assoc
.trait_container(tcx)
.is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine))
&& assoc.opt_name() == Some(rustc_span::sym::Return)
{
if let ty::Coroutine(_, args) = args.type_at(0).kind() {
let return_ty = args.as_coroutine().return_ty();
if !return_ty.is_ty_var() {
return_ty.into()
} else {
continue;
}
} else {
continue;
}
} else {
term.skip_binder()
};
if first {
p!("<");
first = false;
@ -1243,7 +1219,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name()));
match term.kind() {
match term.skip_binder().kind() {
TermKind::Ty(ty) => p!(print(ty)),
TermKind::Const(c) => p!(print(c)),
};

View file

@ -119,14 +119,16 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
#[track_caller]
fn fail(&self, location: Location, msg: impl AsRef<str>) {
// We might see broken MIR when other errors have already occurred.
assert!(
self.tcx.dcx().has_errors().is_some(),
"broken MIR in {:?} ({}) at {:?}:\n{}",
self.body.source.instance,
self.when,
location,
msg.as_ref(),
);
if self.tcx.dcx().has_errors().is_none() {
span_bug!(
self.body.source_info(location).span,
"broken MIR in {:?} ({}) at {:?}:\n{}",
self.body.source.instance,
self.when,
location,
msg.as_ref(),
);
}
}
fn check_edge(&mut self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {

View file

@ -322,6 +322,7 @@ impl ExpnId {
/// `expn_id.outer_expn_is_descendant_of(ctxt)` is equivalent to but faster than
/// `expn_id.is_descendant_of(ctxt.outer_expn())`.
#[inline]
pub fn outer_expn_is_descendant_of(self, ctxt: SyntaxContext) -> bool {
HygieneData::with(|data| data.is_descendant_of(self, data.outer_expn(ctxt)))
}
@ -394,6 +395,7 @@ impl HygieneData {
}
}
#[inline]
fn with<R>(f: impl FnOnce(&mut HygieneData) -> R) -> R {
with_session_globals(|session_globals| f(&mut session_globals.hygiene_data.borrow_mut()))
}
@ -406,6 +408,7 @@ impl HygieneData {
}
}
#[inline]
fn local_expn_data(&self, expn_id: LocalExpnId) -> &ExpnData {
self.local_expn_data[expn_id].as_ref().expect("no expansion data for an expansion ID")
}
@ -437,23 +440,28 @@ impl HygieneData {
}
}
#[inline]
fn normalize_to_macros_2_0(&self, ctxt: SyntaxContext) -> SyntaxContext {
self.syntax_context_data[ctxt.0 as usize].opaque
}
#[inline]
fn normalize_to_macro_rules(&self, ctxt: SyntaxContext) -> SyntaxContext {
self.syntax_context_data[ctxt.0 as usize].opaque_and_semiopaque
}
#[inline]
fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
self.syntax_context_data[ctxt.0 as usize].outer_expn
}
#[inline]
fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) {
let data = &self.syntax_context_data[ctxt.0 as usize];
(data.outer_expn, data.outer_transparency)
}
#[inline]
fn parent_ctxt(&self, ctxt: SyntaxContext) -> SyntaxContext {
self.syntax_context_data[ctxt.0 as usize].parent
}
@ -718,11 +726,13 @@ impl SyntaxContext {
SyntaxContext(raw as u32)
}
#[inline]
fn from_usize(raw: usize) -> SyntaxContext {
SyntaxContext(u32::try_from(raw).unwrap())
}
/// Extend a syntax context with a given expansion and transparency.
#[inline]
pub fn apply_mark(self, expn_id: ExpnId, transparency: Transparency) -> SyntaxContext {
HygieneData::with(|data| data.apply_mark(self, expn_id, transparency))
}
@ -743,10 +753,12 @@ impl SyntaxContext {
/// of g (call it g1), calling remove_mark will result in the SyntaxContext for the
/// invocation of f that created g1.
/// Returns the mark that was removed.
#[inline]
pub fn remove_mark(&mut self) -> ExpnId {
HygieneData::with(|data| data.remove_mark(self).0)
}
#[inline]
pub fn marks(self) -> Vec<(ExpnId, Transparency)> {
HygieneData::with(|data| data.marks(self))
}
@ -776,11 +788,13 @@ impl SyntaxContext {
/// ```
/// This returns the expansion whose definition scope we use to privacy check the resolution,
/// or `None` if we privacy check as usual (i.e., not w.r.t. a macro definition scope).
#[inline]
pub fn adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
HygieneData::with(|data| data.adjust(self, expn_id))
}
/// Like `SyntaxContext::adjust`, but also normalizes `self` to macros 2.0.
#[inline]
pub(crate) fn normalize_to_macros_2_0_and_adjust(&mut self, expn_id: ExpnId) -> Option<ExpnId> {
HygieneData::with(|data| {
*self = data.normalize_to_macros_2_0(*self);
@ -901,10 +915,12 @@ impl SyntaxContext {
HygieneData::with(|data| data.outer_mark(self))
}
#[inline]
pub(crate) fn dollar_crate_name(self) -> Symbol {
HygieneData::with(|data| data.syntax_context_data[self.0 as usize].dollar_crate_name)
}
#[inline]
pub fn edition(self) -> Edition {
HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition)
}

View file

@ -167,6 +167,7 @@ where
}
}
#[inline]
pub fn with_session_globals<R, F>(f: F) -> R
where
F: FnOnce(&SessionGlobals) -> R,

View file

@ -3,7 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, Target, TargetMetadata,
pub(crate) fn target() -> Target {
Target {
arch: "amdgpu".into(),
data_layout: "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
data_layout: "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
llvm_target: "amdgcn-amd-amdhsa".into(),
metadata: TargetMetadata {
description: Some("AMD GPU".into()),

View file

@ -12,11 +12,11 @@ use rustc_infer::traits::solve::Goal;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::traits::solve::Certainty;
use rustc_middle::ty::{
self, SizedTraitKind, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
self, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
};
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
use crate::traits::{EvaluateConstErr, ObligationCause, specialization_graph};
use crate::traits::{EvaluateConstErr, ObligationCause, sizedness_fast_path, specialization_graph};
#[repr(transparent)]
pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>);
@ -76,19 +76,11 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
if trait_pred.polarity() == ty::PredicatePolarity::Positive {
match self.0.tcx.as_lang_item(trait_pred.def_id()) {
Some(LangItem::Sized)
if self
.resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
.has_trivial_sizedness(self.0.tcx, SizedTraitKind::Sized) =>
{
return Some(Certainty::Yes);
}
Some(LangItem::MetaSized)
if self
.resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
.has_trivial_sizedness(self.0.tcx, SizedTraitKind::MetaSized) =>
{
return Some(Certainty::Yes);
Some(LangItem::Sized) | Some(LangItem::MetaSized) => {
let predicate = self.resolve_vars_if_possible(goal.predicate);
if sizedness_fast_path(self.tcx, predicate, goal.param_env) {
return Some(Certainty::Yes);
}
}
Some(LangItem::Copy | LangItem::Clone) => {
let self_ty =

View file

@ -363,7 +363,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
let infcx = self.selcx.infcx;
if sizedness_fast_path(infcx.tcx, obligation.predicate) {
if sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) {
return ProcessResult::Changed(thin_vec![]);
}

View file

@ -15,7 +15,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
tcx: TyCtxt<'tcx>,
key: &ParamEnvAnd<'tcx, Self>,
) -> Option<Self::QueryResponse> {
if sizedness_fast_path(tcx, key.value.predicate) {
if sizedness_fast_path(tcx, key.value.predicate, key.param_env) {
return Some(());
}

View file

@ -597,7 +597,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
None => self.check_recursion_limit(&obligation, &obligation)?,
}
if sizedness_fast_path(self.tcx(), obligation.predicate) {
if sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env) {
return Ok(EvaluatedToOk);
}

View file

@ -365,7 +365,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
}
}
pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>) -> bool {
pub fn sizedness_fast_path<'tcx>(
tcx: TyCtxt<'tcx>,
predicate: ty::Predicate<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> bool {
// Proving `Sized`/`MetaSized`, very often on "obviously sized" types like
// `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to
// canonicalize and all that for such cases.
@ -390,6 +394,20 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
debug!("fast path -- trivial sizedness");
return true;
}
if matches!(trait_pred.self_ty().kind(), ty::Param(_) | ty::Placeholder(_)) {
for clause in param_env.caller_bounds() {
if let ty::ClauseKind::Trait(clause_pred) = clause.kind().skip_binder()
&& clause_pred.polarity == ty::PredicatePolarity::Positive
&& clause_pred.self_ty() == trait_pred.self_ty()
&& (clause_pred.def_id() == trait_pred.def_id()
|| (sizedness == SizedTraitKind::MetaSized
&& tcx.is_lang_item(clause_pred.def_id(), LangItem::Sized)))
{
return true;
}
}
}
}
false

View file

@ -24,7 +24,7 @@ fn evaluate_obligation<'tcx>(
debug!("evaluate_obligation: goal={:#?}", goal);
let ParamEnvAnd { param_env, value: predicate } = goal;
if sizedness_fast_path(tcx, predicate) {
if sizedness_fast_path(tcx, predicate, param_env) {
return Ok(EvaluationResult::EvaluatedToOk);
}

View file

@ -783,7 +783,7 @@ impl TypeId {
// This is a provenance-stripping memcpy.
for (i, chunk) in self.data.iter().copied().enumerate() {
let chunk = chunk.expose_provenance().to_ne_bytes();
let chunk = chunk.addr().to_ne_bytes();
let start = i * chunk.len();
bytes[start..(start + chunk.len())].copy_from_slice(&chunk);
}

View file

@ -28,15 +28,15 @@ pub trait AsyncIterator {
/// async iterator state:
///
/// - `Poll::Pending` means that this async iterator's next value is not ready
/// yet. Implementations will ensure that the current task will be notified
/// when the next value may be ready.
/// yet. Implementations will ensure that the current task will be notified
/// when the next value may be ready.
///
/// - `Poll::Ready(Some(val))` means that the async iterator has successfully
/// produced a value, `val`, and may produce further values on subsequent
/// `poll_next` calls.
/// produced a value, `val`, and may produce further values on subsequent
/// `poll_next` calls.
///
/// - `Poll::Ready(None)` means that the async iterator has terminated, and
/// `poll_next` should not be invoked again.
/// `poll_next` should not be invoked again.
///
/// # Panics
///

View file

@ -1482,13 +1482,14 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
}
}
fn default_chaining_impl<T: PointeeSized, U: PointeeSized>(
fn default_chaining_impl<T, U>(
lhs: &T,
rhs: &U,
p: impl FnOnce(Ordering) -> bool,
) -> ControlFlow<bool>
where
T: PartialOrd<U>,
T: PartialOrd<U> + PointeeSized,
U: PointeeSized,
{
// It's important that this only call `partial_cmp` once, not call `eq` then
// one of the relational operators. We don't want to `bcmp`-then-`memcp` a

View file

@ -854,7 +854,6 @@ impl Display for Arguments<'_> {
/// }";
/// assert_eq!(format!("The origin is: {origin:#?}"), expected);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
on(

View file

@ -1379,6 +1379,7 @@ pub unsafe fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
///
/// The stabilized version of this intrinsic is
/// [`f16::floor`](../../std/primitive.f16.html#method.floor)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn floorf16(x: f16) -> f16;
@ -1386,6 +1387,7 @@ pub const unsafe fn floorf16(x: f16) -> f16;
///
/// The stabilized version of this intrinsic is
/// [`f32::floor`](../../std/primitive.f32.html#method.floor)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn floorf32(x: f32) -> f32;
@ -1393,6 +1395,7 @@ pub const unsafe fn floorf32(x: f32) -> f32;
///
/// The stabilized version of this intrinsic is
/// [`f64::floor`](../../std/primitive.f64.html#method.floor)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn floorf64(x: f64) -> f64;
@ -1400,6 +1403,7 @@ pub const unsafe fn floorf64(x: f64) -> f64;
///
/// The stabilized version of this intrinsic is
/// [`f128::floor`](../../std/primitive.f128.html#method.floor)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn floorf128(x: f128) -> f128;
@ -1408,6 +1412,7 @@ pub const unsafe fn floorf128(x: f128) -> f128;
///
/// The stabilized version of this intrinsic is
/// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn ceilf16(x: f16) -> f16;
@ -1415,6 +1420,7 @@ pub const unsafe fn ceilf16(x: f16) -> f16;
///
/// The stabilized version of this intrinsic is
/// [`f32::ceil`](../../std/primitive.f32.html#method.ceil)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn ceilf32(x: f32) -> f32;
@ -1422,6 +1428,7 @@ pub const unsafe fn ceilf32(x: f32) -> f32;
///
/// The stabilized version of this intrinsic is
/// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn ceilf64(x: f64) -> f64;
@ -1429,6 +1436,7 @@ pub const unsafe fn ceilf64(x: f64) -> f64;
///
/// The stabilized version of this intrinsic is
/// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn ceilf128(x: f128) -> f128;
@ -1437,6 +1445,7 @@ pub const unsafe fn ceilf128(x: f128) -> f128;
///
/// The stabilized version of this intrinsic is
/// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn truncf16(x: f16) -> f16;
@ -1444,6 +1453,7 @@ pub const unsafe fn truncf16(x: f16) -> f16;
///
/// The stabilized version of this intrinsic is
/// [`f32::trunc`](../../std/primitive.f32.html#method.trunc)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn truncf32(x: f32) -> f32;
@ -1451,6 +1461,7 @@ pub const unsafe fn truncf32(x: f32) -> f32;
///
/// The stabilized version of this intrinsic is
/// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn truncf64(x: f64) -> f64;
@ -1458,6 +1469,7 @@ pub const unsafe fn truncf64(x: f64) -> f64;
///
/// The stabilized version of this intrinsic is
/// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn truncf128(x: f128) -> f128;
@ -1467,6 +1479,7 @@ pub const unsafe fn truncf128(x: f128) -> f128;
///
/// The stabilized version of this intrinsic is
/// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const fn round_ties_even_f16(x: f16) -> f16;
@ -1476,6 +1489,7 @@ pub const fn round_ties_even_f16(x: f16) -> f16;
///
/// The stabilized version of this intrinsic is
/// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const fn round_ties_even_f32(x: f32) -> f32;
@ -1485,6 +1499,7 @@ pub const fn round_ties_even_f32(x: f32) -> f32;
///
/// The stabilized version of this intrinsic is
/// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const fn round_ties_even_f64(x: f64) -> f64;
@ -1494,6 +1509,7 @@ pub const fn round_ties_even_f64(x: f64) -> f64;
///
/// The stabilized version of this intrinsic is
/// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const fn round_ties_even_f128(x: f128) -> f128;
@ -1502,6 +1518,7 @@ pub const fn round_ties_even_f128(x: f128) -> f128;
///
/// The stabilized version of this intrinsic is
/// [`f16::round`](../../std/primitive.f16.html#method.round)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn roundf16(x: f16) -> f16;
@ -1509,6 +1526,7 @@ pub const unsafe fn roundf16(x: f16) -> f16;
///
/// The stabilized version of this intrinsic is
/// [`f32::round`](../../std/primitive.f32.html#method.round)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn roundf32(x: f32) -> f32;
@ -1516,6 +1534,7 @@ pub const unsafe fn roundf32(x: f32) -> f32;
///
/// The stabilized version of this intrinsic is
/// [`f64::round`](../../std/primitive.f64.html#method.round)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn roundf64(x: f64) -> f64;
@ -1523,6 +1542,7 @@ pub const unsafe fn roundf64(x: f64) -> f64;
///
/// The stabilized version of this intrinsic is
/// [`f128::round`](../../std/primitive.f128.html#method.round)
#[rustc_intrinsic_const_stable_indirect]
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn roundf128(x: f128) -> f128;

View file

@ -436,7 +436,6 @@ pub trait Extend<A> {
/// **For implementors:** For a collection to unsafely rely on this method's safety precondition (that is,
/// invoke UB if they are violated), it must implement `extend_reserve` correctly. In other words,
/// callers may assume that if they `extend_reserve`ed enough space they can call this method.
// This method is for internal usage only. It is only on the trait because of specialization's limitations.
#[unstable(feature = "extend_one_unchecked", issue = "none")]
#[doc(hidden)]

View file

@ -3414,10 +3414,10 @@ pub trait Iterator {
/// ```
#[stable(feature = "iter_copied", since = "1.36.0")]
#[rustc_diagnostic_item = "iter_copied"]
fn copied<'a, T: 'a>(self) -> Copied<Self>
fn copied<'a, T>(self) -> Copied<Self>
where
T: Copy + 'a,
Self: Sized + Iterator<Item = &'a T>,
T: Copy,
{
Copied::new(self)
}
@ -3462,10 +3462,10 @@ pub trait Iterator {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_diagnostic_item = "iter_cloned"]
fn cloned<'a, T: 'a>(self) -> Cloned<Self>
fn cloned<'a, T>(self) -> Cloned<Self>
where
T: Clone + 'a,
Self: Sized + Iterator<Item = &'a T>,
T: Clone,
{
Cloned::new(self)
}

View file

@ -39,9 +39,9 @@
//! return. You should mark your implementation using `#[panic_handler]`.
//!
//! * `rust_eh_personality` - is used by the failure mechanisms of the
//! compiler. This is often mapped to GCC's personality function, but crates
//! which do not trigger a panic can be assured that this function is never
//! called. The `lang` attribute is called `eh_personality`.
//! compiler. This is often mapped to GCC's personality function, but crates
//! which do not trigger a panic can be assured that this function is never
//! called. The `lang` attribute is called `eh_personality`.
#![stable(feature = "core", since = "1.6.0")]
#![doc(

View file

@ -1005,28 +1005,6 @@ impl<T> MaybeUninit<T> {
}
}
/// Deprecated version of [`slice::assume_init_ref`].
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[deprecated(
note = "replaced by inherent assume_init_ref method; will eventually be removed",
since = "1.83.0"
)]
pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
// SAFETY: Same for both methods.
unsafe { slice.assume_init_ref() }
}
/// Deprecated version of [`slice::assume_init_mut`].
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[deprecated(
note = "replaced by inherent assume_init_mut method; will eventually be removed",
since = "1.83.0"
)]
pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
// SAFETY: Same for both methods.
unsafe { slice.assume_init_mut() }
}
/// Gets a pointer to the first element of the array.
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
#[inline(always)]
@ -1040,94 +1018,6 @@ impl<T> MaybeUninit<T> {
pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
this.as_mut_ptr() as *mut T
}
/// Deprecated version of [`slice::write_copy_of_slice`].
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
#[deprecated(
note = "replaced by inherent write_copy_of_slice method; will eventually be removed",
since = "1.83.0"
)]
pub fn copy_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
where
T: Copy,
{
this.write_copy_of_slice(src)
}
/// Deprecated version of [`slice::write_clone_of_slice`].
#[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
#[deprecated(
note = "replaced by inherent write_clone_of_slice method; will eventually be removed",
since = "1.83.0"
)]
pub fn clone_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
where
T: Clone,
{
this.write_clone_of_slice(src)
}
/// Deprecated version of [`slice::write_filled`].
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
#[deprecated(
note = "replaced by inherent write_filled method; will eventually be removed",
since = "1.83.0"
)]
pub fn fill<'a>(this: &'a mut [MaybeUninit<T>], value: T) -> &'a mut [T]
where
T: Clone,
{
this.write_filled(value)
}
/// Deprecated version of [`slice::write_with`].
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
#[deprecated(
note = "replaced by inherent write_with method; will eventually be removed",
since = "1.83.0"
)]
pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit<T>], mut f: F) -> &'a mut [T]
where
F: FnMut() -> T,
{
this.write_with(|_| f())
}
/// Deprecated version of [`slice::write_iter`].
#[unstable(feature = "maybe_uninit_fill", issue = "117428")]
#[deprecated(
note = "replaced by inherent write_iter method; will eventually be removed",
since = "1.83.0"
)]
pub fn fill_from<'a, I>(
this: &'a mut [MaybeUninit<T>],
it: I,
) -> (&'a mut [T], &'a mut [MaybeUninit<T>])
where
I: IntoIterator<Item = T>,
{
this.write_iter(it)
}
/// Deprecated version of [`slice::as_bytes`].
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
#[deprecated(
note = "replaced by inherent as_bytes method; will eventually be removed",
since = "1.83.0"
)]
pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] {
this.as_bytes()
}
/// Deprecated version of [`slice::as_bytes_mut`].
#[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
#[deprecated(
note = "replaced by inherent as_bytes_mut method; will eventually be removed",
since = "1.83.0"
)]
pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] {
this.as_bytes_mut()
}
}
impl<T> [MaybeUninit<T>] {
@ -1304,7 +1194,7 @@ impl<T> [MaybeUninit<T>] {
/// Fills a slice with elements returned by calling a closure for each index.
///
/// This method uses a closure to create new values. If you'd rather `Clone` a given value, use
/// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can
/// [slice::write_filled]. If you want to use the `Default` trait to generate values, you can
/// pass [`|_| Default::default()`][Default::default] as the argument.
///
/// # Panics
@ -1463,7 +1353,7 @@ impl<T> [MaybeUninit<T>] {
/// use std::mem::MaybeUninit;
///
/// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()];
/// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit);
/// let uninit_bytes = uninit.as_bytes_mut();
/// uninit_bytes.write_copy_of_slice(&[0x12, 0x34, 0x56, 0x78]);
/// let vals = unsafe { uninit.assume_init_ref() };
/// if cfg!(target_endian = "little") {

View file

@ -36,7 +36,7 @@ pub use crate::intrinsics::transmute;
/// * If you want to leak memory, see [`Box::leak`].
/// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`].
/// * If you want to dispose of a value properly, running its destructor, see
/// [`mem::drop`].
/// [`mem::drop`].
///
/// # Safety
///

View file

@ -787,7 +787,6 @@ impl Ipv4Addr {
/// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
/// [unspecified address]: Ipv4Addr::UNSPECIFIED
/// [broadcast address]: Ipv4Addr::BROADCAST
///
/// # Examples
///

View file

@ -1448,7 +1448,6 @@ impl f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn floor(self) -> f128 {
// SAFETY: intrinsic with no preconditions
@ -1478,7 +1477,6 @@ impl f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn ceil(self) -> f128 {
// SAFETY: intrinsic with no preconditions
@ -1514,7 +1512,6 @@ impl f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round(self) -> f128 {
// SAFETY: intrinsic with no preconditions
@ -1548,7 +1545,6 @@ impl f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round_ties_even(self) -> f128 {
intrinsics::round_ties_even_f128(self)
@ -1580,7 +1576,6 @@ impl f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn trunc(self) -> f128 {
// SAFETY: intrinsic with no preconditions
@ -1611,7 +1606,6 @@ impl f128 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn fract(self) -> f128 {
self - self.trunc()

View file

@ -1424,7 +1424,6 @@ impl f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn floor(self) -> f16 {
// SAFETY: intrinsic with no preconditions
@ -1454,7 +1453,6 @@ impl f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn ceil(self) -> f16 {
// SAFETY: intrinsic with no preconditions
@ -1490,7 +1488,6 @@ impl f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round(self) -> f16 {
// SAFETY: intrinsic with no preconditions
@ -1524,7 +1521,6 @@ impl f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round_ties_even(self) -> f16 {
intrinsics::round_ties_even_f16(self)
@ -1556,7 +1552,6 @@ impl f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn trunc(self) -> f16 {
// SAFETY: intrinsic with no preconditions
@ -1587,7 +1582,6 @@ impl f16 {
#[rustc_allow_incoherent_impl]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
// #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn fract(self) -> f16 {
self - self.trunc()

View file

@ -1591,7 +1591,6 @@ pub mod math {
/// [`f32::floor`]: ../../../std/primitive.f32.html#method.floor
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn floor(x: f32) -> f32 {
// SAFETY: intrinsic with no preconditions
@ -1622,7 +1621,6 @@ pub mod math {
#[doc(alias = "ceiling")]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
pub const fn ceil(x: f32) -> f32 {
// SAFETY: intrinsic with no preconditions
unsafe { intrinsics::ceilf32(x) }
@ -1657,7 +1655,6 @@ pub mod math {
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[must_use = "method returns a new number and does not mutate the original value"]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
pub const fn round(x: f32) -> f32 {
// SAFETY: intrinsic with no preconditions
unsafe { intrinsics::roundf32(x) }
@ -1691,7 +1688,6 @@ pub mod math {
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[must_use = "method returns a new number and does not mutate the original value"]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
pub const fn round_ties_even(x: f32) -> f32 {
intrinsics::round_ties_even_f32(x)
}
@ -1722,7 +1718,6 @@ pub mod math {
#[doc(alias = "truncate")]
#[must_use = "method returns a new number and does not mutate the original value"]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
pub const fn trunc(x: f32) -> f32 {
// SAFETY: intrinsic with no preconditions
unsafe { intrinsics::truncf32(x) }
@ -1752,7 +1747,6 @@ pub mod math {
/// [`f32::fract`]: ../../../std/primitive.f32.html#method.fract
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn fract(x: f32) -> f32 {
x - trunc(x)

View file

@ -1589,7 +1589,6 @@ pub mod math {
/// [`f64::floor`]: ../../../std/primitive.f64.html#method.floor
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn floor(x: f64) -> f64 {
// SAFETY: intrinsic with no preconditions
@ -1619,7 +1618,6 @@ pub mod math {
#[inline]
#[doc(alias = "ceiling")]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn ceil(x: f64) -> f64 {
// SAFETY: intrinsic with no preconditions
@ -1654,7 +1652,6 @@ pub mod math {
/// [`f64::round`]: ../../../std/primitive.f64.html#method.round
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round(x: f64) -> f64 {
// SAFETY: intrinsic with no preconditions
@ -1688,7 +1685,6 @@ pub mod math {
/// [`f64::round_ties_even`]: ../../../std/primitive.f64.html#method.round_ties_even
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn round_ties_even(x: f64) -> f64 {
intrinsics::round_ties_even_f64(x)
@ -1719,7 +1715,6 @@ pub mod math {
#[inline]
#[doc(alias = "truncate")]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn trunc(x: f64) -> f64 {
// SAFETY: intrinsic with no preconditions
@ -1750,7 +1745,6 @@ pub mod math {
/// [`f64::fract`]: ../../../std/primitive.f64.html#method.fract
#[inline]
#[unstable(feature = "core_float_math", issue = "137578")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn fract(x: f64) -> f64 {
x - trunc(x)

View file

@ -1,5 +1,5 @@
/// These functions compute the integer logarithm of their type, assuming
/// that someone has already checked that the value is strictly positive.
//! These functions compute the integer logarithm of their type, assuming
//! that someone has already checked that the value is strictly positive.
// 0 < val <= u8::MAX
#[inline]

View file

@ -556,7 +556,7 @@ macro_rules! uint_impl {
pub const fn strict_add(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_add(rhs);
if b { overflow_panic::add() } else { a }
}
}
/// Unchecked integer addition. Computes `self + rhs`, assuming overflow
/// cannot occur.
@ -653,7 +653,7 @@ macro_rules! uint_impl {
pub const fn strict_add_signed(self, rhs: $SignedT) -> Self {
let (a, b) = self.overflowing_add_signed(rhs);
if b { overflow_panic::add() } else { a }
}
}
/// Checked integer subtraction. Computes `self - rhs`, returning
/// `None` if overflow occurred.
@ -713,7 +713,7 @@ macro_rules! uint_impl {
pub const fn strict_sub(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_sub(rhs);
if b { overflow_panic::sub() } else { a }
}
}
/// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
/// cannot occur.
@ -805,6 +805,43 @@ macro_rules! uint_impl {
}
}
/// Strict subtraction with a signed integer. Computes `self - rhs`,
/// panicking if overflow occurred.
///
/// # Panics
///
/// ## Overflow behavior
///
/// This function will always panic on overflow, regardless of whether overflow checks are enabled.
///
/// # Examples
///
/// ```
/// #![feature(strict_overflow_ops)]
#[doc = concat!("assert_eq!(3", stringify!($SelfT), ".strict_sub_signed(2), 1);")]
/// ```
///
/// The following panic because of overflow:
///
/// ```should_panic
/// #![feature(strict_overflow_ops)]
#[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_sub_signed(2);")]
/// ```
///
/// ```should_panic
/// #![feature(strict_overflow_ops)]
#[doc = concat!("let _ = (", stringify!($SelfT), "::MAX).strict_sub_signed(-1);")]
/// ```
#[unstable(feature = "strict_overflow_ops", issue = "118260")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
#[track_caller]
pub const fn strict_sub_signed(self, rhs: $SignedT) -> Self {
let (a, b) = self.overflowing_sub_signed(rhs);
if b { overflow_panic::sub() } else { a }
}
#[doc = concat!(
"Checked integer subtraction. Computes `self - rhs` and checks if the result fits into an [`",
stringify!($SignedT), "`], returning `None` if overflow occurred."
@ -913,7 +950,7 @@ macro_rules! uint_impl {
pub const fn strict_mul(self, rhs: Self) -> Self {
let (a, b) = self.overflowing_mul(rhs);
if b { overflow_panic::mul() } else { a }
}
}
/// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
/// cannot occur.

View file

@ -1363,7 +1363,6 @@ mod prim_f16 {}
/// x = a + b + c + d; // As written
/// x = (a + c) + (b + d); // Reordered to shorten critical path and enable vectorization
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_f32 {}

View file

@ -10,24 +10,24 @@ When calling this method, you have to ensure that *either* the pointer is null *
all of the following is true:
* The pointer must be [valid] for reads for `ptr.len() * size_of::<T>()` many bytes,
and it must be properly aligned. This means in particular:
and it must be properly aligned. This means in particular:
* The entire memory range of this slice must be contained within a single [allocation]!
Slices can never span across multiple allocations.
Slices can never span across multiple allocations.
* The pointer must be aligned even for zero-length slices. One
reason for this is that enum layout optimizations may rely on references
(including slices of any length) being aligned and non-null to distinguish
them from other data. You can obtain a pointer that is usable as `data`
for zero-length slices using [`NonNull::dangling()`].
reason for this is that enum layout optimizations may rely on references
(including slices of any length) being aligned and non-null to distinguish
them from other data. You can obtain a pointer that is usable as `data`
for zero-length slices using [`NonNull::dangling()`].
* The total size `ptr.len() * size_of::<T>()` of the slice must be no larger than `isize::MAX`.
See the safety documentation of [`pointer::offset`].
See the safety documentation of [`pointer::offset`].
* You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
In particular, while this reference exists, the memory the pointer points to must
not get mutated (except inside `UnsafeCell`).
arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
In particular, while this reference exists, the memory the pointer points to must
not get mutated (except inside `UnsafeCell`).
This applies even if the result of this method is unused!

View file

@ -28,7 +28,8 @@
//! undefined behavior to perform two concurrent accesses to the same location from different
//! threads unless both accesses only read from memory. Notice that this explicitly
//! includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot
//! be used for inter-thread synchronization.
//! be used for inter-thread synchronization, regardless of whether they are acting on
//! Rust memory or not.
//! * The result of casting a reference to a pointer is valid for as long as the
//! underlying allocation is live and no reference (just raw pointers) is used to
//! access the same memory. That is, reference and pointer accesses cannot be
@ -114,6 +115,10 @@
//! fully contiguous (i.e., has no "holes"), there is no guarantee that this
//! will not change in the future.
//!
//! Allocations must behave like "normal" memory: in particular, reads must not have
//! side-effects, and writes must become visible to other threads using the usual synchronization
//! primitives.
//!
//! For any allocation with `base` address, `size`, and a set of
//! `addresses`, the following are guaranteed:
//! - For all addresses `a` in `addresses`, `a` is in the range `base .. (base +
@ -2021,54 +2026,61 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
}
}
/// Performs a volatile read of the value from `src` without moving it. This
/// leaves the memory in `src` unchanged.
/// Performs a volatile read of the value from `src` without moving it.
///
/// Volatile operations are intended to act on I/O memory, and are guaranteed
/// to not be elided or reordered by the compiler across other volatile
/// operations.
/// Volatile operations are intended to act on I/O memory. As such, they are considered externally
/// observable events (just like syscalls, but less opaque), and are guaranteed to not be elided or
/// reordered by the compiler across other externally observable events. With this in mind, there
/// are two cases of usage that need to be distinguished:
///
/// # Notes
/// - When a volatile operation is used for memory inside an [allocation], it behaves exactly like
/// [`read`], except for the additional guarantee that it won't be elided or reordered (see
/// above). This implies that the operation will actually access memory and not e.g. be lowered to
/// reusing data from a previous read. Other than that, all the usual rules for memory accesses
/// apply (including provenance). In particular, just like in C, whether an operation is volatile
/// has no bearing whatsoever on questions involving concurrent accesses from multiple threads.
/// Volatile accesses behave exactly like non-atomic accesses in that regard.
///
/// Rust does not currently have a rigorously and formally defined memory model,
/// so the precise semantics of what "volatile" means here is subject to change
/// over time. That being said, the semantics will almost always end up pretty
/// similar to [C11's definition of volatile][c11].
/// - Volatile operations, however, may also be used to access memory that is _outside_ of any Rust
/// allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is
/// typically used for CPU and peripheral registers that must be accessed via an I/O memory
/// mapping, most commonly at fixed addresses reserved by the hardware. These often have special
/// semantics associated to their manipulation, and cannot be used as general purpose memory.
/// Here, any address value is possible, including 0 and [`usize::MAX`], so long as the semantics
/// of such a read are well-defined by the target hardware. The provenance of the pointer is
/// irrelevant, and it can be created with [`without_provenance`]. The access must not trap. It
/// can cause side-effects, but those must not affect Rust-allocated memory in any way. This
/// access is still not considered [atomic], and as such it cannot be used for inter-thread
/// synchronization.
///
/// The compiler shouldn't change the relative order or number of volatile
/// memory operations. However, volatile memory operations on zero-sized types
/// (e.g., if a zero-sized type is passed to `read_volatile`) are noops
/// and may be ignored.
/// Note that volatile memory operations where T is a zero-sized type are noops and may be ignored.
///
/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
/// [allocation]: crate::ptr#allocated-object
/// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses
///
/// # Safety
///
/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of whether `T` is
/// [`Copy`]. If `T` is not [`Copy`], using both the returned value and the value at `*src` can
/// [violate memory safety][read-ownership]. However, storing non-[`Copy`] types in volatile memory
/// is almost certainly incorrect.
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `src` must be [valid] for reads.
/// * `src` must be either [valid] for reads, or it must point to memory outside of all Rust
/// allocations and reading from that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `src` must be properly aligned.
///
/// * `src` must point to a properly initialized value of type `T`.
///
/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
/// value and the value at `*src` can [violate memory safety][read-ownership].
/// However, storing non-[`Copy`] types in volatile memory is almost certainly
/// incorrect.
/// * Reading from `src` must produce a properly initialized value of type `T`.
///
/// Note that even if `T` has size `0`, the pointer must be properly aligned.
///
/// [valid]: self#safety
/// [read-ownership]: read#ownership-of-the-returned-value
///
/// Just like in C, whether an operation is volatile has no bearing whatsoever
/// on questions involving concurrent access from multiple threads. Volatile
/// accesses behave exactly like non-atomic accesses in that regard. In particular,
/// a race between a `read_volatile` and any write operation to the same location
/// is undefined behavior.
///
/// # Examples
///
/// Basic usage:
@ -2090,50 +2102,63 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
unsafe {
ub_checks::assert_unsafe_precondition!(
check_language_ub,
"ptr::read_volatile requires that the pointer argument is aligned and non-null",
"ptr::read_volatile requires that the pointer argument is aligned",
(
addr: *const () = src as *const (),
align: usize = align_of::<T>(),
is_zst: bool = T::IS_ZST,
) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst)
) => ub_checks::maybe_is_aligned(addr, align)
);
intrinsics::volatile_load(src)
}
}
/// Performs a volatile write of a memory location with the given value without
/// reading or dropping the old value.
/// Performs a volatile write of a memory location with the given value without reading or dropping
/// the old value.
///
/// Volatile operations are intended to act on I/O memory, and are guaranteed
/// to not be elided or reordered by the compiler across other volatile
/// operations.
/// Volatile operations are intended to act on I/O memory. As such, they are considered externally
/// observable events (just like syscalls), and are guaranteed to not be elided or reordered by the
/// compiler across other externally observable events. With this in mind, there are two cases of
/// usage that need to be distinguished:
///
/// `write_volatile` does not drop the contents of `dst`. This is safe, but it
/// could leak allocations or resources, so care should be taken not to overwrite
/// an object that should be dropped.
/// - When a volatile operation is used for memory inside an [allocation], it behaves exactly like
/// [`write`][write()], except for the additional guarantee that it won't be elided or reordered
/// (see above). This implies that the operation will actually access memory and not e.g. be
/// lowered to a register access. Other than that, all the usual rules for memory accesses apply
/// (including provenance). In particular, just like in C, whether an operation is volatile has no
/// bearing whatsoever on questions involving concurrent access from multiple threads. Volatile
/// accesses behave exactly like non-atomic accesses in that regard.
///
/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
/// location pointed to by `dst`.
/// - Volatile operations, however, may also be used to access memory that is _outside_ of any Rust
/// allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is
/// typically used for CPU and peripheral registers that must be accessed via an I/O memory
/// mapping, most commonly at fixed addresses reserved by the hardware. These often have special
/// semantics associated to their manipulation, and cannot be used as general purpose memory.
/// Here, any address value is possible, including 0 and [`usize::MAX`], so long as the semantics
/// of such a write are well-defined by the target hardware. The provenance of the pointer is
/// irrelevant, and it can be created with [`without_provenance`]. The access must not trap. It
/// can cause side-effects, but those must not affect Rust-allocated memory in any way. This
/// access is still not considered [atomic], and as such it cannot be used for inter-thread
/// synchronization.
///
/// # Notes
/// Note that volatile memory operations on zero-sized types (e.g., if a zero-sized type is passed
/// to `write_volatile`) are noops and may be ignored.
///
/// Rust does not currently have a rigorously and formally defined memory model,
/// so the precise semantics of what "volatile" means here is subject to change
/// over time. That being said, the semantics will almost always end up pretty
/// similar to [C11's definition of volatile][c11].
/// `write_volatile` does not drop the contents of `dst`. This is safe, but it could leak
/// allocations or resources, so care should be taken not to overwrite an object that should be
/// dropped when operating on Rust memory. Additionally, it does not drop `src`. Semantically, `src`
/// is moved into the location pointed to by `dst`.
///
/// The compiler shouldn't change the relative order or number of volatile
/// memory operations. However, volatile memory operations on zero-sized types
/// (e.g., if a zero-sized type is passed to `write_volatile`) are noops
/// and may be ignored.
///
/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
/// [allocation]: crate::ptr#allocated-object
/// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `dst` must be [valid] for writes.
/// * `dst` must be either [valid] for writes, or it must point to memory outside of all Rust
/// allocations and writing to that memory must:
/// - not trap, and
/// - not cause any memory inside a Rust allocation to be modified.
///
/// * `dst` must be properly aligned.
///
@ -2141,12 +2166,6 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
///
/// [valid]: self#safety
///
/// Just like in C, whether an operation is volatile has no bearing whatsoever
/// on questions involving concurrent access from multiple threads. Volatile
/// accesses behave exactly like non-atomic accesses in that regard. In particular,
/// a race between a `write_volatile` and any other operation (reading or writing)
/// on the same location is undefined behavior.
///
/// # Examples
///
/// Basic usage:
@ -2170,12 +2189,11 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
unsafe {
ub_checks::assert_unsafe_precondition!(
check_language_ub,
"ptr::write_volatile requires that the pointer argument is aligned and non-null",
"ptr::write_volatile requires that the pointer argument is aligned",
(
addr: *mut () = dst as *mut (),
align: usize = align_of::<T>(),
is_zst: bool = T::IS_ZST,
) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst)
) => ub_checks::maybe_is_aligned(addr, align)
);
intrinsics::volatile_store(dst, src);
}

View file

@ -2651,7 +2651,6 @@ impl str {
/// you're trying to parse into.
///
/// `parse` can parse into any type that implements the [`FromStr`] trait.
///
/// # Errors
///

View file

@ -120,13 +120,25 @@ pub(crate) const fn maybe_is_aligned_and_not_null(
align: usize,
is_zst: bool,
) -> bool {
// This is just for safety checks so we can const_eval_select.
maybe_is_aligned(ptr, align) && (is_zst || !ptr.is_null())
}
/// Checks whether `ptr` is properly aligned with respect to the given alignment.
///
/// In `const` this is approximate and can fail spuriously. It is primarily intended
/// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the
/// check is anyway not executed in `const`.
#[inline]
#[rustc_allow_const_fn_unstable(const_eval_select)]
pub(crate) const fn maybe_is_aligned(ptr: *const (), align: usize) -> bool {
// This is just for safety checks so we can const_eval_select.
const_eval_select!(
@capture { ptr: *const (), align: usize, is_zst: bool } -> bool:
@capture { ptr: *const (), align: usize } -> bool:
if const {
is_zst || !ptr.is_null()
true
} else {
ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
ptr.is_aligned_to(align)
}
)
}

View file

@ -19,7 +19,6 @@
#![feature(const_deref)]
#![feature(const_destruct)]
#![feature(const_eval_select)]
#![feature(const_float_round_methods)]
#![feature(const_ops)]
#![feature(const_ref_cell)]
#![feature(const_trait_impl)]

View file

@ -329,7 +329,6 @@
#![feature(bstr_internals)]
#![feature(char_internals)]
#![feature(clone_to_uninit)]
#![feature(const_float_round_methods)]
#![feature(core_intrinsics)]
#![feature(core_io_borrowed_buf)]
#![feature(duration_constants)]

View file

@ -44,7 +44,7 @@ impl f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn floor(self) -> f32 {
core::f32::math::floor(self)
@ -67,7 +67,7 @@ impl f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn ceil(self) -> f32 {
core::f32::math::ceil(self)
@ -96,7 +96,7 @@ impl f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn round(self) -> f32 {
core::f32::math::round(self)
@ -123,7 +123,7 @@ impl f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "round_ties_even", since = "1.77.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn round_ties_even(self) -> f32 {
core::f32::math::round_ties_even(self)
@ -149,7 +149,7 @@ impl f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn trunc(self) -> f32 {
core::f32::math::trunc(self)
@ -173,7 +173,7 @@ impl f32 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn fract(self) -> f32 {
core::f32::math::fract(self)

View file

@ -44,7 +44,7 @@ impl f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn floor(self) -> f64 {
core::f64::math::floor(self)
@ -67,7 +67,7 @@ impl f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn ceil(self) -> f64 {
core::f64::math::ceil(self)
@ -96,7 +96,7 @@ impl f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn round(self) -> f64 {
core::f64::math::round(self)
@ -123,7 +123,7 @@ impl f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "round_ties_even", since = "1.77.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn round_ties_even(self) -> f64 {
core::f64::math::round_ties_even(self)
@ -149,7 +149,7 @@ impl f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn trunc(self) -> f64 {
core::f64::math::trunc(self)
@ -173,7 +173,7 @@ impl f64 {
#[rustc_allow_incoherent_impl]
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
#[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
#[inline]
pub const fn fract(self) -> f64 {
core::f64::math::fract(self)

View file

@ -355,7 +355,7 @@ impl Step for CodegenBackend {
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
rustc_cargo_env(builder, &mut cargo, target, build_compiler.stage);
rustc_cargo_env(builder, &mut cargo, target);
let _guard = builder.msg_check(format!("rustc_codegen_{backend}"), target, None);

View file

@ -1316,15 +1316,10 @@ pub fn rustc_cargo(
cargo.env("RUSTC_WRAPPER", ccache);
}
rustc_cargo_env(builder, cargo, target, build_compiler.stage);
rustc_cargo_env(builder, cargo, target);
}
pub fn rustc_cargo_env(
builder: &Builder<'_>,
cargo: &mut Cargo,
target: TargetSelection,
build_stage: u32,
) {
pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
// Set some configuration variables picked up by build scripts and
// the compiler alike
cargo
@ -1379,18 +1374,24 @@ pub fn rustc_cargo_env(
cargo.rustflag("--cfg=llvm_enzyme");
}
// Note that this is disabled if LLVM itself is disabled or we're in a check
// build. If we are in a check build we still go ahead here presuming we've
// detected that LLVM is already built and good to go which helps prevent
// busting caches (e.g. like #71152).
// These conditionals represent a tension between three forces:
// - For non-check builds, we need to define some LLVM-related environment
// variables, requiring LLVM to have been built.
// - For check builds, we want to avoid building LLVM if possible.
// - Check builds and non-check builds should have the same environment if
// possible, to avoid unnecessary rebuilds due to cache-busting.
//
// Therefore we try to avoid building LLVM for check builds, but only if
// building LLVM would be expensive. If "building" LLVM is cheap
// (i.e. it's already built or is downloadable), we prefer to maintain a
// consistent environment between check and non-check builds.
if builder.config.llvm_enabled(target) {
let building_is_expensive =
let building_llvm_is_expensive =
crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
.should_build();
// `top_stage == stage` might be false for `check --stage 1`, if we are building the stage 1 compiler
let can_skip_build = builder.kind == Kind::Check && builder.top_stage == build_stage;
let should_skip_build = building_is_expensive && can_skip_build;
if !should_skip_build {
let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
if !skip_llvm {
rustc_llvm_env(builder, cargo, target)
}
}
@ -1407,6 +1408,9 @@ pub fn rustc_cargo_env(
/// Pass down configuration from the LLVM build into the build of
/// rustc_llvm and rustc_codegen_llvm.
///
/// Note that this has the side-effect of _building LLVM_, which is sometimes
/// unwanted (e.g. for check builds).
fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
if builder.config.is_rust_llvm(target) {
cargo.env("LLVM_RUSTLLVM", "1");
@ -1665,7 +1669,7 @@ impl Step for CodegenBackend {
cargo
.arg("--manifest-path")
.arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
rustc_cargo_env(builder, &mut cargo, target);
// Ideally, we'd have a separate step for the individual codegen backends,
// like we have in tests (test::CodegenGCC) but that would require a lot of restructuring.

View file

@ -1757,6 +1757,10 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
cmd.arg("--host").arg(&*compiler.host.triple);
cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
if let Some(codegen_backend) = builder.config.default_codegen_backend(compiler.host) {
cmd.arg("--codegen-backend").arg(&codegen_backend);
}
if builder.build.config.llvm_enzyme {
cmd.arg("--has-enzyme");
}
@ -1810,7 +1814,24 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
}
let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
flags.push(format!(
"-Cdebuginfo={}",
if suite == "codegen" {
// codegen tests typically check LLVM IR and are sensitive to additional debuginfo.
// So do not apply `rust.debuginfo-level-tests` for codegen tests.
if builder.config.rust_debuginfo_level_tests
!= crate::core::config::DebuginfoLevel::None
{
println!(
"NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
builder.config.rust_debuginfo_level_tests
);
}
crate::core::config::DebuginfoLevel::None
} else {
builder.config.rust_debuginfo_level_tests
}
));
flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
if suite != "mir-opt" {
@ -3387,7 +3408,7 @@ impl Step for CodegenCranelift {
cargo
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
compile::rustc_cargo_env(builder, &mut cargo, target);
// Avoid incremental cache issues when changing rustc
cargo.env("CARGO_BUILD_INCREMENTAL", "false");
@ -3519,7 +3540,7 @@ impl Step for CodegenGCC {
cargo
.arg("--manifest-path")
.arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
compile::rustc_cargo_env(builder, &mut cargo, target);
add_cg_gcc_cargo_flags(&mut cargo, &gcc);
// Avoid incremental cache issues when changing rustc

View file

@ -712,7 +712,11 @@ mod snapshot {
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
");
}
#[test]
fn build_rustc_no_explicit_stage() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
ctx.config("build")
.path("rustc")
@ -1303,17 +1307,19 @@ mod snapshot {
ctx.config("check")
.path("compiler")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
");
}
#[test]
fn check_rustc_no_explicit_stage() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
ctx.config("check")
.path("rustc")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
");
}
@ -1333,7 +1339,6 @@ mod snapshot {
.path("compiler")
.stage(1)
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
@ -1465,7 +1470,6 @@ mod snapshot {
.paths(&["library", "compiler"])
.args(&args)
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
@ -1479,7 +1483,6 @@ mod snapshot {
ctx.config("check")
.path("miri")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> Miri 1 <host>
");
@ -1500,7 +1503,6 @@ mod snapshot {
.path("miri")
.stage(1)
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> Miri 1 <host>
");
@ -1553,7 +1555,6 @@ mod snapshot {
ctx.config("check")
.path("rustc_codegen_cranelift")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> cranelift 1 <host>
[check] rustc 0 <host> -> gcc 1 <host>
@ -1567,7 +1568,6 @@ mod snapshot {
ctx.config("check")
.path("rust-analyzer")
.render_steps(), @r"
[build] llvm <host>
[check] rustc 0 <host> -> rustc 1 <host>
[check] rustc 0 <host> -> rust-analyzer 1 <host>
");

View file

@ -43,4 +43,9 @@ if isWindows && isKnownToBeMingwBuild; then
curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}"
7z x -y mingw.7z > /dev/null
ciCommandAddPath "$(cygpath -m "$(pwd)/${mingw_dir}/bin")"
# Initialize mingw for the user.
# This should be done by github but isn't for some reason.
# (see https://github.com/actions/runner-images/issues/12600)
/c/msys64/usr/bin/bash -lc ' '
fi

View file

@ -205,6 +205,8 @@ settings:
on `wasm32-unknown-unknown` target because the target does not support the
`proc-macro` crate type.
- `needs-target-std` — ignores if target platform does not have std support.
- `ignore-backends` — ignores the listed backends, separated by whitespace characters.
- `needs-backends` — only runs the test if current codegen backend is listed.
The following directives will check LLVM support:

View file

@ -116,7 +116,7 @@ pub(crate) fn build_index(
// Set up alias indexes.
for (i, item) in cache.search_index.iter().enumerate() {
for alias in &item.aliases[..] {
aliases.entry(alias.as_str().to_lowercase()).or_default().push(i);
aliases.entry(alias.to_string()).or_default().push(i);
}
}

View file

@ -219,6 +219,8 @@ declare namespace rustdoc {
crate: string,
descShard: SearchDescShard,
id: number,
// This is the name of the item. For doc aliases, if you want the name of the aliased
// item, take a look at `Row.original.name`.
name: string,
normalizedName: string,
word: string,
@ -227,6 +229,11 @@ declare namespace rustdoc {
path: string,
ty: number,
type: FunctionSearchType | null,
descIndex: number,
bitIndex: number,
implDisambiguator: String | null,
is_alias?: boolean,
original?: Row,
}
/**

View file

@ -830,7 +830,7 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) {
*/
function makePrimitiveElement(name, extra) {
return Object.assign({
name: name,
name,
id: null,
fullPath: [name],
pathWithoutLast: [],
@ -1483,6 +1483,7 @@ class DocSearch {
*/
this.assocTypeIdNameMap = new Map();
this.ALIASES = new Map();
this.FOUND_ALIASES = new Set();
this.rootPath = rootPath;
this.searchState = searchState;
@ -2030,6 +2031,8 @@ class DocSearch {
// normalized names, type signature objects and fingerprints, and aliases.
id = 0;
/** @type {Array<[string, { [key: string]: Array<number> }, number]>} */
const allAliases = [];
for (const [crate, crateCorpus] of rawSearchIndex) {
// a string representing the lengths of each description shard
// a string representing the list of function types
@ -2178,10 +2181,10 @@ class DocSearch {
paths[i] = { ty, name, path, exactPath, unboxFlag };
}
// convert `item*` into an object form, and construct word indices.
// Convert `item*` into an object form, and construct word indices.
//
// before any analysis is performed lets gather the search terms to
// search against apart from the rest of the data. This is a quick
// Before any analysis is performed, let's gather the search terms to
// search against apart from the rest of the data. This is a quick
// operation that is cached for the life of the page state so that
// all other search operations have access to this cached data for
// faster analysis operations
@ -2269,29 +2272,58 @@ class DocSearch {
}
if (aliases) {
const currentCrateAliases = new Map();
this.ALIASES.set(crate, currentCrateAliases);
for (const alias_name in aliases) {
if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) {
continue;
}
/** @type{number[]} */
let currentNameAliases;
if (currentCrateAliases.has(alias_name)) {
currentNameAliases = currentCrateAliases.get(alias_name);
} else {
currentNameAliases = [];
currentCrateAliases.set(alias_name, currentNameAliases);
}
for (const local_alias of aliases[alias_name]) {
currentNameAliases.push(local_alias + currentIndex);
}
}
// We need to add the aliases in `searchIndex` after we finished filling it
// to not mess up indexes.
allAliases.push([crate, aliases, currentIndex]);
}
currentIndex += itemTypes.length;
this.searchState.descShards.set(crate, descShardList);
}
for (const [crate, aliases, index] of allAliases) {
for (const [alias_name, alias_refs] of Object.entries(aliases)) {
if (!this.ALIASES.has(crate)) {
this.ALIASES.set(crate, new Map());
}
const word = alias_name.toLowerCase();
const crate_alias_map = this.ALIASES.get(crate);
if (!crate_alias_map.has(word)) {
crate_alias_map.set(word, []);
}
const aliases_map = crate_alias_map.get(word);
const normalizedName = word.indexOf("_") === -1 ? word : word.replace(/_/g, "");
for (const alias of alias_refs) {
const originalIndex = alias + index;
const original = searchIndex[originalIndex];
/** @type {rustdoc.Row} */
const row = {
crate,
name: alias_name,
normalizedName,
is_alias: true,
ty: original.ty,
type: original.type,
paramNames: [],
word,
id,
parent: undefined,
original,
path: "",
implDisambiguator: original.implDisambiguator,
// Needed to load the description of the original item.
// @ts-ignore
descShard: original.descShard,
descIndex: original.descIndex,
bitIndex: original.bitIndex,
};
aliases_map.push(row);
this.nameTrie.insert(normalizedName, id, this.tailTable);
id += 1;
searchIndex.push(row);
}
}
}
// Drop the (rather large) hash table used for reusing function items
this.TYPES_POOL = new Map();
return searchIndex;
@ -2536,6 +2568,8 @@ class DocSearch {
parsedQuery.elems.reduce((acc, next) => acc + next.pathLast.length, 0) +
parsedQuery.returned.reduce((acc, next) => acc + next.pathLast.length, 0);
const maxEditDistance = Math.floor(queryLen / 3);
// We reinitialize the `FOUND_ALIASES` map.
this.FOUND_ALIASES.clear();
/**
* @type {Map<string, number>}
@ -2695,6 +2729,10 @@ class DocSearch {
const buildHrefAndPath = item => {
let displayPath;
let href;
if (item.is_alias) {
this.FOUND_ALIASES.add(item.word);
item = item.original;
}
const type = itemTypes[item.ty];
const name = item.name;
let path = item.path;
@ -3198,8 +3236,7 @@ class DocSearch {
result.item = this.searchIndex[result.id];
result.word = this.searchIndex[result.id].word;
if (isReturnTypeQuery) {
// we are doing a return-type based search,
// deprioritize "clone-like" results,
// We are doing a return-type based search, deprioritize "clone-like" results,
// ie. functions that also take the queried type as an argument.
const resultItemType = result.item && result.item.type;
if (!resultItemType) {
@ -4259,28 +4296,13 @@ class DocSearch {
return false;
}
// this does not yet have a type in `rustdoc.d.ts`.
// @ts-expect-error
function createAliasFromItem(item) {
return {
crate: item.crate,
name: item.name,
path: item.path,
descShard: item.descShard,
descIndex: item.descIndex,
exactPath: item.exactPath,
ty: item.ty,
parent: item.parent,
type: item.type,
is_alias: true,
bitIndex: item.bitIndex,
implDisambiguator: item.implDisambiguator,
};
}
// @ts-expect-error
const handleAliases = async(ret, query, filterCrates, currentCrate) => {
const lowerQuery = query.toLowerCase();
if (this.FOUND_ALIASES.has(lowerQuery)) {
return;
}
this.FOUND_ALIASES.add(lowerQuery);
// We separate aliases and crate aliases because we want to have current crate
// aliases to be before the others in the displayed results.
// @ts-expect-error
@ -4292,7 +4314,7 @@ class DocSearch {
&& this.ALIASES.get(filterCrates).has(lowerQuery)) {
const query_aliases = this.ALIASES.get(filterCrates).get(lowerQuery);
for (const alias of query_aliases) {
aliases.push(createAliasFromItem(this.searchIndex[alias]));
aliases.push(alias);
}
}
} else {
@ -4302,7 +4324,7 @@ class DocSearch {
const pushTo = crate === currentCrate ? crateAliases : aliases;
const query_aliases = crateAliasesIndex.get(lowerQuery);
for (const alias of query_aliases) {
pushTo.push(createAliasFromItem(this.searchIndex[alias]));
pushTo.push(alias);
}
}
}
@ -4310,9 +4332,9 @@ class DocSearch {
// @ts-expect-error
const sortFunc = (aaa, bbb) => {
if (aaa.path < bbb.path) {
if (aaa.original.path < bbb.original.path) {
return 1;
} else if (aaa.path === bbb.path) {
} else if (aaa.original.path === bbb.original.path) {
return 0;
}
return -1;
@ -4321,21 +4343,10 @@ class DocSearch {
crateAliases.sort(sortFunc);
aliases.sort(sortFunc);
// @ts-expect-error
const fetchDesc = alias => {
// @ts-expect-error
return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex) ?
"" : this.searchState.loadDesc(alias);
};
const [crateDescs, descs] = await Promise.all([
// @ts-expect-error
Promise.all(crateAliases.map(fetchDesc)),
Promise.all(aliases.map(fetchDesc)),
]);
// @ts-expect-error
const pushFunc = alias => {
alias.alias = query;
// Cloning `alias` to prevent its fields to be updated.
alias = {...alias};
const res = buildHrefAndPath(alias);
alias.displayPath = pathSplitter(res[0]);
alias.fullPath = alias.displayPath + alias.name;
@ -4347,16 +4358,8 @@ class DocSearch {
}
};
aliases.forEach((alias, i) => {
// @ts-expect-error
alias.desc = descs[i];
});
aliases.forEach(pushFunc);
// @ts-expect-error
crateAliases.forEach((alias, i) => {
alias.desc = crateDescs[i];
});
// @ts-expect-error
crateAliases.forEach(pushFunc);
};
@ -4802,7 +4805,7 @@ async function addTab(array, query, display) {
output.className = "search-results " + extraClass;
const lis = Promise.all(array.map(async item => {
const name = item.name;
const name = item.is_alias ? item.original.name : item.name;
const type = itemTypes[item.ty];
const longType = longItemTypes[item.ty];
const typeName = longType.length !== 0 ? `${longType}` : "?";
@ -4822,7 +4825,7 @@ async function addTab(array, query, display) {
let alias = " ";
if (item.is_alias) {
alias = ` <div class="alias">\
<b>${item.alias}</b><i class="grey">&nbsp;- see&nbsp;</i>\
<b>${item.name}</b><i class="grey">&nbsp;- see&nbsp;</i>\
</div>`;
}
resultName.insertAdjacentHTML(
@ -5201,6 +5204,7 @@ function registerSearchEvents() {
if (searchState.input.value.length === 0) {
searchState.hideResults();
} else {
// @ts-ignore
searchState.timeout = setTimeout(search, 500);
}
};
@ -5842,8 +5846,8 @@ Lev1TParametricDescription.prototype.offsetIncrs3 = /*2 bits per value */ new In
// be called ONLY when the whole file has been parsed and loaded.
// @ts-expect-error
function initSearch(searchIndx) {
rawSearchIndex = searchIndx;
function initSearch(searchIndex) {
rawSearchIndex = searchIndex;
if (typeof window !== "undefined") {
// @ts-expect-error
docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState);

@ -1 +1 @@
Subproject commit d3c793b025645a4565ac59aceb30d2d116ff1a41
Subproject commit e8a2ffcf322f45b8dce82c65ab27a3e2430a6b51

View file

@ -175,6 +175,36 @@ pub enum Sanitizer {
Hwaddress,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum CodegenBackend {
Cranelift,
Gcc,
Llvm,
}
impl<'a> TryFrom<&'a str> for CodegenBackend {
type Error = &'static str;
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
match value.to_lowercase().as_str() {
"cranelift" => Ok(Self::Cranelift),
"gcc" => Ok(Self::Gcc),
"llvm" => Ok(Self::Llvm),
_ => Err("unknown backend"),
}
}
}
impl CodegenBackend {
pub fn as_str(self) -> &'static str {
match self {
Self::Cranelift => "cranelift",
Self::Gcc => "gcc",
Self::Llvm => "llvm",
}
}
}
/// Configuration for `compiletest` *per invocation*.
///
/// In terms of `bootstrap`, this means that `./x test tests/ui tests/run-make` actually correspond
@ -651,6 +681,9 @@ pub struct Config {
/// need `core` stubs in cross-compilation scenarios that do not otherwise want/need to
/// `-Zbuild-std`. Used in e.g. ABI tests.
pub minicore_path: Utf8PathBuf,
/// Current codegen backend used.
pub codegen_backend: CodegenBackend,
}
impl Config {
@ -753,6 +786,7 @@ impl Config {
profiler_runtime: Default::default(),
diff_command: Default::default(),
minicore_path: Default::default(),
codegen_backend: CodegenBackend::Llvm,
}
}

View file

@ -9,7 +9,7 @@ use camino::{Utf8Path, Utf8PathBuf};
use semver::Version;
use tracing::*;
use crate::common::{Config, Debugger, FailMode, PassMode, RunFailMode, TestMode};
use crate::common::{CodegenBackend, Config, Debugger, FailMode, PassMode, RunFailMode, TestMode};
use crate::debuggers::{extract_cdb_version, extract_gdb_version};
use crate::directives::auxiliary::{AuxProps, parse_and_update_aux};
use crate::directives::needs::CachedNeedsConditions;
@ -818,6 +818,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"ignore-arm-unknown-linux-musleabihf",
"ignore-auxiliary",
"ignore-avr",
"ignore-backends",
"ignore-beta",
"ignore-cdb",
"ignore-compare-mode-next-solver",
@ -907,6 +908,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"min-llvm-version",
"min-system-llvm-version",
"needs-asm-support",
"needs-backends",
"needs-crate-type",
"needs-deterministic-layouts",
"needs-dlltool",
@ -1669,6 +1671,8 @@ pub(crate) fn make_test_description<R: Read>(
decision!(cfg::handle_only(config, ln));
decision!(needs::handle_needs(&cache.needs, config, ln));
decision!(ignore_llvm(config, path, ln));
decision!(ignore_backends(config, path, ln));
decision!(needs_backends(config, path, ln));
decision!(ignore_cdb(config, ln));
decision!(ignore_gdb(config, ln));
decision!(ignore_lldb(config, ln));
@ -1795,6 +1799,49 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
IgnoreDecision::Continue
}
fn ignore_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
if let Some(backends_to_ignore) = config.parse_name_value_directive(line, "ignore-backends") {
for backend in backends_to_ignore.split_whitespace().map(|backend| {
match CodegenBackend::try_from(backend) {
Ok(backend) => backend,
Err(error) => {
panic!("Invalid ignore-backends value `{backend}` in `{path}`: {error}")
}
}
}) {
if config.codegen_backend == backend {
return IgnoreDecision::Ignore {
reason: format!("{} backend is marked as ignore", backend.as_str()),
};
}
}
}
IgnoreDecision::Continue
}
fn needs_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
if let Some(needed_backends) = config.parse_name_value_directive(line, "needs-backends") {
if !needed_backends
.split_whitespace()
.map(|backend| match CodegenBackend::try_from(backend) {
Ok(backend) => backend,
Err(error) => {
panic!("Invalid needs-backends value `{backend}` in `{path}`: {error}")
}
})
.any(|backend| config.codegen_backend == backend)
{
return IgnoreDecision::Ignore {
reason: format!(
"{} backend is not part of required backends",
config.codegen_backend.as_str()
),
};
}
}
IgnoreDecision::Continue
}
fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
if let Some(needed_components) =
config.parse_name_value_directive(line, "needs-llvm-components")

View file

@ -39,7 +39,7 @@ use walkdir::WalkDir;
use self::directives::{EarlyProps, make_test_description};
use crate::common::{
CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
CodegenBackend, CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
expected_output_path, output_base_dir, output_relative_path,
};
use crate::directives::DirectivesCache;
@ -203,6 +203,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
"debugger",
"only test a specific debugger in debuginfo tests",
"gdb | lldb | cdb",
)
.optopt(
"",
"codegen-backend",
"the codegen backend currently used",
"CODEGEN BACKEND NAME",
);
let (argv0, args_) = args.split_first().unwrap();
@ -264,6 +270,15 @@ pub fn parse_config(args: Vec<String>) -> Config {
|| directives::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
);
let codegen_backend = match matches.opt_str("codegen-backend").as_deref() {
Some(backend) => match CodegenBackend::try_from(backend) {
Ok(backend) => backend,
Err(error) => panic!("invalid value `{backend}` for `--codegen-backend`: {error}"),
},
// By default, it's always llvm.
None => CodegenBackend::Llvm,
};
let run_ignored = matches.opt_present("ignored");
let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions");
let with_std_debug_assertions = matches.opt_present("with-std-debug-assertions");
@ -449,6 +464,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
diff_command: matches.opt_str("compiletest-diff-tool"),
minicore_path: opt_path(matches, "minicore-path"),
codegen_backend,
}
}

View file

@ -1 +1 @@
6707bf0f59485cf054ac1095725df43220e4be20
460259d14de0274b97b8801e08cb2fe5f16fdac5

View file

@ -157,7 +157,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.get_alloc_bytes_unchecked_raw(alloc_id)?
}
}
AllocKind::Function | AllocKind::VTable => {
AllocKind::Function | AllocKind::Virtual => {
// Allocate some dummy memory to get a unique address for this function/vtable.
let alloc_bytes = MiriAllocBytes::from_bytes(
&[0u8; 1],

View file

@ -650,7 +650,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
dcx.log_protector();
}
},
AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
AllocKind::Function | AllocKind::Virtual | AllocKind::Dead => {
// No stacked borrows on these allocations.
}
}
@ -1021,7 +1021,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
trace!("Stacked Borrows tag {tag:?} exposed in {alloc_id:?}");
alloc_extra.borrow_tracker_sb().borrow_mut().exposed_tags.insert(tag);
}
AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
AllocKind::Function | AllocKind::Virtual | AllocKind::Dead => {
// No stacked borrows on these allocations.
}
}

View file

@ -673,7 +673,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
trace!("Tree Borrows tag {tag:?} exposed in {alloc_id:?}");
alloc_extra.borrow_tracker_tb().borrow_mut().expose_tag(tag);
}
AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
AllocKind::Function | AllocKind::Virtual | AllocKind::Dead => {
// No tree borrows on these allocations.
}
}

View file

@ -1,11 +1,15 @@
error: internal compiler error: compiler/rustc_mir_transform/src/validate.rs:LL:CC: broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]:
place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection)
--> tests/panic/mir-validation.rs:LL:CC
|
LL | *(tuple.0) = 1;
| ^^^^^^^^^^^^^^
thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC:
broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]:
place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection)
Box<dyn Any>
stack backtrace:
error: the compiler unexpectedly panicked. this is a bug.
@ -20,3 +24,5 @@ LL | extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
error: aborting due to 1 previous error

View file

@ -0,0 +1,19 @@
use std::any::{Any, TypeId};
fn main() {
let t1 = TypeId::of::<u64>();
let t2 = TypeId::of::<u64>();
assert_eq!(t1, t2);
let t3 = TypeId::of::<usize>();
assert_ne!(t1, t3);
let _ = format!("{t1:?}"); // test that we can debug-print
let b = Box::new(0u64) as Box<dyn Any>;
assert_eq!(*b.downcast_ref::<u64>().unwrap(), 0);
assert!(b.downcast_ref::<usize>().is_none());
// Get the first pointer chunk and try to make it a ZST ref.
// This used to trigger an error because TypeId allocs got misclassified as "LiveData".
let _raw_chunk = unsafe { (&raw const t1).cast::<&()>().read() };
}

View file

@ -19,9 +19,9 @@ dependencies = [
[[package]]
name = "ammonia"
version = "4.1.0"
version = "4.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ada2ee439075a3e70b6992fce18ac4e407cd05aea9ca3f75d2c0b0c20bbb364"
checksum = "d6b346764dd0814805de8abf899fe03065bcee69bb1a4771c785817e39f3978f"
dependencies = [
"cssparser",
"html5ever",
@ -156,9 +156,9 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]]
name = "cc"
version = "1.2.29"
version = "1.2.30"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362"
checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
dependencies = [
"shlex",
]
@ -185,9 +185,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.40"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
dependencies = [
"clap_builder",
"clap_derive",
@ -195,9 +195,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.40"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
dependencies = [
"anstream",
"anstyle",
@ -208,18 +208,18 @@ dependencies = [
[[package]]
name = "clap_complete"
version = "4.5.54"
version = "4.5.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aad5b1b4de04fead402672b48897030eec1f3bfe1550776322f59f6d6e6a5677"
checksum = "a5abde44486daf70c5be8b8f8f1b66c49f86236edf6fa2abadb4d961c4c6229a"
dependencies = [
"clap",
]
[[package]]
name = "clap_derive"
version = "4.5.40"
version = "4.5.41"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
dependencies = [
"heck",
"proc-macro2",
@ -256,9 +256,9 @@ dependencies = [
[[package]]
name = "crc32fast"
version = "1.4.2"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
dependencies = [
"cfg-if",
]
@ -582,12 +582,11 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "html5ever"
version = "0.31.0"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "953cbbe631aae7fc0a112702ad5d3aaf09da38beaf45ea84610d6e1c358f569c"
checksum = "55d958c2f74b664487a2035fe1dadb032c48718a03b63f3ab0b8537db8549ed4"
dependencies = [
"log",
"mac",
"markup5ever",
"match_token",
]
@ -863,9 +862,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
[[package]]
name = "markup5ever"
version = "0.16.2"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2e4cd8c02f18a011991a039855480c64d74291c5792fcc160d55d77dc4de4a39"
checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3"
dependencies = [
"log",
"tendril",
@ -874,9 +873,9 @@ dependencies = [
[[package]]
name = "match_token"
version = "0.1.0"
version = "0.35.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf"
dependencies = [
"proc-macro2",
"quote",
@ -1394,15 +1393,15 @@ dependencies = [
[[package]]
name = "rustix"
version = "1.0.7"
version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags 2.9.1",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.59.0",
"windows-sys 0.60.2",
]
[[package]]
@ -1460,9 +1459,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.140"
version = "1.0.141"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
dependencies = [
"itoa",
"memchr",
@ -2103,9 +2102,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
[[package]]
name = "winnow"
version = "0.7.11"
version = "0.7.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
dependencies = [
"memchr",
]

View file

@ -28,7 +28,14 @@ function readFile(filePath) {
}
function contentToDiffLine(key, value) {
return `"${key}": "${value}",`;
if (typeof value === "object" && !Array.isArray(value) && value !== null) {
const out = Object.entries(value)
.filter(([subKey, _]) => ["path", "name"].includes(subKey))
.map(([subKey, subValue]) => `"${subKey}": ${JSON.stringify(subValue)}`)
.join(", ");
return `"${key}": ${out},`;
}
return `"${key}": ${JSON.stringify(value)},`;
}
function shouldIgnoreField(fieldName) {
@ -37,47 +44,61 @@ function shouldIgnoreField(fieldName) {
fieldName === "proposeCorrectionTo";
}
function valueMapper(key, testOutput) {
const isAlias = testOutput["is_alias"];
let value = testOutput[key];
// To make our life easier, if there is a "parent" type, we add it to the path.
if (key === "path") {
if (testOutput["parent"] !== undefined) {
if (value.length > 0) {
value += "::" + testOutput["parent"]["name"];
} else {
value = testOutput["parent"]["name"];
}
} else if (testOutput["is_alias"]) {
value = valueMapper(key, testOutput["original"]);
}
} else if (isAlias && key === "alias") {
value = testOutput["name"];
} else if (isAlias && ["name"].includes(key)) {
value = testOutput["original"][key];
}
return value;
}
// This function is only called when no matching result was found and therefore will only display
// the diff between the two items.
function betterLookingDiff(entry, data) {
function betterLookingDiff(expected, testOutput) {
let output = " {\n";
const spaces = " ";
for (const key in entry) {
if (!Object.prototype.hasOwnProperty.call(entry, key)) {
const spaces = " ";
for (const key in expected) {
if (!Object.prototype.hasOwnProperty.call(expected, key)) {
continue;
}
if (!data || !Object.prototype.hasOwnProperty.call(data, key)) {
output += "-" + spaces + contentToDiffLine(key, entry[key]) + "\n";
if (!testOutput || !Object.prototype.hasOwnProperty.call(testOutput, key)) {
output += "-" + spaces + contentToDiffLine(key, expected[key]) + "\n";
continue;
}
const value = data[key];
if (value !== entry[key]) {
output += "-" + spaces + contentToDiffLine(key, entry[key]) + "\n";
const value = valueMapper(key, testOutput);
if (value !== expected[key]) {
output += "-" + spaces + contentToDiffLine(key, expected[key]) + "\n";
output += "+" + spaces + contentToDiffLine(key, value) + "\n";
} else {
output += spaces + contentToDiffLine(key, value) + "\n";
output += spaces + " " + contentToDiffLine(key, value) + "\n";
}
}
return output + " }";
}
function lookForEntry(entry, data) {
return data.findIndex(data_entry => {
function lookForEntry(expected, testOutput) {
return testOutput.findIndex(testOutputEntry => {
let allGood = true;
for (const key in entry) {
if (!Object.prototype.hasOwnProperty.call(entry, key)) {
for (const key in expected) {
if (!Object.prototype.hasOwnProperty.call(expected, key)) {
continue;
}
let value = data_entry[key];
// To make our life easier, if there is a "parent" type, we add it to the path.
if (key === "path" && data_entry["parent"] !== undefined) {
if (value.length > 0) {
value += "::" + data_entry["parent"]["name"];
} else {
value = data_entry["parent"]["name"];
}
}
if (value !== entry[key]) {
const value = valueMapper(key, testOutputEntry);
if (value !== expected[key]) {
allGood = false;
break;
}

View file

@ -1,7 +1,7 @@
[package]
name = "unicode-table-generator"
version = "0.1.0"
edition = "2021"
edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -21,7 +21,7 @@ impl RawEmitter {
let points = ranges
.iter()
.flat_map(|r| (r.start..r.end).into_iter().collect::<Vec<u32>>())
.flat_map(|r| (r.start..r.end).collect::<Vec<u32>>())
.collect::<Vec<u32>>();
println!("there are {} points", points.len());
@ -32,21 +32,20 @@ impl RawEmitter {
// assert that there is no whitespace over the 0x3000 range.
assert!(point <= 0x3000, "the highest unicode whitespace value has changed");
let high_bytes = point as usize >> 8;
let codepoints = codepoints_by_high_bytes.entry(high_bytes).or_insert_with(Vec::new);
let codepoints = codepoints_by_high_bytes.entry(high_bytes).or_default();
codepoints.push(point);
}
let mut bit_for_high_byte = 1u8;
let mut arms = Vec::<String>::new();
let mut high_bytes: Vec<usize> =
codepoints_by_high_bytes.keys().map(|k| k.clone()).collect();
let mut high_bytes: Vec<usize> = codepoints_by_high_bytes.keys().copied().collect();
high_bytes.sort();
for high_byte in high_bytes {
let codepoints = codepoints_by_high_bytes.get_mut(&high_byte).unwrap();
if codepoints.len() == 1 {
let ch = codepoints.pop().unwrap();
arms.push(format!("{} => c as u32 == {:#04x}", high_byte, ch));
arms.push(format!("{high_byte} => c as u32 == {ch:#04x}"));
continue;
}
// more than 1 codepoint in this arm
@ -54,8 +53,7 @@ impl RawEmitter {
map[(*codepoint & 0xff) as usize] |= bit_for_high_byte;
}
arms.push(format!(
"{} => WHITESPACE_MAP[c as usize & 0xff] & {} != 0",
high_byte, bit_for_high_byte
"{high_byte} => WHITESPACE_MAP[c as usize & 0xff] & {bit_for_high_byte} != 0"
));
bit_for_high_byte <<= 1;
}
@ -68,7 +66,7 @@ impl RawEmitter {
writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap();
writeln!(&mut self.file, " match c as u32 >> 8 {{").unwrap();
for arm in arms {
writeln!(&mut self.file, " {},", arm).unwrap();
writeln!(&mut self.file, " {arm},").unwrap();
}
writeln!(&mut self.file, " _ => false,").unwrap();
writeln!(&mut self.file, " }}").unwrap();

View file

@ -9,7 +9,7 @@ const INDEX_MASK: u32 = 1 << 22;
pub(crate) fn generate_case_mapping(data: &UnicodeData) -> String {
let mut file = String::new();
write!(file, "const INDEX_MASK: u32 = 0x{:x};", INDEX_MASK).unwrap();
write!(file, "const INDEX_MASK: u32 = 0x{INDEX_MASK:x};").unwrap();
file.push_str("\n\n");
file.push_str(HEADER.trim_start());
file.push('\n');

View file

@ -160,15 +160,15 @@ fn load_data() -> UnicodeData {
.push(Codepoints::Single(row.codepoint));
}
if let Some(mapped) = row.simple_lowercase_mapping {
if mapped != row.codepoint {
to_lower.insert(row.codepoint.value(), (mapped.value(), 0, 0));
}
if let Some(mapped) = row.simple_lowercase_mapping
&& mapped != row.codepoint
{
to_lower.insert(row.codepoint.value(), (mapped.value(), 0, 0));
}
if let Some(mapped) = row.simple_uppercase_mapping {
if mapped != row.codepoint {
to_upper.insert(row.codepoint.value(), (mapped.value(), 0, 0));
}
if let Some(mapped) = row.simple_uppercase_mapping
&& mapped != row.codepoint
{
to_upper.insert(row.codepoint.value(), (mapped.value(), 0, 0));
}
}
@ -196,12 +196,12 @@ fn load_data() -> UnicodeData {
.flat_map(|codepoints| match codepoints {
Codepoints::Single(c) => c
.scalar()
.map(|ch| (ch as u32..ch as u32 + 1))
.map(|ch| ch as u32..ch as u32 + 1)
.into_iter()
.collect::<Vec<_>>(),
Codepoints::Range(c) => c
.into_iter()
.flat_map(|c| c.scalar().map(|ch| (ch as u32..ch as u32 + 1)))
.flat_map(|c| c.scalar().map(|ch| ch as u32..ch as u32 + 1))
.collect::<Vec<_>>(),
})
.collect::<Vec<Range<u32>>>(),
@ -236,7 +236,7 @@ fn main() {
let ranges_by_property = &unicode_data.ranges;
if let Some(path) = test_path {
std::fs::write(&path, generate_tests(&write_location, &ranges_by_property)).unwrap();
std::fs::write(&path, generate_tests(&write_location, ranges_by_property)).unwrap();
}
let mut total_bytes = 0;
@ -246,9 +246,9 @@ fn main() {
let mut emitter = RawEmitter::new();
if property == &"White_Space" {
emit_whitespace(&mut emitter, &ranges);
emit_whitespace(&mut emitter, ranges);
} else {
emit_codepoints(&mut emitter, &ranges);
emit_codepoints(&mut emitter, ranges);
}
modules.push((property.to_lowercase().to_string(), emitter.file));
@ -288,7 +288,7 @@ fn main() {
for line in contents.lines() {
if !line.trim().is_empty() {
table_file.push_str(" ");
table_file.push_str(&line);
table_file.push_str(line);
}
table_file.push('\n');
}
@ -312,7 +312,7 @@ fn version() -> String {
let start = readme.find(prefix).unwrap() + prefix.len();
let end = readme.find(" of the Unicode Standard.").unwrap();
let version =
readme[start..end].split('.').map(|v| v.parse::<u32>().expect(&v)).collect::<Vec<_>>();
readme[start..end].split('.').map(|v| v.parse::<u32>().expect(v)).collect::<Vec<_>>();
let [major, minor, micro] = [version[0], version[1], version[2]];
out.push_str(&format!("({major}, {minor}, {micro});\n"));
@ -320,7 +320,7 @@ fn version() -> String {
}
fn fmt_list<V: std::fmt::Debug>(values: impl IntoIterator<Item = V>) -> String {
let pieces = values.into_iter().map(|b| format!("{:?}, ", b)).collect::<Vec<_>>();
let pieces = values.into_iter().map(|b| format!("{b:?}, ")).collect::<Vec<_>>();
let mut out = String::new();
let mut line = String::from("\n ");
for piece in pieces {
@ -348,7 +348,7 @@ fn generate_tests(data_path: &str, ranges: &[(&str, Vec<Range<u32>>)]) -> String
s.push_str("\nfn main() {\n");
for (property, ranges) in ranges {
s.push_str(&format!(r#" println!("Testing {}");"#, property));
s.push_str(&format!(r#" println!("Testing {property}");"#));
s.push('\n');
s.push_str(&format!(" {}_true();\n", property.to_lowercase()));
s.push_str(&format!(" {}_false();\n", property.to_lowercase()));
@ -373,7 +373,7 @@ fn generate_tests(data_path: &str, ranges: &[(&str, Vec<Range<u32>>)]) -> String
s.push_str(" }\n\n");
}
s.push_str("}");
s.push('}');
s
}
@ -388,7 +388,7 @@ fn generate_asserts(s: &mut String, property: &str, points: &[u32], truthy: bool
range.start,
));
} else {
s.push_str(&format!(" for chn in {:?}u32 {{\n", range));
s.push_str(&format!(" for chn in {range:?}u32 {{\n"));
s.push_str(&format!(
" assert!({}unicode_data::{}::lookup(std::char::from_u32(chn).unwrap()), \"{{:?}}\", chn);\n",
if truthy { "" } else { "!" },
@ -439,7 +439,7 @@ fn merge_ranges(ranges: &mut Vec<Range<u32>>) {
let mut last_end = None;
for range in ranges {
if let Some(last) = last_end {
assert!(range.start > last, "{:?}", range);
assert!(range.start > last, "{range:?}");
}
last_end = Some(range.end);
}

View file

@ -156,10 +156,10 @@ pub fn emit_codepoints(emitter: &mut RawEmitter, ranges: &[Range<u32>]) {
emitter.blank_line();
let mut bitset = emitter.clone();
let bitset_ok = bitset.emit_bitset(&ranges).is_ok();
let bitset_ok = bitset.emit_bitset(ranges).is_ok();
let mut skiplist = emitter.clone();
skiplist.emit_skiplist(&ranges);
skiplist.emit_skiplist(ranges);
if bitset_ok && bitset.bytes_used <= skiplist.bytes_used {
*emitter = bitset;
@ -174,7 +174,7 @@ pub fn emit_whitespace(emitter: &mut RawEmitter, ranges: &[Range<u32>]) {
emitter.blank_line();
let mut cascading = emitter.clone();
cascading.emit_cascading_map(&ranges);
cascading.emit_cascading_map(ranges);
*emitter = cascading;
emitter.desc = String::from("cascading");
}
@ -272,7 +272,7 @@ impl Canonicalized {
// for canonical when possible.
while let Some((&to, _)) = mappings
.iter()
.find(|(&to, _)| to == 0)
.find(|&(&to, _)| to == 0)
.or_else(|| mappings.iter().max_by_key(|m| m.1.len()))
{
// Get the mapping with the most entries. Currently, no mapping can
@ -311,10 +311,9 @@ impl Canonicalized {
}
}
}
assert!(
unique_mapping
.insert(to, UniqueMapping::Canonical(canonical_words.len()))
.is_none()
assert_eq!(
unique_mapping.insert(to, UniqueMapping::Canonical(canonical_words.len())),
None
);
canonical_words.push(to);
@ -340,14 +339,10 @@ impl Canonicalized {
// We'll probably always have some slack though so this loop will still
// be needed.
for &w in unique_words {
if !unique_mapping.contains_key(&w) {
assert!(
unique_mapping
.insert(w, UniqueMapping::Canonical(canonical_words.len()))
.is_none()
);
unique_mapping.entry(w).or_insert_with(|| {
canonical_words.push(w);
}
UniqueMapping::Canonical(canonical_words.len())
});
}
assert_eq!(canonicalized_words.len() + canonical_words.len(), unique_words.len());
assert_eq!(unique_mapping.len(), unique_words.len());

View file

@ -2,7 +2,7 @@
// other architectures (including ARM and x86-64) use the prefix `.Lanon.`
//@ only-linux
//@ assembly-output: emit-asm
//@ compile-flags: --crate-type=lib -Copt-level=3
//@ compile-flags: --crate-type=lib -Copt-level=3 -Cllvm-args=-enable-global-merge=0
//@ edition: 2024
use std::ffi::CStr;

View file

@ -8,6 +8,14 @@
//@ min-llvm-version: 21.0.0
#![crate_type = "lib"]
#![feature(no_core)]
#![no_core]
extern crate minicore;
unsafe extern "C" {
safe fn add(x: i32, y: i32) -> i32;
}
pub fn add_one(x: i32) -> i32 {
// CHECK-LABEL: __cfi__{{.*}}7add_one{{.*}}:
@ -23,7 +31,7 @@ pub fn add_one(x: i32) -> i32 {
// CHECK-NEXT: nop
// CHECK-NEXT: nop
// CHECK-NEXT: mov ecx, 2628068948
x + 1
add(x, 1)
}
pub fn add_two(x: i32, _y: i32) -> i32 {
@ -40,7 +48,7 @@ pub fn add_two(x: i32, _y: i32) -> i32 {
// CHECK-NEXT: nop
// CHECK-NEXT: nop
// CHECK-NEXT: mov edx, 2505940310
x + 2
add(x, 2)
}
pub fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
@ -57,5 +65,5 @@ pub fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
// CHECK-NEXT: nop
// CHECK-NEXT: nop
// CHECK-NEXT: mov edx, 653723426
f(arg) + f(arg)
add(f(arg), f(arg))
}

View file

@ -2,7 +2,6 @@
//@ assembly-output: emit-asm
//@ compile-flags: -C target-feature=+exception-handling
//@ compile-flags: -C panic=unwind
//@ compile-flags: -C llvm-args=-wasm-enable-eh
#![crate_type = "lib"]
#![feature(core_intrinsics)]

View file

@ -0,0 +1,28 @@
//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes
// This test is here to hit the `Rvalue::Repeat` case in `codegen_rvalue_operand`.
// It only applies when the resulting array is a ZST, so the test is written in
// such a way as to keep MIR optimizations from seeing that fact and removing
// the local and statement altogether. (At the time of writing, no other codegen
// test hit that code path, nor did a stage 2 build of the compiler.)
#![crate_type = "lib"]
#[repr(transparent)]
pub struct Wrapper<T, const N: usize>([T; N]);
// CHECK-LABEL: define {{.+}}do_repeat{{.+}}(i32 noundef %x)
// CHECK-NEXT: start:
// CHECK-NOT: alloca
// CHECK-NEXT: ret void
#[inline(never)]
pub fn do_repeat<T: Copy, const N: usize>(x: T) -> Wrapper<T, N> {
Wrapper([x; N])
}
// CHECK-LABEL: @trigger_repeat_zero_len
#[no_mangle]
pub fn trigger_repeat_zero_len() -> Wrapper<u32, 0> {
// CHECK: call void {{.+}}do_repeat{{.+}}(i32 noundef 4)
do_repeat(4)
}

View file

@ -0,0 +1,28 @@
//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes
// This test is here to hit the `Rvalue::Repeat` case in `codegen_rvalue_operand`.
// It only applies when the resulting array is a ZST, so the test is written in
// such a way as to keep MIR optimizations from seeing that fact and removing
// the local and statement altogether. (At the time of writing, no other codegen
// test hit that code path, nor did a stage 2 build of the compiler.)
#![crate_type = "lib"]
#[repr(transparent)]
pub struct Wrapper<T, const N: usize>([T; N]);
// CHECK-LABEL: define {{.+}}do_repeat{{.+}}()
// CHECK-NEXT: start:
// CHECK-NOT: alloca
// CHECK-NEXT: ret void
#[inline(never)]
pub fn do_repeat<T: Copy, const N: usize>(x: T) -> Wrapper<T, N> {
Wrapper([x; N])
}
// CHECK-LABEL: @trigger_repeat_zst_elem
#[no_mangle]
pub fn trigger_repeat_zst_elem() -> Wrapper<(), 8> {
// CHECK: call void {{.+}}do_repeat{{.+}}()
do_repeat(())
}

View file

@ -0,0 +1,11 @@
// This test ensures that aliases are also allowed to be partially matched.
// ignore-order
const EXPECTED = {
// The full alias name is `getcwd`.
'query': 'getcw',
'others': [
{ 'path': 'std::env', 'name': 'current_dir', 'alias': 'getcwd' },
],
};

View file

@ -115,11 +115,10 @@ const EXPECTED = [
query: '加法',
others: [
{
name: "add",
name: "加法",
path: "non_english_identifier",
is_alias: true,
alias: "加法",
href: "../non_english_identifier/macro.add.html"
href: "../non_english_identifier/trait.加法.html",
desc: "Add"
},
{
name: "add",
@ -129,11 +128,13 @@ const EXPECTED = [
href: "../non_english_identifier/fn.add.html"
},
{
name: "加法",
name: "add",
path: "non_english_identifier",
href: "../non_english_identifier/trait.加法.html",
desc: "Add"
}],
is_alias: true,
alias: "加法",
href: "../non_english_identifier/macro.add.html"
},
],
in_args: [{
name: "加上",
path: "non_english_identifier::加法",

View file

@ -0,0 +1,24 @@
// Test to ensure that specifying a value for crt-static in target features
// does not result in skipping the features following it.
// This is a regression test for #144143
//@ add-core-stubs
//@ needs-llvm-components: x86
//@ compile-flags: --target=x86_64-unknown-linux-gnu
//@ compile-flags: -Ctarget-feature=+crt-static,+avx2
#![crate_type = "rlib"]
#![feature(no_core, rustc_attrs, lang_items)]
#![no_core]
extern crate minicore;
use minicore::*;
#[rustc_builtin_macro]
macro_rules! compile_error {
() => {};
}
#[cfg(target_feature = "avx2")]
compile_error!("+avx2");
//~^ ERROR: +avx2

View file

@ -0,0 +1,8 @@
error: +avx2
--> $DIR/crt-static-with-target-features-works.rs:23:1
|
LL | compile_error!("+avx2");
| ^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 1 previous error

View file

@ -0,0 +1,19 @@
#![feature(impl_trait_in_bindings)]
trait Trait {}
impl<T: ?Sized> Trait for T {}
fn doesnt_work() {
let x: &impl Trait = "hi";
//~^ ERROR the size for values of type `str` cannot be known at compilation time
}
fn works() {
let x: &(impl Trait + ?Sized) = "hi";
// No implicit sized.
let x: &impl Trait = &();
// Is actually sized.
}
fn main() {}

View file

@ -0,0 +1,11 @@
error[E0277]: the size for values of type `str` cannot be known at compilation time
--> $DIR/implicit-sized.rs:7:13
|
LL | let x: &impl Trait = "hi";
| ^^^^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `Sized` is not implemented for `str`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.

View file

@ -58,10 +58,9 @@ unsafe fn null_ptr() {
let _a: A = ptr::read_unaligned(ptr::null_mut());
//~^ ERROR calling this function with a null pointer is undefined behavior
// These two should *not* fire the lint.
let _a: A = ptr::read_volatile(ptr::null());
//~^ ERROR calling this function with a null pointer is undefined behavior
let _a: A = ptr::read_volatile(ptr::null_mut());
//~^ ERROR calling this function with a null pointer is undefined behavior
let _a: A = ptr::replace(ptr::null_mut(), v);
//~^ ERROR calling this function with a null pointer is undefined behavior
@ -82,8 +81,8 @@ unsafe fn null_ptr() {
ptr::write_unaligned(ptr::null_mut(), v);
//~^ ERROR calling this function with a null pointer is undefined behavior
// This one should *not* fire the lint.
ptr::write_volatile(ptr::null_mut(), v);
//~^ ERROR calling this function with a null pointer is undefined behavior
ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
//~^ ERROR calling this function with a null pointer is undefined behavior

View file

@ -164,27 +164,7 @@ LL | let _a: A = ptr::read_unaligned(ptr::null_mut());
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:61:17
|
LL | let _a: A = ptr::read_volatile(ptr::null());
| ^^^^^^^^^^^^^^^^^^^-----------^
| |
| null pointer originates from here
|
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:63:17
|
LL | let _a: A = ptr::read_volatile(ptr::null_mut());
| ^^^^^^^^^^^^^^^^^^^---------------^
| |
| null pointer originates from here
|
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:66:17
--> $DIR/invalid_null_args.rs:65:17
|
LL | let _a: A = ptr::replace(ptr::null_mut(), v);
| ^^^^^^^^^^^^^---------------^^^^
@ -194,7 +174,7 @@ LL | let _a: A = ptr::replace(ptr::null_mut(), v);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:69:5
--> $DIR/invalid_null_args.rs:68:5
|
LL | ptr::swap::<A>(ptr::null_mut(), &mut v);
| ^^^^^^^^^^^^^^^---------------^^^^^^^^^
@ -204,7 +184,7 @@ LL | ptr::swap::<A>(ptr::null_mut(), &mut v);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:71:5
--> $DIR/invalid_null_args.rs:70:5
|
LL | ptr::swap::<A>(&mut v, ptr::null_mut());
| ^^^^^^^^^^^^^^^^^^^^^^^---------------^
@ -214,7 +194,7 @@ LL | ptr::swap::<A>(&mut v, ptr::null_mut());
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:74:5
--> $DIR/invalid_null_args.rs:73:5
|
LL | ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^^^^^
@ -224,7 +204,7 @@ LL | ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:76:5
--> $DIR/invalid_null_args.rs:75:5
|
LL | ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@ -234,7 +214,7 @@ LL | ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:79:5
--> $DIR/invalid_null_args.rs:78:5
|
LL | ptr::write(ptr::null_mut(), v);
| ^^^^^^^^^^^---------------^^^^
@ -244,7 +224,7 @@ LL | ptr::write(ptr::null_mut(), v);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:82:5
--> $DIR/invalid_null_args.rs:81:5
|
LL | ptr::write_unaligned(ptr::null_mut(), v);
| ^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@ -254,17 +234,7 @@ LL | ptr::write_unaligned(ptr::null_mut(), v);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:85:5
|
LL | ptr::write_volatile(ptr::null_mut(), v);
| ^^^^^^^^^^^^^^^^^^^^---------------^^^^
| |
| null pointer originates from here
|
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:88:5
--> $DIR/invalid_null_args.rs:87:5
|
LL | ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^
@ -274,7 +244,7 @@ LL | ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:93:18
--> $DIR/invalid_null_args.rs:92:18
|
LL | let _a: u8 = ptr::read(const_ptr);
| ^^^^^^^^^^^^^^^^^^^^
@ -287,7 +257,7 @@ LL | let null_ptr = ptr::null_mut();
| ^^^^^^^^^^^^^^^
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:100:5
--> $DIR/invalid_null_args.rs:99:5
|
LL | std::slice::from_raw_parts::<()>(ptr::null(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
@ -297,7 +267,7 @@ LL | std::slice::from_raw_parts::<()>(ptr::null(), 0);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:102:5
--> $DIR/invalid_null_args.rs:101:5
|
LL | std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
@ -307,7 +277,7 @@ LL | std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:104:5
--> $DIR/invalid_null_args.rs:103:5
|
LL | std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@ -317,7 +287,7 @@ LL | std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
--> $DIR/invalid_null_args.rs:106:5
--> $DIR/invalid_null_args.rs:105:5
|
LL | std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@ -326,5 +296,5 @@ LL | std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
|
= help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
error: aborting due to 31 previous errors
error: aborting due to 28 previous errors

View file

@ -8,8 +8,9 @@
// This test reproduces the circumstances that caused the error to appear, and checks
// that compilation is successful.
//@ check-pass
//@ build-pass
//@ compile-flags: --test -C debuginfo=2 -C lto=fat
//@ no-prefer-dynamic
//@ incremental
extern crate alloc;

View file

@ -21,6 +21,8 @@ pub fn f(a: u32) -> u32 {
}
bb1 = {
Call(RET = f(1), ReturnTo(bb2), UnwindTerminate(ReasonAbi))
//~^ ERROR broken MIR in Item
//~| ERROR encountered critical edge in `Call` terminator
}
bb2 = {
@ -29,5 +31,3 @@ pub fn f(a: u32) -> u32 {
}
}
}
//~? RAW encountered critical edge in `Call` terminator

View file

@ -1,9 +1,7 @@
//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires
//@ revisions: null misaligned
#![allow(invalid_null_arguments)]
//@ revisions: misaligned
use std::ptr;
@ -11,8 +9,6 @@ fn main() {
let src = [0u16; 2];
let src = src.as_ptr();
unsafe {
#[cfg(null)]
ptr::read_volatile(ptr::null::<u8>());
#[cfg(misaligned)]
ptr::read_volatile(src.byte_add(1));
}

View file

@ -1,9 +1,7 @@
//@ run-crash
//@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
//@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires
//@ revisions: null misaligned
#![allow(invalid_null_arguments)]
//@ revisions: misaligned
use std::ptr;
@ -11,8 +9,6 @@ fn main() {
let mut dst = [0u16; 2];
let mut dst = dst.as_mut_ptr();
unsafe {
#[cfg(null)]
ptr::write_volatile(ptr::null_mut::<u8>(), 1u8);
#[cfg(misaligned)]
ptr::write_volatile(dst.byte_add(1), 1u16);
}

View file

@ -1,5 +1,5 @@
error[E0308]: mismatched types
--> $DIR/incomplete-inference-issue-143992.rs:27:28
--> $DIR/incomplete-inference-issue-143992.rs:30:28
|
LL | let _x = T::Assoc::new(());
| ------------- ^^ expected `[u32; 1]`, found `()`
@ -7,7 +7,7 @@ LL | let _x = T::Assoc::new(());
| arguments to this function are incorrect
|
note: associated function defined here
--> $DIR/incomplete-inference-issue-143992.rs:18:8
--> $DIR/incomplete-inference-issue-143992.rs:21:8
|
LL | fn new(r: R) -> R {
| ^^^ ----

View file

@ -0,0 +1,17 @@
error[E0308]: mismatched types
--> $DIR/incomplete-inference-issue-143992.rs:30:28
|
LL | let _x = T::Assoc::new(());
| ------------- ^^ expected `[u32; 1]`, found `()`
| |
| arguments to this function are incorrect
|
note: associated function defined here
--> $DIR/incomplete-inference-issue-143992.rs:21:8
|
LL | fn new(r: R) -> R {
| ^^^ ----
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View file

@ -1,9 +1,12 @@
//@ compile-flags: --crate-type=lib
//@ revisions: current next
//@ revisions: current next current_sized_hierarchy next_sized_hierarchy
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[current] check-pass
//@[next] check-pass
//@[next] compile-flags: -Znext-solver
//@[next] check-fail
//@[next_sized_hierarchy] compile-flags: -Znext-solver
#![cfg_attr(any(current_sized_hierarchy, next_sized_hierarchy), feature(sized_hierarchy))]
// Test that we avoid incomplete inference when normalizing. Without this,
// `Trait`'s implicit `MetaSized` supertrait requires proving `T::Assoc<_>: MetaSized`
@ -25,5 +28,6 @@ where
T::Assoc<[u32; 1]>: Clone,
{
let _x = T::Assoc::new(());
//[next]~^ ERROR mismatched types
//[next_sized_hierarchy]~^ ERROR mismatched types
//[current_sized_hierarchy]~^^ ERROR mismatched types
}

View file

@ -12,13 +12,6 @@ LL | impl<T: Bound, U> Trait<U> for T {
| ----- ^^^^^^^^ ^
| |
| unsatisfied trait bound introduced here
note: required by a bound in `Bound`
--> $DIR/normalizes-to-is-not-productive.rs:8:1
|
LL | / trait Bound {
LL | | fn method();
LL | | }
| |_^ required by this bound in `Bound`
error[E0277]: the trait bound `Foo: Bound` is not satisfied
--> $DIR/normalizes-to-is-not-productive.rs:47:19

View file

@ -19,23 +19,6 @@ error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
LL | Self::Assoc: A<T>,
| ^^^^
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: MetaSized`
--> $DIR/normalize-param-env-2.rs:24:22
|
LL | Self::Assoc: A<T>,
| ^^^^
|
note: required by a bound in `A`
--> $DIR/normalize-param-env-2.rs:9:1
|
LL | / trait A<T> {
LL | | type Assoc;
LL | |
LL | | fn f()
... |
LL | | }
| |_^ required by this bound in `A`
error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc well-formed`
--> $DIR/normalize-param-env-2.rs:24:22
|
@ -63,6 +46,6 @@ LL | where
LL | Self::Assoc: A<T>,
| ^^^^ required by this bound in `A::f`
error: aborting due to 6 previous errors
error: aborting due to 5 previous errors
For more information about this error, try `rustc --explain E0275`.

View file

@ -4,20 +4,6 @@ error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait`
LL | <T as Trait>::Assoc: Trait,
| ^^^^^
error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: MetaSized`
--> $DIR/normalize-param-env-4.rs:19:26
|
LL | <T as Trait>::Assoc: Trait,
| ^^^^^
|
note: required by a bound in `Trait`
--> $DIR/normalize-param-env-4.rs:7:1
|
LL | / trait Trait {
LL | | type Assoc;
LL | | }
| |_^ required by this bound in `Trait`
error: aborting due to 2 previous errors
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0275`.

View file

@ -1,13 +1,13 @@
use std::ops::Add;
fn dbl<T>(x: T) -> <T as Add>::Output
//~^ ERROR type annotations needed
where
T: Copy + Add,
UUU: Copy,
//~^ ERROR cannot find type `UUU` in this scope
{
x + x
//~^ ERROR use of moved value: `x`
}
fn main() {

View file

@ -1,16 +1,33 @@
error[E0412]: cannot find type `UUU` in this scope
--> $DIR/ignore-err-clauses.rs:7:5
--> $DIR/ignore-err-clauses.rs:6:5
|
LL | UUU: Copy,
| ^^^ not found in this scope
error[E0282]: type annotations needed
--> $DIR/ignore-err-clauses.rs:3:14
error[E0382]: use of moved value: `x`
--> $DIR/ignore-err-clauses.rs:9:9
|
LL | fn dbl<T>(x: T) -> <T as Add>::Output
| ^ cannot infer type for type parameter `T`
| - move occurs because `x` has type `T`, which does not implement the `Copy` trait
...
LL | x + x
| ----^
| | |
| | value used here after move
| `x` moved due to usage in operator
|
help: if `T` implemented `Clone`, you could clone the value
--> $DIR/ignore-err-clauses.rs:3:8
|
LL | fn dbl<T>(x: T) -> <T as Add>::Output
| ^ consider constraining this type parameter with `Clone`
...
LL | x + x
| - you could clone this value
note: calling this operator moves the left-hand side
--> $SRC_DIR/core/src/ops/arith.rs:LL:COL
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0282, E0412.
For more information about an error, try `rustc --explain E0282`.
Some errors have detailed explanations: E0382, E0412.
For more information about an error, try `rustc --explain E0382`.