Skip to content

Rollup of 2 pull requests #93702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 5 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions compiler/rustc_ast_passes/src/feature_gate.rs
Original file line number Diff line number Diff line change
@@ -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,
8 changes: 5 additions & 3 deletions compiler/rustc_metadata/src/native_libs.rs
Original file line number Diff line number Diff line change
@@ -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,
31 changes: 17 additions & 14 deletions compiler/rustc_middle/src/ty/layout.rs
Original file line number Diff line number Diff line change
@@ -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,
}
}

20 changes: 11 additions & 9 deletions compiler/rustc_target/src/abi/call/mod.rs
Original file line number Diff line number Diff line change
@@ -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),
86 changes: 49 additions & 37 deletions compiler/rustc_target/src/spec/abi.rs
Original file line number Diff line number Diff line change
@@ -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
22 changes: 11 additions & 11 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
})
}

2 changes: 1 addition & 1 deletion compiler/rustc_typeck/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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!(
78 changes: 38 additions & 40 deletions library/core/src/iter/adapters/mod.rs
Original file line number Diff line number Diff line change
@@ -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,59 +128,62 @@ 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<R>,
}

/// Process the given iterator as if it yielded a `T` instead of a
/// `Result<T, _>`. Any errors will stop the inner iterator and
/// the overall result will be an error.
pub(crate) fn process_results<I, T, E, F, U>(iter: I, mut f: F) -> Result<U, E>
/// 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<I, T, R, F, U>(iter: I, mut f: F) -> ChangeOutputType<I::Item, U>
where
I: Iterator<Item = Result<T, E>>,
for<'a> F: FnMut(ResultShunt<'a, I, E>) -> U,
I: Iterator<Item: Try<Output = T, Residual = R>>,
for<'a> F: FnMut(GenericShunt<'a, I, R>) -> U,
R: Residual<U>,
{
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<I, T, E> Iterator for ResultShunt<'_, I, E>
impl<I, R> Iterator for GenericShunt<'_, I, R>
where
I: Iterator<Item = Result<T, E>>,
I: Iterator<Item: Try<Residual = R>>,
{
type Item = T;
type Item = <I::Item as Try>::Output;

fn next(&mut self) -> Option<Self::Item> {
self.find(|_| true)
self.try_for_each(ControlFlow::Break).break_value()
}

fn size_hint(&self) -> (usize, Option<usize>) {
if self.error.is_err() {
if self.residual.is_some() {
(0, Some(0))
} else {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}

fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
fn try_fold<B, F, T>(&mut self, init: B, mut f: F) -> T
where
F: FnMut(B, Self::Item) -> R,
R: Try<Output = B>,
F: FnMut(B, Self::Item) -> T,
T: Try<Output = B>,
{
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<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
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<I, E> SourceIter for ResultShunt<'_, I, E>
unsafe impl<I, R> 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<I, T, E> InPlaceIterable for ResultShunt<'_, I, E> where
I: Iterator<Item = Result<T, E>> + InPlaceIterable
unsafe impl<I, T, R> InPlaceIterable for GenericShunt<'_, I, R> where
I: Iterator<Item: Try<Output = T, Residual = R>> + InPlaceIterable
{
}
2 changes: 1 addition & 1 deletion library/core/src/iter/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
8 changes: 4 additions & 4 deletions library/core/src/iter/traits/accum.rs
Original file line number Diff line number Diff line change
@@ -167,7 +167,7 @@ where
where
I: Iterator<Item = Result<U, E>>,
{
iter::process_results(iter, |i| i.sum())
iter::try_process(iter, |i| i.sum())
}
}

@@ -183,7 +183,7 @@ where
where
I: Iterator<Item = Result<U, E>>,
{
iter::process_results(iter, |i| i.product())
iter::try_process(iter, |i| i.product())
}
}

@@ -210,7 +210,7 @@ where
where
I: Iterator<Item = Option<U>>,
{
iter.map(|x| x.ok_or(())).sum::<Result<_, _>>().ok()
iter::try_process(iter, |i| i.sum())
}
}

@@ -226,6 +226,6 @@ where
where
I: Iterator<Item = Option<U>>,
{
iter.map(|x| x.ok_or(())).product::<Result<_, _>>().ok()
iter::try_process(iter, |i| i.product())
}
}
8 changes: 8 additions & 0 deletions library/core/src/ops/try_trait.rs
Original file line number Diff line number Diff line change
@@ -359,6 +359,14 @@ pub(crate) type ChangeOutputType<T, V> = <<T as Try>::Residual as Residual<V>>::
#[repr(transparent)]
pub(crate) struct NeverShortCircuit<T>(pub T);

impl<T> NeverShortCircuit<T> {
/// Wrap a binary `FnMut` to return its result wrapped in a `NeverShortCircuit`.
#[inline]
pub fn wrap_mut_2<A, B>(mut f: impl FnMut(A, B) -> T) -> impl FnMut(A, B) -> Self {
move |a, b| NeverShortCircuit(f(a, b))
}
}

pub(crate) enum NeverShortCircuitResidual {}

impl<T> Try for NeverShortCircuit<T> {
4 changes: 2 additions & 2 deletions library/core/src/option.rs
Original file line number Diff line number Diff line change
@@ -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<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
// FIXME(#11084): This could be replaced with Iterator::scan when this
// performance bug is closed.

iter.into_iter().map(|x| x.ok_or(())).collect::<Result<_, _>>().ok()
iter::try_process(iter.into_iter(), |i| i.collect())
}
}

2 changes: 1 addition & 1 deletion library/core/src/result.rs
Original file line number Diff line number Diff line change
@@ -2016,7 +2016,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
// 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())
}
}

17 changes: 14 additions & 3 deletions src/doc/unstable-book/src/language-features/c-unwind.md
Original file line number Diff line number Diff line change
@@ -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.

31 changes: 31 additions & 0 deletions src/test/codegen/unwind-abis/aapcs-unwind-abi.rs
Original file line number Diff line number Diff line change
@@ -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: }
29 changes: 29 additions & 0 deletions src/test/codegen/unwind-abis/cdecl-unwind-abi.rs
Original file line number Diff line number Diff line change
@@ -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: }
31 changes: 31 additions & 0 deletions src/test/codegen/unwind-abis/fastcall-unwind-abi.rs
Original file line number Diff line number Diff line change
@@ -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: }
31 changes: 31 additions & 0 deletions src/test/codegen/unwind-abis/sysv64-unwind-abi.rs
Original file line number Diff line number Diff line change
@@ -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: }
31 changes: 31 additions & 0 deletions src/test/codegen/unwind-abis/vectorcall-unwind-abi.rs
Original file line number Diff line number Diff line change
@@ -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: }
31 changes: 31 additions & 0 deletions src/test/codegen/unwind-abis/win64-unwind-abi.rs
Original file line number Diff line number Diff line change
@@ -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: }
2 changes: 1 addition & 1 deletion src/test/run-make-fulldeps/core-no-fp-fmt-parse/Makefile
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion src/test/ui/codemap_tests/unicode.stderr
Original file line number Diff line number Diff line change
@@ -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

2 changes: 1 addition & 1 deletion src/test/ui/parser/issues/issue-8537.stderr
Original file line number Diff line number Diff line change
@@ -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