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 ad817e185a3cf..87965b06435dd 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -2776,17 +2776,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 @@ -2813,14 +2816,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, @@ -2831,7 +2834,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 92ee3fd294bdf..d7af3bec0ca5c 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1559,15 +1559,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, } @@ -1584,12 +1584,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", @@ -1626,13 +1626,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 7b004fa086bf3..d415e37ff0116 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -122,7 +122,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/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs index db8776ac7418d..2ae92e89d63b5 100644 --- a/library/core/src/iter/adapters/mod.rs +++ b/library/core/src/iter/adapters/mod.rs @@ -1,5 +1,5 @@ use crate::iter::{InPlaceIterable, Iterator}; -use crate::ops::{ControlFlow, Try}; +use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, NeverShortCircuit, Residual, Try}; mod chain; mod cloned; @@ -128,41 +128,45 @@ pub unsafe trait SourceIter { } /// An iterator adapter that produces output as long as the underlying -/// iterator produces `Result::Ok` values. +/// iterator produces values where `Try::branch` says to `ControlFlow::Continue`. /// -/// If an error is encountered, the iterator stops and the error is -/// stored. -pub(crate) struct ResultShunt<'a, I, E> { +/// If a `ControlFlow::Break` is encountered, the iterator stops and the +/// residual is stored. +pub(crate) struct GenericShunt<'a, I, R> { iter: I, - error: &'a mut Result<(), E>, + residual: &'a mut Option, } -/// Process the given iterator as if it yielded a `T` instead of a -/// `Result`. Any errors will stop the inner iterator and -/// the overall result will be an error. -pub(crate) fn process_results(iter: I, mut f: F) -> Result +/// Process the given iterator as if it yielded a the item's `Try::Output` +/// type instead. Any `Try::Residual`s encountered will stop the inner iterator +/// and be propagated back to the overall result. +pub(crate) fn try_process(iter: I, mut f: F) -> ChangeOutputType where - I: Iterator>, - for<'a> F: FnMut(ResultShunt<'a, I, E>) -> U, + I: Iterator>, + for<'a> F: FnMut(GenericShunt<'a, I, R>) -> U, + R: Residual, { - let mut error = Ok(()); - let shunt = ResultShunt { iter, error: &mut error }; + let mut residual = None; + let shunt = GenericShunt { iter, residual: &mut residual }; let value = f(shunt); - error.map(|()| value) + match residual { + Some(r) => FromResidual::from_residual(r), + None => Try::from_output(value), + } } -impl Iterator for ResultShunt<'_, I, E> +impl Iterator for GenericShunt<'_, I, R> where - I: Iterator>, + I: Iterator>, { - type Item = T; + type Item = ::Output; fn next(&mut self) -> Option { - self.find(|_| true) + self.try_for_each(ControlFlow::Break).break_value() } fn size_hint(&self) -> (usize, Option) { - if self.error.is_err() { + if self.residual.is_some() { (0, Some(0)) } else { let (_, upper) = self.iter.size_hint(); @@ -170,17 +174,16 @@ where } } - fn try_fold(&mut self, init: B, mut f: F) -> R + fn try_fold(&mut self, init: B, mut f: F) -> T where - F: FnMut(B, Self::Item) -> R, - R: Try, + F: FnMut(B, Self::Item) -> T, + T: Try, { - let error = &mut *self.error; self.iter - .try_fold(init, |acc, x| match x { - Ok(x) => ControlFlow::from_try(f(acc, x)), - Err(e) => { - *error = Err(e); + .try_fold(init, |acc, x| match Try::branch(x) { + ControlFlow::Continue(x) => ControlFlow::from_try(f(acc, x)), + ControlFlow::Break(r) => { + *self.residual = Some(r); ControlFlow::Break(try { acc }) } }) @@ -192,17 +195,12 @@ where Self: Sized, F: FnMut(B, Self::Item) -> B, { - #[inline] - fn ok(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result { - move |acc, x| Ok(f(acc, x)) - } - - self.try_fold(init, ok(fold)).unwrap() + self.try_fold(init, NeverShortCircuit::wrap_mut_2(fold)).0 } } #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl SourceIter for ResultShunt<'_, I, E> +unsafe impl SourceIter for GenericShunt<'_, I, R> where I: SourceIter, { @@ -215,11 +213,11 @@ where } } -// SAFETY: ResultShunt::next calls I::find, which has to advance `iter` in order to -// return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's guaranteed that -// at least one item will be moved out from the underlying source. +// SAFETY: GenericShunt::next calls `I::try_for_each`, which has to advance `iter` +// in order to return `Some(_)`. Since `iter` has type `I: InPlaceIterable` it's +// guaranteed that at least one item will be moved out from the underlying source. #[unstable(issue = "none", feature = "inplace_iteration")] -unsafe impl InPlaceIterable for ResultShunt<'_, I, E> where - I: Iterator> + InPlaceIterable +unsafe impl InPlaceIterable for GenericShunt<'_, I, R> where + I: Iterator> + InPlaceIterable { } diff --git a/library/core/src/iter/mod.rs b/library/core/src/iter/mod.rs index da459ed7c68f4..65f56f64dbfa6 100644 --- a/library/core/src/iter/mod.rs +++ b/library/core/src/iter/mod.rs @@ -417,7 +417,7 @@ pub use self::adapters::{ #[unstable(feature = "iter_intersperse", reason = "recently added", issue = "79524")] pub use self::adapters::{Intersperse, IntersperseWith}; -pub(crate) use self::adapters::process_results; +pub(crate) use self::adapters::try_process; mod adapters; mod range; diff --git a/library/core/src/iter/traits/accum.rs b/library/core/src/iter/traits/accum.rs index c2e837df5ff2a..84d83ee39699f 100644 --- a/library/core/src/iter/traits/accum.rs +++ b/library/core/src/iter/traits/accum.rs @@ -167,7 +167,7 @@ where where I: Iterator>, { - iter::process_results(iter, |i| i.sum()) + iter::try_process(iter, |i| i.sum()) } } @@ -183,7 +183,7 @@ where where I: Iterator>, { - iter::process_results(iter, |i| i.product()) + iter::try_process(iter, |i| i.product()) } } @@ -210,7 +210,7 @@ where where I: Iterator>, { - iter.map(|x| x.ok_or(())).sum::>().ok() + iter::try_process(iter, |i| i.sum()) } } @@ -226,6 +226,6 @@ where where I: Iterator>, { - iter.map(|x| x.ok_or(())).product::>().ok() + iter::try_process(iter, |i| i.product()) } } diff --git a/library/core/src/ops/try_trait.rs b/library/core/src/ops/try_trait.rs index 6a414ae8c4b80..eac426ad31164 100644 --- a/library/core/src/ops/try_trait.rs +++ b/library/core/src/ops/try_trait.rs @@ -359,6 +359,14 @@ pub(crate) type ChangeOutputType = <::Residual as Residual>:: #[repr(transparent)] pub(crate) struct NeverShortCircuit(pub T); +impl NeverShortCircuit { + /// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`. + #[inline] + pub fn wrap_mut_2(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self { + move |a, b| NeverShortCircuit(f(a, b)) + } +} + pub(crate) enum NeverShortCircuitResidual {} impl Try for NeverShortCircuit { diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 611f4ab38ab33..ec04692d3e0c8 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -500,7 +500,7 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::iter::{FromIterator, FusedIterator, TrustedLen}; +use crate::iter::{self, FromIterator, FusedIterator, TrustedLen}; use crate::panicking::{panic, panic_str}; use crate::pin::Pin; use crate::{ @@ -2233,7 +2233,7 @@ impl> FromIterator> for Option { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. - iter.into_iter().map(|x| x.ok_or(())).collect::>().ok() + iter::try_process(iter.into_iter(), |i| i.collect()) } } diff --git a/library/core/src/result.rs b/library/core/src/result.rs index fbd6d419236ae..05b4fa035b1ae 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -2016,7 +2016,7 @@ impl> FromIterator> for Result { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. - iter::process_results(iter.into_iter(), |i| i.collect()) + iter::try_process(iter.into_iter(), |i| i.collect()) } } 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/run-make-fulldeps/core-no-fp-fmt-parse/Makefile b/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile index bc4562bef3a96..f79e4c3f4798c 100644 --- a/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile +++ b/src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile @@ -1,4 +1,4 @@ -include ../tools.mk all: - $(RUSTC) --edition=2018 --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse + $(RUSTC) --edition=2021 --crate-type=rlib ../../../../library/core/src/lib.rs --cfg no_fp_fmt_parse 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