From 547b4e601e797e7989f6fc9ebe921376c74bd1f0 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 1 Feb 2022 18:53:45 +0100 Subject: [PATCH 1/7] Add more *-unwind ABI variants The following *-unwind ABIs are now supported: - "C-unwind" - "cdecl-unwind" - "stdcall-unwind" - "fastcall-unwind" - "vectorcall-unwind" - "thiscall-unwind" - "aapcs-unwind" - "win64-unwind" - "sysv64-unwind" - "system-unwind" --- compiler/rustc_ast_passes/src/feature_gate.rs | 48 +++++++++++ compiler/rustc_metadata/src/native_libs.rs | 8 +- compiler/rustc_middle/src/ty/layout.rs | 31 ++++--- compiler/rustc_target/src/abi/call/mod.rs | 20 +++-- compiler/rustc_target/src/spec/abi.rs | 86 +++++++++++-------- compiler/rustc_target/src/spec/mod.rs | 22 ++--- compiler/rustc_typeck/src/lib.rs | 2 +- .../src/language-features/c-unwind.md | 17 +++- .../codegen/unwind-abis/aapcs-unwind-abi.rs | 31 +++++++ .../codegen/unwind-abis/cdecl-unwind-abi.rs | 29 +++++++ .../unwind-abis/fastcall-unwind-abi.rs | 31 +++++++ .../codegen/unwind-abis/sysv64-unwind-abi.rs | 31 +++++++ .../unwind-abis/vectorcall-unwind-abi.rs | 31 +++++++ .../codegen/unwind-abis/win64-unwind-abi.rs | 31 +++++++ src/test/ui/codemap_tests/unicode.stderr | 2 +- src/test/ui/parser/issues/issue-8537.stderr | 2 +- 16 files changed, 342 insertions(+), 80 deletions(-) create mode 100644 src/test/codegen/unwind-abis/aapcs-unwind-abi.rs create mode 100644 src/test/codegen/unwind-abis/cdecl-unwind-abi.rs create mode 100644 src/test/codegen/unwind-abis/fastcall-unwind-abi.rs create mode 100644 src/test/codegen/unwind-abis/sysv64-unwind-abi.rs create mode 100644 src/test/codegen/unwind-abis/vectorcall-unwind-abi.rs create mode 100644 src/test/codegen/unwind-abis/win64-unwind-abi.rs diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index a6ecfa4520608..0a96e60d4d3af 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -196,6 +196,54 @@ impl<'a> PostExpansionVisitor<'a> { "thiscall-unwind ABI is experimental and subject to change" ); } + "cdecl-unwind" => { + gate_feature_post!( + &self, + c_unwind, + span, + "cdecl-unwind ABI is experimental and subject to change" + ); + } + "fastcall-unwind" => { + gate_feature_post!( + &self, + c_unwind, + span, + "fastcall-unwind ABI is experimental and subject to change" + ); + } + "vectorcall-unwind" => { + gate_feature_post!( + &self, + c_unwind, + span, + "vectorcall-unwind ABI is experimental and subject to change" + ); + } + "aapcs-unwind" => { + gate_feature_post!( + &self, + c_unwind, + span, + "aapcs-unwind ABI is experimental and subject to change" + ); + } + "win64-unwind" => { + gate_feature_post!( + &self, + c_unwind, + span, + "win64-unwind ABI is experimental and subject to change" + ); + } + "sysv64-unwind" => { + gate_feature_post!( + &self, + c_unwind, + span, + "sysv64-unwind ABI is experimental and subject to change" + ); + } "wasm" => { gate_feature_post!( &self, diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 13cd8e4a046b0..88292a4422419 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -404,11 +404,13 @@ impl Collector<'_> { fn build_dll_import(&self, abi: Abi, item: &hir::ForeignItemRef) -> DllImport { let calling_convention = if self.tcx.sess.target.arch == "x86" { match abi { - Abi::C { .. } | Abi::Cdecl => DllCallingConvention::C, + Abi::C { .. } | Abi::Cdecl { .. } => DllCallingConvention::C, Abi::Stdcall { .. } | Abi::System { .. } => { DllCallingConvention::Stdcall(self.i686_arg_list_size(item)) } - Abi::Fastcall => DllCallingConvention::Fastcall(self.i686_arg_list_size(item)), + Abi::Fastcall { .. } => { + DllCallingConvention::Fastcall(self.i686_arg_list_size(item)) + } // Vectorcall is intentionally not supported at this time. _ => { self.tcx.sess.span_fatal( @@ -419,7 +421,7 @@ impl Collector<'_> { } } else { match abi { - Abi::C { .. } | Abi::Win64 | Abi::System { .. } => DllCallingConvention::C, + Abi::C { .. } | Abi::Win64 { .. } | Abi::System { .. } => DllCallingConvention::C, _ => { self.tcx.sess.span_fatal( item.span, diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index caf33fa5d213b..c2aa83b8a7f9b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2773,17 +2773,20 @@ pub fn fn_can_unwind<'tcx>( // [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2945-c-unwind-abi.md use SpecAbi::*; match abi { - C { unwind } | Stdcall { unwind } | System { unwind } | Thiscall { unwind } => { + C { unwind } + | System { unwind } + | Cdecl { unwind } + | Stdcall { unwind } + | Fastcall { unwind } + | Vectorcall { unwind } + | Thiscall { unwind } + | Aapcs { unwind } + | Win64 { unwind } + | SysV64 { unwind } => { unwind || (!tcx.features().c_unwind && tcx.sess.panic_strategy() == PanicStrategy::Unwind) } - Cdecl - | Fastcall - | Vectorcall - | Aapcs - | Win64 - | SysV64 - | PtxKernel + PtxKernel | Msp430Interrupt | X86Interrupt | AmdGpuKernel @@ -2810,14 +2813,14 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { EfiApi => bug!("eficall abi should be selected elsewhere"), Stdcall { .. } => Conv::X86Stdcall, - Fastcall => Conv::X86Fastcall, - Vectorcall => Conv::X86VectorCall, + Fastcall { .. } => Conv::X86Fastcall, + Vectorcall { .. } => Conv::X86VectorCall, Thiscall { .. } => Conv::X86ThisCall, C { .. } => Conv::C, Unadjusted => Conv::C, - Win64 => Conv::X86_64Win64, - SysV64 => Conv::X86_64SysV, - Aapcs => Conv::ArmAapcs, + Win64 { .. } => Conv::X86_64Win64, + SysV64 { .. } => Conv::X86_64SysV, + Aapcs { .. } => Conv::ArmAapcs, CCmseNonSecureCall => Conv::CCmseNonSecureCall, PtxKernel => Conv::PtxKernel, Msp430Interrupt => Conv::Msp430Intr, @@ -2828,7 +2831,7 @@ pub fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi) -> Conv { Wasm => Conv::C, // These API constants ought to be more specific... - Cdecl => Conv::C, + Cdecl { .. } => Conv::C, } } diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 735b7e76e3862..43eb7ab05e0bf 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -658,22 +658,24 @@ impl<'a, Ty> FnAbi<'a, Ty> { match &cx.target_spec().arch[..] { "x86" => { - let flavor = if abi == spec::abi::Abi::Fastcall { + let flavor = if let spec::abi::Abi::Fastcall { .. } = abi { x86::Flavor::Fastcall } else { x86::Flavor::General }; x86::compute_abi_info(cx, self, flavor); } - "x86_64" => { - if abi == spec::abi::Abi::SysV64 { - x86_64::compute_abi_info(cx, self); - } else if abi == spec::abi::Abi::Win64 || cx.target_spec().is_like_windows { - x86_win64::compute_abi_info(self); - } else { - x86_64::compute_abi_info(cx, self); + "x86_64" => match abi { + spec::abi::Abi::SysV64 { .. } => x86_64::compute_abi_info(cx, self), + spec::abi::Abi::Win64 { .. } => x86_win64::compute_abi_info(self), + _ => { + if cx.target_spec().is_like_windows { + x86_win64::compute_abi_info(self) + } else { + x86_64::compute_abi_info(cx, self) + } } - } + }, "aarch64" => aarch64::compute_abi_info(cx, self), "amdgpu" => amdgpu::compute_abi_info(cx, self), "arm" => arm::compute_abi_info(cx, self), diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index e3a2226eb9d15..d9e571c72e53a 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -13,14 +13,14 @@ pub enum Abi { // churn. The specific values are meaningless. Rust, C { unwind: bool }, - Cdecl, + Cdecl { unwind: bool }, Stdcall { unwind: bool }, - Fastcall, - Vectorcall, + Fastcall { unwind: bool }, + Vectorcall { unwind: bool }, Thiscall { unwind: bool }, - Aapcs, - Win64, - SysV64, + Aapcs { unwind: bool }, + Win64 { unwind: bool }, + SysV64 { unwind: bool }, PtxKernel, Msp430Interrupt, X86Interrupt, @@ -50,16 +50,22 @@ const AbiDatas: &[AbiData] = &[ AbiData { abi: Abi::Rust, name: "Rust" }, AbiData { abi: Abi::C { unwind: false }, name: "C" }, AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" }, - AbiData { abi: Abi::Cdecl, name: "cdecl" }, + AbiData { abi: Abi::Cdecl { unwind: false }, name: "cdecl" }, + AbiData { abi: Abi::Cdecl { unwind: true }, name: "cdecl-unwind" }, AbiData { abi: Abi::Stdcall { unwind: false }, name: "stdcall" }, AbiData { abi: Abi::Stdcall { unwind: true }, name: "stdcall-unwind" }, - AbiData { abi: Abi::Fastcall, name: "fastcall" }, - AbiData { abi: Abi::Vectorcall, name: "vectorcall" }, + AbiData { abi: Abi::Fastcall { unwind: false }, name: "fastcall" }, + AbiData { abi: Abi::Fastcall { unwind: true }, name: "fastcall-unwind" }, + AbiData { abi: Abi::Vectorcall { unwind: false }, name: "vectorcall" }, + AbiData { abi: Abi::Vectorcall { unwind: true }, name: "vectorcall-unwind" }, AbiData { abi: Abi::Thiscall { unwind: false }, name: "thiscall" }, AbiData { abi: Abi::Thiscall { unwind: true }, name: "thiscall-unwind" }, - AbiData { abi: Abi::Aapcs, name: "aapcs" }, - AbiData { abi: Abi::Win64, name: "win64" }, - AbiData { abi: Abi::SysV64, name: "sysv64" }, + AbiData { abi: Abi::Aapcs { unwind: false }, name: "aapcs" }, + AbiData { abi: Abi::Aapcs { unwind: true }, name: "aapcs-unwind" }, + AbiData { abi: Abi::Win64 { unwind: false }, name: "win64" }, + AbiData { abi: Abi::Win64 { unwind: true }, name: "win64-unwind" }, + AbiData { abi: Abi::SysV64 { unwind: false }, name: "sysv64" }, + AbiData { abi: Abi::SysV64 { unwind: true }, name: "sysv64-unwind" }, AbiData { abi: Abi::PtxKernel, name: "ptx-kernel" }, AbiData { abi: Abi::Msp430Interrupt, name: "msp430-interrupt" }, AbiData { abi: Abi::X86Interrupt, name: "x86-interrupt" }, @@ -101,32 +107,38 @@ impl Abi { C { unwind: false } => 1, C { unwind: true } => 2, // Platform-specific ABIs - Cdecl => 3, - Stdcall { unwind: false } => 4, - Stdcall { unwind: true } => 5, - Fastcall => 6, - Vectorcall => 7, - Thiscall { unwind: false } => 8, - Thiscall { unwind: true } => 9, - Aapcs => 10, - Win64 => 11, - SysV64 => 12, - PtxKernel => 13, - Msp430Interrupt => 14, - X86Interrupt => 15, - AmdGpuKernel => 16, - EfiApi => 17, - AvrInterrupt => 18, - AvrNonBlockingInterrupt => 19, - CCmseNonSecureCall => 20, - Wasm => 21, + Cdecl { unwind: false } => 3, + Cdecl { unwind: true } => 4, + Stdcall { unwind: false } => 5, + Stdcall { unwind: true } => 6, + Fastcall { unwind: false } => 7, + Fastcall { unwind: true } => 8, + Vectorcall { unwind: false } => 9, + Vectorcall { unwind: true } => 10, + Thiscall { unwind: false } => 11, + Thiscall { unwind: true } => 12, + Aapcs { unwind: false } => 13, + Aapcs { unwind: true } => 14, + Win64 { unwind: false } => 15, + Win64 { unwind: true } => 16, + SysV64 { unwind: false } => 17, + SysV64 { unwind: true } => 18, + PtxKernel => 19, + Msp430Interrupt => 20, + X86Interrupt => 21, + AmdGpuKernel => 22, + EfiApi => 23, + AvrInterrupt => 24, + AvrNonBlockingInterrupt => 25, + CCmseNonSecureCall => 26, + Wasm => 27, // Cross-platform ABIs - System { unwind: false } => 22, - System { unwind: true } => 23, - RustIntrinsic => 24, - RustCall => 25, - PlatformIntrinsic => 26, - Unadjusted => 27, + System { unwind: false } => 28, + System { unwind: true } => 29, + RustIntrinsic => 30, + RustCall => 31, + PlatformIntrinsic => 32, + Unadjusted => 33, }; debug_assert!( AbiDatas diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 4effb8bacf6d6..06d38670a63b2 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1556,15 +1556,15 @@ impl Target { Abi::Stdcall { unwind } } Abi::System { unwind } => Abi::C { unwind }, - Abi::EfiApi if self.arch == "x86_64" => Abi::Win64, + Abi::EfiApi if self.arch == "x86_64" => Abi::Win64 { unwind: false }, Abi::EfiApi => Abi::C { unwind: false }, // See commentary in `is_abi_supported`. Abi::Stdcall { .. } | Abi::Thiscall { .. } if self.arch == "x86" => abi, Abi::Stdcall { unwind } | Abi::Thiscall { unwind } => Abi::C { unwind }, - Abi::Fastcall if self.arch == "x86" => abi, - Abi::Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => abi, - Abi::Fastcall | Abi::Vectorcall => Abi::C { unwind: false }, + Abi::Fastcall { .. } if self.arch == "x86" => abi, + Abi::Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi, + Abi::Fastcall { unwind } | Abi::Vectorcall { unwind } => Abi::C { unwind }, abi => abi, } @@ -1581,12 +1581,12 @@ impl Target { | RustCall | PlatformIntrinsic | Unadjusted - | Cdecl + | Cdecl { .. } | EfiApi => true, X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]), - Aapcs => "arm" == self.arch, + Aapcs { .. } => "arm" == self.arch, CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]), - Win64 | SysV64 => self.arch == "x86_64", + Win64 { .. } | SysV64 { .. } => self.arch == "x86_64", PtxKernel => self.arch == "nvptx64", Msp430Interrupt => self.arch == "msp430", AmdGpuKernel => self.arch == "amdgcn", @@ -1623,13 +1623,13 @@ impl Target { // > convention is used. // // -- https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions - Stdcall { .. } | Fastcall | Vectorcall if self.is_like_windows => true, + Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } if self.is_like_windows => true, // Outside of Windows we want to only support these calling conventions for the // architectures for which these calling conventions are actually well defined. - Stdcall { .. } | Fastcall if self.arch == "x86" => true, - Vectorcall if ["x86", "x86_64"].contains(&&self.arch[..]) => true, + Stdcall { .. } | Fastcall { .. } if self.arch == "x86" => true, + Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => true, // Return a `None` for other cases so that we know to emit a future compat lint. - Stdcall { .. } | Fastcall | Vectorcall => return None, + Stdcall { .. } | Fastcall { .. } | Vectorcall { .. } => return None, }) } diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 6a9f154844a57..e4b708dfd147f 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -121,7 +121,7 @@ use bounds::Bounds; fn require_c_abi_if_c_variadic(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: Abi, span: Span) { match (decl.c_variadic, abi) { // The function has the correct calling convention, or isn't a "C-variadic" function. - (false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl) => {} + (false, _) | (true, Abi::C { .. }) | (true, Abi::Cdecl { .. }) => {} // The function is a "C-variadic" function with an incorrect calling convention. (true, _) => { let mut err = struct_span_err!( diff --git a/src/doc/unstable-book/src/language-features/c-unwind.md b/src/doc/unstable-book/src/language-features/c-unwind.md index 2801d9b5e7778..fb32918d5e439 100644 --- a/src/doc/unstable-book/src/language-features/c-unwind.md +++ b/src/doc/unstable-book/src/language-features/c-unwind.md @@ -6,9 +6,20 @@ The tracking issue for this feature is: [#74990] ------------------------ -Introduces four new ABI strings: "C-unwind", "stdcall-unwind", -"thiscall-unwind", and "system-unwind". These enable unwinding from other -languages (such as C++) into Rust frames and from Rust into other languages. +Introduces new ABI strings: +- "C-unwind" +- "cdecl-unwind" +- "stdcall-unwind" +- "fastcall-unwind" +- "vectorcall-unwind" +- "thiscall-unwind" +- "aapcs-unwind" +- "win64-unwind" +- "sysv64-unwind" +- "system-unwind" + +These enable unwinding from other languages (such as C++) into Rust frames and +from Rust into other languages. See [RFC 2945] for more information. diff --git a/src/test/codegen/unwind-abis/aapcs-unwind-abi.rs b/src/test/codegen/unwind-abis/aapcs-unwind-abi.rs new file mode 100644 index 0000000000000..1fe048068601d --- /dev/null +++ b/src/test/codegen/unwind-abis/aapcs-unwind-abi.rs @@ -0,0 +1,31 @@ +// needs-llvm-components: arm +// compile-flags: --target=armv7-unknown-linux-gnueabihf --crate-type=rlib -Cno-prepopulate-passes +#![no_core] +#![feature(no_core, lang_items, c_unwind)] +#[lang="sized"] +trait Sized { } + +// Test that `nounwind` atributes are correctly applied to exported `aapcs` and +// `aapcs-unwind` extern functions. `aapcs-unwind` functions MUST NOT have this attribute. We +// disable optimizations above to prevent LLVM from inferring the attribute. + +// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { +#[no_mangle] +pub extern "aapcs" fn rust_item_that_cannot_unwind() { +} + +// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { +#[no_mangle] +pub extern "aapcs-unwind" fn rust_item_that_can_unwind() { +} + +// Now, make some assertions that the LLVM attributes for these functions are correct. First, make +// sure that the first item is correctly marked with the `nounwind` attribute: +// +// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} } +// +// Next, let's assert that the second item, which CAN unwind, does not have this attribute. +// +// CHECK: attributes #1 = { +// CHECK-NOT: nounwind +// CHECK: } diff --git a/src/test/codegen/unwind-abis/cdecl-unwind-abi.rs b/src/test/codegen/unwind-abis/cdecl-unwind-abi.rs new file mode 100644 index 0000000000000..52e0d2d6e0252 --- /dev/null +++ b/src/test/codegen/unwind-abis/cdecl-unwind-abi.rs @@ -0,0 +1,29 @@ +// compile-flags: -C opt-level=0 + +// Test that `nounwind` atributes are correctly applied to exported `cdecl` and +// `cdecl-unwind` extern functions. `cdecl-unwind` functions MUST NOT have this attribute. We +// disable optimizations above to prevent LLVM from inferring the attribute. + +#![crate_type = "lib"] +#![feature(c_unwind)] + +// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { +#[no_mangle] +pub extern "cdecl" fn rust_item_that_cannot_unwind() { +} + +// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { +#[no_mangle] +pub extern "cdecl-unwind" fn rust_item_that_can_unwind() { +} + +// Now, make some assertions that the LLVM attributes for these functions are correct. First, make +// sure that the first item is correctly marked with the `nounwind` attribute: +// +// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} } +// +// Next, let's assert that the second item, which CAN unwind, does not have this attribute. +// +// CHECK: attributes #1 = { +// CHECK-NOT: nounwind +// CHECK: } diff --git a/src/test/codegen/unwind-abis/fastcall-unwind-abi.rs b/src/test/codegen/unwind-abis/fastcall-unwind-abi.rs new file mode 100644 index 0000000000000..ed23235ebfa80 --- /dev/null +++ b/src/test/codegen/unwind-abis/fastcall-unwind-abi.rs @@ -0,0 +1,31 @@ +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes +#![no_core] +#![feature(no_core, lang_items, c_unwind)] +#[lang="sized"] +trait Sized { } + +// Test that `nounwind` atributes are correctly applied to exported `fastcall` and +// `fastcall-unwind` extern functions. `fastcall-unwind` functions MUST NOT have this attribute. We +// disable optimizations above to prevent LLVM from inferring the attribute. + +// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { +#[no_mangle] +pub extern "fastcall" fn rust_item_that_cannot_unwind() { +} + +// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { +#[no_mangle] +pub extern "fastcall-unwind" fn rust_item_that_can_unwind() { +} + +// Now, make some assertions that the LLVM attributes for these functions are correct. First, make +// sure that the first item is correctly marked with the `nounwind` attribute: +// +// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} } +// +// Next, let's assert that the second item, which CAN unwind, does not have this attribute. +// +// CHECK: attributes #1 = { +// CHECK-NOT: nounwind +// CHECK: } diff --git a/src/test/codegen/unwind-abis/sysv64-unwind-abi.rs b/src/test/codegen/unwind-abis/sysv64-unwind-abi.rs new file mode 100644 index 0000000000000..a38736f2a1f95 --- /dev/null +++ b/src/test/codegen/unwind-abis/sysv64-unwind-abi.rs @@ -0,0 +1,31 @@ +// needs-llvm-components: x86 +// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes +#![no_core] +#![feature(no_core, lang_items, c_unwind)] +#[lang="sized"] +trait Sized { } + +// Test that `nounwind` atributes are correctly applied to exported `sysv64` and +// `sysv64-unwind` extern functions. `sysv64-unwind` functions MUST NOT have this attribute. We +// disable optimizations above to prevent LLVM from inferring the attribute. + +// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { +#[no_mangle] +pub extern "sysv64" fn rust_item_that_cannot_unwind() { +} + +// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { +#[no_mangle] +pub extern "sysv64-unwind" fn rust_item_that_can_unwind() { +} + +// Now, make some assertions that the LLVM attributes for these functions are correct. First, make +// sure that the first item is correctly marked with the `nounwind` attribute: +// +// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} } +// +// Next, let's assert that the second item, which CAN unwind, does not have this attribute. +// +// CHECK: attributes #1 = { +// CHECK-NOT: nounwind +// CHECK: } diff --git a/src/test/codegen/unwind-abis/vectorcall-unwind-abi.rs b/src/test/codegen/unwind-abis/vectorcall-unwind-abi.rs new file mode 100644 index 0000000000000..0fb9612a5e4e8 --- /dev/null +++ b/src/test/codegen/unwind-abis/vectorcall-unwind-abi.rs @@ -0,0 +1,31 @@ +// needs-llvm-components: x86 +// compile-flags: --target=i686-pc-windows-msvc --crate-type=rlib -Cno-prepopulate-passes +#![no_core] +#![feature(no_core, lang_items, c_unwind, abi_vectorcall)] +#[lang="sized"] +trait Sized { } + +// Test that `nounwind` atributes are correctly applied to exported `vectorcall` and +// `vectorcall-unwind` extern functions. `vectorcall-unwind` functions MUST NOT have this attribute. +// We disable optimizations above to prevent LLVM from inferring the attribute. + +// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { +#[no_mangle] +pub extern "vectorcall" fn rust_item_that_cannot_unwind() { +} + +// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { +#[no_mangle] +pub extern "vectorcall-unwind" fn rust_item_that_can_unwind() { +} + +// Now, make some assertions that the LLVM attributes for these functions are correct. First, make +// sure that the first item is correctly marked with the `nounwind` attribute: +// +// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} } +// +// Next, let's assert that the second item, which CAN unwind, does not have this attribute. +// +// CHECK: attributes #1 = { +// CHECK-NOT: nounwind +// CHECK: } diff --git a/src/test/codegen/unwind-abis/win64-unwind-abi.rs b/src/test/codegen/unwind-abis/win64-unwind-abi.rs new file mode 100644 index 0000000000000..5d8482da63056 --- /dev/null +++ b/src/test/codegen/unwind-abis/win64-unwind-abi.rs @@ -0,0 +1,31 @@ +// needs-llvm-components: x86 +// compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=rlib -Cno-prepopulate-passes +#![no_core] +#![feature(no_core, lang_items, c_unwind)] +#[lang="sized"] +trait Sized { } + +// Test that `nounwind` atributes are correctly applied to exported `win64` and +// `win64-unwind` extern functions. `win64-unwind` functions MUST NOT have this attribute. We +// disable optimizations above to prevent LLVM from inferring the attribute. + +// CHECK: @rust_item_that_cannot_unwind() unnamed_addr #0 { +#[no_mangle] +pub extern "win64" fn rust_item_that_cannot_unwind() { +} + +// CHECK: @rust_item_that_can_unwind() unnamed_addr #1 { +#[no_mangle] +pub extern "win64-unwind" fn rust_item_that_can_unwind() { +} + +// Now, make some assertions that the LLVM attributes for these functions are correct. First, make +// sure that the first item is correctly marked with the `nounwind` attribute: +// +// CHECK: attributes #0 = { {{.*}}nounwind{{.*}} } +// +// Next, let's assert that the second item, which CAN unwind, does not have this attribute. +// +// CHECK: attributes #1 = { +// CHECK-NOT: nounwind +// CHECK: } diff --git a/src/test/ui/codemap_tests/unicode.stderr b/src/test/ui/codemap_tests/unicode.stderr index 357dd25389ecb..e5aef04b6894e 100644 --- a/src/test/ui/codemap_tests/unicode.stderr +++ b/src/test/ui/codemap_tests/unicode.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `路濫狼á́́` LL | extern "路濫狼á́́" fn foo() {} | ^^^^^^^^^ invalid ABI | - = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted + = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted error: aborting due to previous error diff --git a/src/test/ui/parser/issues/issue-8537.stderr b/src/test/ui/parser/issues/issue-8537.stderr index 5a29ce2221fc2..5f8d4315de829 100644 --- a/src/test/ui/parser/issues/issue-8537.stderr +++ b/src/test/ui/parser/issues/issue-8537.stderr @@ -4,7 +4,7 @@ error[E0703]: invalid ABI: found `invalid-ab_isize` LL | "invalid-ab_isize" | ^^^^^^^^^^^^^^^^^^ invalid ABI | - = help: valid ABIs: Rust, C, C-unwind, cdecl, stdcall, stdcall-unwind, fastcall, vectorcall, thiscall, thiscall-unwind, aapcs, win64, sysv64, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted + = help: valid ABIs: Rust, C, C-unwind, cdecl, cdecl-unwind, stdcall, stdcall-unwind, fastcall, fastcall-unwind, vectorcall, vectorcall-unwind, thiscall, thiscall-unwind, aapcs, aapcs-unwind, win64, win64-unwind, sysv64, sysv64-unwind, ptx-kernel, msp430-interrupt, x86-interrupt, amdgpu-kernel, efiapi, avr-interrupt, avr-non-blocking-interrupt, C-cmse-nonsecure-call, wasm, system, system-unwind, rust-intrinsic, rust-call, platform-intrinsic, unadjusted error: aborting due to previous error From 0fb2b7a2da00fb323f43f2e503b79086135b5906 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 5 Feb 2022 14:50:46 -0500 Subject: [PATCH 2/7] Drop json::from_reader Performing UTF-8 decode outside the JSON module makes more sense in almost all cases. --- compiler/rustc_serialize/src/json.rs | 22 ---------------------- compiler/rustc_target/src/spec/mod.rs | 4 ++-- 2 files changed, 2 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_serialize/src/json.rs b/compiler/rustc_serialize/src/json.rs index 044de8e4e2483..6a39854924122 100644 --- a/compiler/rustc_serialize/src/json.rs +++ b/compiler/rustc_serialize/src/json.rs @@ -185,8 +185,6 @@ use self::ParserState::*; use std::borrow::Cow; use std::collections::{BTreeMap, HashMap}; -use std::io; -use std::io::prelude::*; use std::mem::swap; use std::num::FpCategory as Fp; use std::ops::Index; @@ -250,7 +248,6 @@ pub enum ErrorCode { pub enum ParserError { /// msg, line, col SyntaxError(ErrorCode, usize, usize), - IoError(io::ErrorKind, String), } // Builder and Parser have the same errors. @@ -329,10 +326,6 @@ impl fmt::Display for ErrorCode { } } -fn io_error_to_error(io: io::Error) -> ParserError { - IoError(io.kind(), io.to_string()) -} - impl fmt::Display for ParserError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { // FIXME this should be a nicer error @@ -2163,21 +2156,6 @@ impl> Builder { } } -/// Decodes a json value from an `&mut io::Read` -pub fn from_reader(rdr: &mut dyn Read) -> Result { - let mut contents = Vec::new(); - match rdr.read_to_end(&mut contents) { - Ok(c) => c, - Err(e) => return Err(io_error_to_error(e)), - }; - let s = match str::from_utf8(&contents).ok() { - Some(s) => s, - _ => return Err(SyntaxError(NotUtf8, 0, 0)), - }; - let mut builder = Builder::new(s.chars()); - builder.build() -} - /// Decodes a json value from a string pub fn from_str(s: &str) -> Result { let mut builder = Builder::new(s.chars()); diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 4effb8bacf6d6..51ab32a79adc5 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2145,8 +2145,8 @@ impl Target { use std::fs; fn load_file(path: &Path) -> Result<(Target, TargetWarnings), String> { - let contents = fs::read(path).map_err(|e| e.to_string())?; - let obj = json::from_reader(&mut &contents[..]).map_err(|e| e.to_string())?; + let contents = fs::read_to_string(path).map_err(|e| e.to_string())?; + let obj = json::from_str(&contents).map_err(|e| e.to_string())?; Target::from_json(obj) } From 2f236246d03852e3d86bb04b1b1da263efd64425 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sat, 5 Feb 2022 20:11:50 -0500 Subject: [PATCH 3/7] Drop time dependency from bootstrap This was only used for the inclusion of 'current' dates into our manpages, but it is not clear that this is practically necessary. The manpage is essentially never updated, and so we can likely afford to keep a manual date in these files. It also seems possible to just omit it, but that may cause other tools trouble, so avoid doing that for now. --- Cargo.lock | 1 - src/bootstrap/Cargo.toml | 1 - src/bootstrap/dist.rs | 25 +++---------------------- src/bootstrap/lib.rs | 20 +------------------- src/doc/man/rustc.1 | 2 +- src/doc/man/rustdoc.1 | 2 +- 6 files changed, 6 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 208ce841759b9..81f34c457a187 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,7 +236,6 @@ dependencies = [ "pretty_assertions", "serde", "serde_json", - "time", "toml", "winapi", ] diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index b68b2163f873a..bf8dc31667c2d 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -44,7 +44,6 @@ libc = "0.2" serde = { version = "1.0.8", features = ["derive"] } serde_json = "1.0.2" toml = "0.5" -time = "0.1" ignore = "0.4.10" opener = "0.5" once_cell = "1.7.2" diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 66b63cd1278c5..472ee3fb01474 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -24,7 +24,6 @@ use crate::tarball::{GeneratedTarball, OverlayKind, Tarball}; use crate::tool::{self, Tool}; use crate::util::{exe, is_dylib, timeit}; use crate::{Compiler, DependencyType, Mode, LLVM_TOOLS}; -use time::{self, Timespec}; pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { format!("{}-{}", component, builder.rust_package_vers()) @@ -422,33 +421,15 @@ impl Step for Rustc { let man_src = builder.src.join("src/doc/man"); let man_dst = image.join("share/man/man1"); - // Reproducible builds: If SOURCE_DATE_EPOCH is set, use that as the time. - let time = env::var("SOURCE_DATE_EPOCH") - .map(|timestamp| { - let epoch = timestamp - .parse() - .map_err(|err| format!("could not parse SOURCE_DATE_EPOCH: {}", err)) - .unwrap(); - - time::at(Timespec::new(epoch, 0)) - }) - .unwrap_or_else(|_| time::now()); - - let month_year = t!(time::strftime("%B %Y", &time)); // don't use our `bootstrap::util::{copy, cp_r}`, because those try // to hardlink, and we don't want to edit the source templates for file_entry in builder.read_dir(&man_src) { let page_src = file_entry.path(); let page_dst = man_dst.join(file_entry.file_name()); + let src_text = t!(std::fs::read_to_string(&page_src)); + let new_text = src_text.replace("", &builder.version); + t!(std::fs::write(&page_dst, &new_text)); t!(fs::copy(&page_src, &page_dst)); - // template in month/year and version number - builder.replace_in_file( - &page_dst, - &[ - ("", &month_year), - ("", &builder.version), - ], - ); } // Debugger scripts diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index e5f84d417bf0b..b2ae57438efc4 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -106,8 +106,7 @@ use std::cell::{Cell, RefCell}; use std::collections::{HashMap, HashSet}; use std::env; -use std::fs::{self, File, OpenOptions}; -use std::io::{Read, Seek, SeekFrom, Write}; +use std::fs::{self, File}; use std::path::{Path, PathBuf}; use std::process::{self, Command}; use std::str; @@ -1335,23 +1334,6 @@ impl Build { } } - /// Search-and-replaces within a file. (Not maximally efficiently: allocates a - /// new string for each replacement.) - pub fn replace_in_file(&self, path: &Path, replacements: &[(&str, &str)]) { - if self.config.dry_run { - return; - } - let mut contents = String::new(); - let mut file = t!(OpenOptions::new().read(true).write(true).open(path)); - t!(file.read_to_string(&mut contents)); - for &(target, replacement) in replacements { - contents = contents.replace(target, replacement); - } - t!(file.seek(SeekFrom::Start(0))); - t!(file.set_len(0)); - t!(file.write_all(contents.as_bytes())); - } - /// Copies the `src` directory recursively to `dst`. Both are assumed to exist /// when this function is called. pub fn cp_r(&self, src: &Path, dst: &Path) { diff --git a/src/doc/man/rustc.1 b/src/doc/man/rustc.1 index 3788e3c864e82..4e7170806d47b 100644 --- a/src/doc/man/rustc.1 +++ b/src/doc/man/rustc.1 @@ -1,4 +1,4 @@ -.TH RUSTC "1" "" "rustc " "User Commands" +.TH RUSTC "1" "April 2019" "rustc " "User Commands" .SH NAME rustc \- The Rust compiler .SH SYNOPSIS diff --git a/src/doc/man/rustdoc.1 b/src/doc/man/rustdoc.1 index d7f78e8f6f4de..e618534797282 100644 --- a/src/doc/man/rustdoc.1 +++ b/src/doc/man/rustdoc.1 @@ -1,4 +1,4 @@ -.TH RUSTDOC "1" "" "rustdoc " "User Commands" +.TH RUSTDOC "1" "July 2018" "rustdoc " "User Commands" .SH NAME rustdoc \- generate documentation from Rust source code .SH SYNOPSIS From a4112dc7b5c8240f4e9163c1f696426e3899a26d Mon Sep 17 00:00:00 2001 From: Yerkebulan Tulibergenov Date: Sat, 5 Feb 2022 19:57:02 -0800 Subject: [PATCH 4/7] fix linking stage1 toolchain in setup --- src/bootstrap/setup.rs | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/src/bootstrap/setup.rs b/src/bootstrap/setup.rs index 5bc0a505bf695..a28815d09761b 100644 --- a/src/bootstrap/setup.rs +++ b/src/bootstrap/setup.rs @@ -1,7 +1,9 @@ use crate::TargetSelection; use crate::{t, VERSION}; +use std::env::consts::EXE_SUFFIX; use std::fmt::Write as _; -use std::path::{Path, PathBuf}; +use std::fs::File; +use std::path::{Path, PathBuf, MAIN_SEPARATOR}; use std::process::Command; use std::str::FromStr; use std::{ @@ -109,7 +111,8 @@ pub fn setup(src_path: &Path, profile: Profile) { println!("`x.py` will now use the configuration at {}", include_path.display()); let build = TargetSelection::from_user(&env!("BUILD_TRIPLE")); - let stage_path = ["build", build.rustc_target_arg(), "stage1"].join("/"); + let stage_path = + ["build", build.rustc_target_arg(), "stage1"].join(&MAIN_SEPARATOR.to_string()); println!(); @@ -171,6 +174,13 @@ fn attempt_toolchain_link(stage_path: &str) { return; } + if !ensure_stage1_toolchain_placeholder_exists(stage_path) { + println!( + "Failed to create a template for stage 1 toolchain or confirm that it already exists" + ); + return; + } + if try_link_toolchain(&stage_path[..]) { println!( "Added `stage1` rustup toolchain; try `cargo +stage1 build` on a separate rust project to run a newly-built toolchain" @@ -219,6 +229,33 @@ fn try_link_toolchain(stage_path: &str) -> bool { .map_or(false, |output| output.status.success()) } +fn ensure_stage1_toolchain_placeholder_exists(stage_path: &str) -> bool { + let pathbuf = PathBuf::from(stage_path); + + if fs::create_dir_all(pathbuf.join("lib")).is_err() { + return false; + }; + + let pathbuf = pathbuf.join("bin"); + if fs::create_dir_all(&pathbuf).is_err() { + return false; + }; + + let pathbuf = pathbuf.join(format!("rustc{}", EXE_SUFFIX)); + + if pathbuf.exists() { + return true; + } + + // Take care not to overwrite the file + let result = File::options().append(true).create(true).open(&pathbuf); + if result.is_err() { + return false; + } + + return true; +} + // Used to get the path for `Subcommand::Setup` pub fn interactive_path() -> io::Result { fn abbrev_all() -> impl Iterator { From 57b102ff73504d45318a66e0df852b74aacd5ca4 Mon Sep 17 00:00:00 2001 From: Ruby Lazuli Date: Sat, 5 Feb 2022 15:02:00 -0600 Subject: [PATCH 5/7] Fix tracking issue for `const_fn_trait_bound` It previously pointed to #57563, the conglomerate issue for `const fn` (presumably under the feature gate `const_fn`). `const_fn_trait_bounds` weren't mentioned here, so this commit changes its tracking issue to a new one. --- compiler/rustc_feature/src/active.rs | 2 +- .../consts/const_fn_trait_bound.stock.stderr | 6 ++--- .../consts/min_const_fn/min_const_fn.stderr | 24 +++++++++---------- .../min_const_fn/min_const_fn_dyn.stderr | 4 ++-- src/test/ui/nll/issue-55825-const-fn.stderr | 2 +- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index bfe2459dc8dc1..aed6ad3f8eca4 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -332,7 +332,7 @@ declare_features! ( /// Allows using and casting function pointers in a `const fn`. (active, const_fn_fn_ptr_basics, "1.48.0", Some(57563), None), /// Allows trait bounds in `const fn`. - (active, const_fn_trait_bound, "1.53.0", Some(57563), None), + (active, const_fn_trait_bound, "1.53.0", Some(93706), None), /// Allows `for _ in _` loops in const contexts. (active, const_for, "1.56.0", Some(87575), None), /// Allows argument and return position `impl Trait` in a `const fn`. diff --git a/src/test/ui/consts/const_fn_trait_bound.stock.stderr b/src/test/ui/consts/const_fn_trait_bound.stock.stderr index d652b5268a8bf..7d9e18cb341f3 100644 --- a/src/test/ui/consts/const_fn_trait_bound.stock.stderr +++ b/src/test/ui/consts/const_fn_trait_bound.stock.stderr @@ -4,7 +4,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl LL | const fn test1() {} | ^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait objects in const fn are unstable @@ -13,7 +13,7 @@ error[E0658]: trait objects in const fn are unstable LL | const fn test2(_x: &dyn Send) {} | ^^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait objects in const fn are unstable @@ -22,7 +22,7 @@ error[E0658]: trait objects in const fn are unstable LL | const fn test3() -> &'static dyn Send { loop {} } | ^^^^^^^^^^^^^^^^^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error: aborting due to 3 previous errors diff --git a/src/test/ui/consts/min_const_fn/min_const_fn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn.stderr index fd1ab6f64bf56..67cb604b6a7be 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn.stderr @@ -136,7 +136,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl LL | const fn foo11(t: T) -> T { t } | ^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable @@ -145,7 +145,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl LL | const fn foo11_2(t: T) -> T { t } | ^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0013]: constant functions cannot refer to statics @@ -218,7 +218,7 @@ LL | LL | const fn foo(&self) {} | ------------------- function declared as const here | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable @@ -230,7 +230,7 @@ LL | LL | const fn foo2(&self) {} | -------------------- function declared as const here | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable @@ -242,7 +242,7 @@ LL | LL | const fn foo3(&self) {} | -------------------- function declared as const here | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait bounds other than `Sized` on const fn parameters are unstable @@ -251,7 +251,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl LL | const fn no_apit2(_x: AlanTuring) {} | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0493]: destructors cannot be evaluated at compile-time @@ -268,7 +268,7 @@ error[E0658]: trait bounds other than `Sized` on const fn parameters are unstabl LL | const fn no_apit(_x: impl std::fmt::Debug) {} | ^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0493]: destructors cannot be evaluated at compile-time @@ -285,7 +285,7 @@ error[E0658]: trait objects in const fn are unstable LL | const fn no_dyn_trait(_x: &dyn std::fmt::Debug) {} | ^^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait objects in const fn are unstable @@ -294,7 +294,7 @@ error[E0658]: trait objects in const fn are unstable LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait objects in const fn are unstable @@ -305,7 +305,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 | | | function declared as const here | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait objects in const fn are unstable @@ -316,7 +316,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 | | | function declared as const here | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait objects in const fn are unstable @@ -327,7 +327,7 @@ LL | const fn really_no_traits_i_mean_it() { (&() as &dyn std::fmt::Debug, ()).1 | | | function declared as const here | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: function pointers cannot appear in constant functions diff --git a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr index 6eec1df5aeca7..4c2199101d302 100644 --- a/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr +++ b/src/test/ui/consts/min_const_fn/min_const_fn_dyn.stderr @@ -6,7 +6,7 @@ LL | const fn no_inner_dyn_trait2(x: Hide) { LL | x.0.field; | ^^^^^^^^^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error[E0658]: trait objects in const fn are unstable @@ -17,7 +17,7 @@ LL | const fn no_inner_dyn_trait_ret() -> Hide { Hide(HasDyn { field: &0 }) } | | | function declared as const here | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/issue-55825-const-fn.stderr b/src/test/ui/nll/issue-55825-const-fn.stderr index 9af5180343bf2..c834f8bd9c4f5 100644 --- a/src/test/ui/nll/issue-55825-const-fn.stderr +++ b/src/test/ui/nll/issue-55825-const-fn.stderr @@ -4,7 +4,7 @@ error[E0658]: trait objects in const fn are unstable LL | const fn no_dyn_trait_ret() -> &'static dyn std::fmt::Debug { &() } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: see issue #57563 for more information + = note: see issue #93706 for more information = help: add `#![feature(const_fn_trait_bound)]` to the crate attributes to enable error: aborting due to previous error From afb7a502f6e4e564d034ebf9601f4a4a13551f15 Mon Sep 17 00:00:00 2001 From: Inteon <42113979+inteon@users.noreply.github.com> Date: Sun, 6 Feb 2022 20:07:03 +0100 Subject: [PATCH 6/7] rewrite from_bytes_with_nul to match code style in from_vec_with_nul Signed-off-by: Inteon <42113979+inteon@users.noreply.github.com> --- library/std/src/ffi/c_str.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 66fee2fe54837..e10c6a5daf13e 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -1252,15 +1252,16 @@ impl CStr { /// assert!(cstr.is_err()); /// ``` #[stable(feature = "cstr_from_bytes", since = "1.10.0")] - pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&CStr, FromBytesWithNulError> { + pub fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> { let nul_pos = memchr::memchr(0, bytes); - if let Some(nul_pos) = nul_pos { - if nul_pos + 1 != bytes.len() { - return Err(FromBytesWithNulError::interior_nul(nul_pos)); + match nul_pos { + Some(nul_pos) if nul_pos + 1 == bytes.len() => { + // SAFETY: We know there is only one nul byte, at the end + // of the byte slice. + Ok(unsafe { Self::from_bytes_with_nul_unchecked(bytes) }) } - Ok(unsafe { CStr::from_bytes_with_nul_unchecked(bytes) }) - } else { - Err(FromBytesWithNulError::not_nul_terminated()) + Some(nul_pos) => Err(FromBytesWithNulError::interior_nul(nul_pos)), + None => Err(FromBytesWithNulError::not_nul_terminated()), } } From cf4ac6b1e16e08ee7513ed03a323c6d00504beb2 Mon Sep 17 00:00:00 2001 From: Jane Lusby Date: Fri, 28 Jan 2022 14:07:27 -0800 Subject: [PATCH 7/7] Add From for ExitCode This should cover a mostly cross-platform subset of supported exit codes. --- library/std/src/process.rs | 8 ++++++++ library/std/src/sys/unix/process/process_common.rs | 6 ++++++ library/std/src/sys/unsupported/process.rs | 9 +++++++++ library/std/src/sys/windows/process.rs | 6 ++++++ 4 files changed, 29 insertions(+) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 7d7e08a714938..1f04890539604 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1691,6 +1691,14 @@ impl ExitCode { } } +#[unstable(feature = "process_exitcode_placeholder", issue = "48711")] +impl From for ExitCode { + /// Construct an exit code from an arbitrary u8 value. + fn from(code: u8) -> Self { + ExitCode(imp::ExitCode::from(code)) + } +} + impl Child { /// Forces the child process to exit. If the child has already exited, an [`InvalidInput`] /// error is returned. diff --git a/library/std/src/sys/unix/process/process_common.rs b/library/std/src/sys/unix/process/process_common.rs index 7ac2f9d8af75a..97985ddd3316b 100644 --- a/library/std/src/sys/unix/process/process_common.rs +++ b/library/std/src/sys/unix/process/process_common.rs @@ -476,6 +476,12 @@ impl ExitCode { } } +impl From for ExitCode { + fn from(code: u8) -> Self { + Self(code) + } +} + pub struct CommandArgs<'a> { iter: crate::slice::Iter<'a, CString>, } diff --git a/library/std/src/sys/unsupported/process.rs b/library/std/src/sys/unsupported/process.rs index 7846e43cfb53e..deb58ffa8c7de 100644 --- a/library/std/src/sys/unsupported/process.rs +++ b/library/std/src/sys/unsupported/process.rs @@ -162,6 +162,15 @@ impl ExitCode { } } +impl From for ExitCode { + fn from(code: u8) -> Self { + match code { + 0 => Self::SUCCESS, + 1..255 => Self::FAILURE, + } + } +} + pub struct Process(!); impl Process { diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 5ad570427978e..f9e71951b2a23 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -666,6 +666,12 @@ impl ExitCode { } } +impl From for ExitCode { + fn from(code: u8) -> Self { + ExitCode(c::DWORD::from(code)) + } +} + fn zeroed_startupinfo() -> c::STARTUPINFO { c::STARTUPINFO { cb: 0,