Skip to content

Commit 24e6ba0

Browse files
committed
Add a macro that simplifies transitioning to the Rust intrinsic ABI
Migrating intrinsics at this time seems to come with a lot of boilerplate in the form of attributes and empty bodies (see <rust-lang#127337> for an example). Add a macro that simplifies this, and makes the transition from `extern "rust-intrinsic"` intrinsics much cleaner.
1 parent f00f850 commit 24e6ba0

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

library/core/src/intrinsics.rs

+87
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,93 @@ pub unsafe fn drop_in_place<T: ?Sized>(to_drop: *mut T) {
8585
unsafe { crate::ptr::drop_in_place(to_drop) }
8686
}
8787

88+
/// Turn function signatures into an intrinsic implementation in the Rust ABI, with an
89+
/// `unimplemented!` body.
90+
///
91+
/// This applies an `unstable` attribute, so don't use it with functions that are stable.
92+
/// Due to macro limitations, functions with keyword qualifiers `const` or `unsafe` cannot be
93+
/// combined with functions that do not have them, or have a different combination, and as such
94+
/// must be placed in separate `intrinsics!` blocks.
95+
///
96+
/// Const intrinsics do not get `rustc_const_{stable, unstable}`.
97+
macro_rules! intrinsics {
98+
// Default: non-const, safe
99+
( $(
100+
$(#[$meta:meta])*
101+
pub fn $name:ident
102+
$(<$( $gen:ident $(: $bound:ident $(+ $bound2:ident)* $(+ $bound_lt:lifetime)*)? ),* >)?
103+
($($args:tt)*) $(-> $ret:ty)?;
104+
105+
)* ) => { $(
106+
#[rustc_nounwind]
107+
#[rustc_intrinsic]
108+
#[rustc_intrinsic_must_be_overridden]
109+
#[unstable(feature = "core_intrinsics", issue = "none")]
110+
$(#[$meta])*
111+
pub fn $name $(<$( $gen $(: $bound $(+ $bound2)* $(+ $bound_lt)*)? ),* >)?
112+
($($args)*) $(-> $ret)? {
113+
unreachable!();
114+
}
115+
)+ };
116+
117+
// non-const, unsafe
118+
( $(
119+
$(#[$meta:meta])*
120+
pub unsafe fn $name:ident
121+
$(<$( $gen:ident $(: $bound:ident $(+ $bound2:ident)* $(+ $bound_lt:lifetime)*)? ),* >)?
122+
($($args:tt)*) $(-> $ret:ty)?;
123+
124+
)* ) => { $(
125+
#[rustc_nounwind]
126+
#[rustc_intrinsic]
127+
#[rustc_intrinsic_must_be_overridden]
128+
#[unstable(feature = "core_intrinsics", issue = "none")]
129+
$(#[$meta])*
130+
pub unsafe fn $name $(<$( $gen $(: $bound $(+ $bound2)* $(+ $bound_lt)*)? ),* >)?
131+
($($args)*) $(-> $ret)? {
132+
unreachable!();
133+
}
134+
)+ };
135+
136+
// const, safe
137+
( $(
138+
$(#[$meta:meta])*
139+
pub const fn $name:ident
140+
$(<$( $gen:ident $(: $bound:ident $(+ $bound2:ident)* $(+ $bound_lt:lifetime)*)? ),* >)?
141+
($($args:tt)*) $(-> $ret:ty)?;
142+
143+
)* ) => { $(
144+
#[rustc_nounwind]
145+
#[rustc_intrinsic]
146+
#[rustc_intrinsic_must_be_overridden]
147+
#[unstable(feature = "core_intrinsics", issue = "none")]
148+
$(#[$meta])*
149+
pub const fn $name $(<$( $gen $(: $bound $(+ $bound2)* $(+ $bound_lt)*)? ),* >)?
150+
($($args)*) $(-> $ret)? {
151+
unreachable!();
152+
}
153+
)+ };
154+
155+
// const, unsafe
156+
( $(
157+
$(#[$meta:meta])*
158+
pub const unsafe fn $name:ident
159+
$(<$( $gen:ident $(: $bound:ident $(+ $bound2:ident)* $(+ $bound_lt:lifetime)*)? ),* >)?
160+
($($args:tt)*) $(-> $ret:ty)?;
161+
162+
)* ) => { $(
163+
#[rustc_nounwind]
164+
#[rustc_intrinsic]
165+
#[rustc_intrinsic_must_be_overridden]
166+
#[unstable(feature = "core_intrinsics", issue = "none")]
167+
$(#[$meta])*
168+
pub const unsafe fn $name $(<$( $gen $(: $bound $(+ $bound2)* $(+ $bound_lt)*)? ),* >)?
169+
($($args)*) $(-> $ret)? {
170+
unreachable!();
171+
}
172+
)+ };
173+
}
174+
88175
extern "rust-intrinsic" {
89176
// N.B., these intrinsics take raw pointers because they mutate aliased
90177
// memory, which is not valid for either `&` or `&mut`.

0 commit comments

Comments
 (0)