Auto merge of #128298 - matthiaskrgr:rollup-0wdu2wo, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #127853 (`#[naked]`: report incompatible attributes) - #128276 (Add a README to rustbook to explain its purpose) - #128279 (Stabilize `is_sorted`) - #128282 (bitwise and bytewise methods on `NonZero`) - #128285 (rustc book: document how the RUST_TARGET_PATH variable is used) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
3954398882
@ -220,6 +220,11 @@ builtin_macros_multiple_defaults = multiple declared defaults
|
||||
.note = only one variant can be default
|
||||
.suggestion = make `{$ident}` default
|
||||
|
||||
builtin_macros_naked_functions_testing_attribute =
|
||||
cannot use `#[naked]` with testing attributes
|
||||
.label = function marked with testing attribute here
|
||||
.naked_attribute = `#[naked]` is incompatible with testing attributes
|
||||
|
||||
builtin_macros_no_default_variant = no default declared
|
||||
.help = make a unit variant default by placing `#[default]` above it
|
||||
.suggestion = make `{$ident}` default
|
||||
|
@ -923,3 +923,13 @@ pub(crate) struct ExpectedItem<'a> {
|
||||
pub span: Span,
|
||||
pub token: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(builtin_macros_naked_functions_testing_attribute, code = E0736)]
|
||||
pub struct NakedFunctionTestingAttribute {
|
||||
#[primary_span]
|
||||
#[label(builtin_macros_naked_attribute)]
|
||||
pub naked_span: Span,
|
||||
#[label]
|
||||
pub testing_span: Span,
|
||||
}
|
||||
|
@ -133,6 +133,14 @@ pub(crate) fn expand_test_or_bench(
|
||||
};
|
||||
};
|
||||
|
||||
if let Some(attr) = attr::find_by_name(&item.attrs, sym::naked) {
|
||||
cx.dcx().emit_err(errors::NakedFunctionTestingAttribute {
|
||||
testing_span: attr_sp,
|
||||
naked_span: attr.span,
|
||||
});
|
||||
return vec![Annotatable::Item(item)];
|
||||
}
|
||||
|
||||
// check_*_signature will report any errors in the type so compilation
|
||||
// will fail. We shouldn't try to expand in this case because the errors
|
||||
// would be spurious.
|
||||
|
@ -3,7 +3,6 @@
|
||||
coroutines,
|
||||
stmt_expr_attributes,
|
||||
coroutine_trait,
|
||||
is_sorted,
|
||||
repr_simd,
|
||||
tuple_trait,
|
||||
unboxed_closures
|
||||
|
@ -1,5 +1,5 @@
|
||||
#![allow(internal_features)]
|
||||
#![feature(core_intrinsics, coroutines, coroutine_trait, is_sorted, stmt_expr_attributes)]
|
||||
#![feature(core_intrinsics, coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||
|
||||
#[cfg(feature="master")]
|
||||
#[cfg(target_arch="x86_64")]
|
||||
|
@ -1,14 +1,20 @@
|
||||
`#[track_caller]` and `#[naked]` cannot both be applied to the same function.
|
||||
Functions marked with the `#[naked]` attribute are restricted in what other
|
||||
attributes they may be marked with.
|
||||
|
||||
Notable attributes that are incompatible with `#[naked]` are:
|
||||
|
||||
* `#[inline]`
|
||||
* `#[track_caller]`
|
||||
* `#[test]`, `#[ignore]`, `#[should_panic]`
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0736
|
||||
#[inline]
|
||||
#[naked]
|
||||
#[track_caller]
|
||||
fn foo() {}
|
||||
```
|
||||
|
||||
This is primarily due to ABI incompatibilities between the two attributes.
|
||||
See [RFC 2091] for details on this and other limitations.
|
||||
|
||||
[RFC 2091]: https://github.com/rust-lang/rfcs/blob/master/text/2091-inline-semantic.md
|
||||
These incompatibilities are due to the fact that naked functions deliberately
|
||||
impose strict restrictions regarding the code that the compiler is
|
||||
allowed to produce for this function.
|
||||
|
@ -1,4 +1,4 @@
|
||||
`#[track_caller]` can not be applied on struct.
|
||||
`#[track_caller]` must be applied to a function
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
|
@ -64,7 +64,6 @@
|
||||
#![doc(rust_logo)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(never_type)]
|
||||
|
@ -1984,14 +1984,18 @@
|
||||
///
|
||||
/// ```rust
|
||||
/// trait MyIterator : Iterator {
|
||||
/// // is_sorted is an unstable method that already exists on the Iterator trait
|
||||
/// fn is_sorted(self) -> bool where Self: Sized {true}
|
||||
/// // is_partitioned is an unstable method that already exists on the Iterator trait
|
||||
/// fn is_partitioned<P>(self, predicate: P) -> bool
|
||||
/// where
|
||||
/// Self: Sized,
|
||||
/// P: FnMut(Self::Item) -> bool,
|
||||
/// {true}
|
||||
/// }
|
||||
///
|
||||
/// impl<T: ?Sized> MyIterator for T where T: Iterator { }
|
||||
///
|
||||
/// let x = vec![1, 2, 3];
|
||||
/// let _ = x.iter().is_sorted();
|
||||
/// let _ = x.iter().is_partitioned(|_| true);
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
@ -2007,7 +2011,7 @@
|
||||
/// is an early-warning to let you know that there may be a collision in
|
||||
/// the future. This can be avoided by adding type annotations to
|
||||
/// disambiguate which trait method you intend to call, such as
|
||||
/// `MyIterator::is_sorted(my_iter)` or renaming or removing the method.
|
||||
/// `MyIterator::is_partitioned(my_iter, my_predicate)` or renaming or removing the method.
|
||||
///
|
||||
/// [nightly channel]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
|
||||
/// [`feature` attribute]: https://doc.rust-lang.org/nightly/unstable-book/
|
||||
|
@ -6,7 +6,6 @@
|
||||
#![feature(decl_macro)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(impl_trait_in_assoc_type)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(map_try_insert)]
|
||||
#![feature(never_type)]
|
||||
|
@ -1,6 +1,5 @@
|
||||
// tidy-alphabetical-start
|
||||
#![feature(array_windows)]
|
||||
#![feature(is_sorted)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
|
@ -69,9 +69,6 @@ passes_break_non_loop =
|
||||
.suggestion = use `break` on its own without a value inside this `{$kind}` loop
|
||||
.break_expr_suggestion = alternatively, you might have meant to use the available loop label
|
||||
|
||||
passes_cannot_inline_naked_function =
|
||||
naked functions cannot be inlined
|
||||
|
||||
passes_cannot_stabilize_deprecated =
|
||||
an API can't be stabilized after it is deprecated
|
||||
.label = invalid version
|
||||
@ -485,6 +482,11 @@ passes_naked_functions_asm_block =
|
||||
passes_naked_functions_asm_options =
|
||||
asm options unsupported in naked functions: {$unsupported_options}
|
||||
|
||||
passes_naked_functions_incompatible_attribute =
|
||||
attribute incompatible with `#[naked]`
|
||||
.label = the `{$attr}` attribute is incompatible with `#[naked]`
|
||||
.naked_attribute = function marked with `#[naked]` here
|
||||
|
||||
passes_naked_functions_must_use_noreturn =
|
||||
asm in naked functions must use `noreturn` option
|
||||
.suggestion = consider specifying that the asm block is responsible for returning from the function
|
||||
@ -492,9 +494,6 @@ passes_naked_functions_must_use_noreturn =
|
||||
passes_naked_functions_operands =
|
||||
only `const` and `sym` operands are supported in naked functions
|
||||
|
||||
passes_naked_tracked_caller =
|
||||
cannot use `#[track_caller]` with `#[naked]`
|
||||
|
||||
passes_no_link =
|
||||
attribute should be applied to an `extern crate` item
|
||||
.label = not an `extern crate` item
|
||||
|
@ -155,7 +155,7 @@ fn check_attributes(
|
||||
[sym::rustc_std_internal_symbol] => {
|
||||
self.check_rustc_std_internal_symbol(attr, span, target)
|
||||
}
|
||||
[sym::naked] => self.check_naked(hir_id, attr, span, target),
|
||||
[sym::naked] => self.check_naked(hir_id, attr, span, target, attrs),
|
||||
[sym::rustc_never_returns_null_ptr] => {
|
||||
self.check_applied_to_fn_or_method(hir_id, attr, span, target)
|
||||
}
|
||||
@ -410,12 +410,71 @@ fn check_generic_attr(
|
||||
}
|
||||
|
||||
/// Checks if `#[naked]` is applied to a function definition.
|
||||
fn check_naked(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) -> bool {
|
||||
fn check_naked(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
attr: &Attribute,
|
||||
span: Span,
|
||||
target: Target,
|
||||
attrs: &[Attribute],
|
||||
) -> bool {
|
||||
// many attributes don't make sense in combination with #[naked].
|
||||
// Notable attributes that are incompatible with `#[naked]` are:
|
||||
//
|
||||
// * `#[inline]`
|
||||
// * `#[track_caller]`
|
||||
// * `#[test]`, `#[ignore]`, `#[should_panic]`
|
||||
//
|
||||
// NOTE: when making changes to this list, check that `error_codes/E0736.md` remains accurate
|
||||
const ALLOW_LIST: &[rustc_span::Symbol] = &[
|
||||
// conditional compilation
|
||||
sym::cfg,
|
||||
sym::cfg_attr,
|
||||
// testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`)
|
||||
sym::test,
|
||||
sym::ignore,
|
||||
sym::should_panic,
|
||||
sym::bench,
|
||||
// diagnostics
|
||||
sym::allow,
|
||||
sym::warn,
|
||||
sym::deny,
|
||||
sym::forbid,
|
||||
sym::deprecated,
|
||||
sym::must_use,
|
||||
// abi, linking and FFI
|
||||
sym::export_name,
|
||||
sym::link_section,
|
||||
sym::linkage,
|
||||
sym::no_mangle,
|
||||
sym::naked,
|
||||
sym::instruction_set,
|
||||
// code generation
|
||||
sym::cold,
|
||||
sym::target_feature,
|
||||
// documentation
|
||||
sym::doc,
|
||||
];
|
||||
|
||||
match target {
|
||||
Target::Fn
|
||||
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
|
||||
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {
|
||||
for other_attr in attrs {
|
||||
if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) {
|
||||
self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute {
|
||||
span: other_attr.span,
|
||||
naked_span: attr.span,
|
||||
attr: other_attr.name_or_empty(),
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
|
||||
// `#[allow_internal_unstable]` attribute with just a lint, because we previously
|
||||
// `#[naked]` attribute with just a lint, because we previously
|
||||
// erroneously allowed it and some crates used it accidentally, to be compatible
|
||||
// with crates depending on them, we can't throw an error here.
|
||||
Target::Field | Target::Arm | Target::MacroDef => {
|
||||
@ -488,7 +547,7 @@ fn check_collapse_debuginfo(&self, attr: &Attribute, span: Span, target: Target)
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if a `#[track_caller]` is applied to a non-naked function. Returns `true` if valid.
|
||||
/// Checks if a `#[track_caller]` is applied to a function. Returns `true` if valid.
|
||||
fn check_track_caller(
|
||||
&self,
|
||||
hir_id: HirId,
|
||||
@ -498,10 +557,6 @@ fn check_track_caller(
|
||||
target: Target,
|
||||
) -> bool {
|
||||
match target {
|
||||
_ if attrs.iter().any(|attr| attr.has_name(sym::naked)) => {
|
||||
self.dcx().emit_err(errors::NakedTrackedCaller { attr_span });
|
||||
false
|
||||
}
|
||||
Target::Fn => {
|
||||
// `#[track_caller]` is not valid on weak lang items because they are called via
|
||||
// `extern` declarations and `#[track_caller]` would alter their ABI.
|
||||
|
@ -79,13 +79,6 @@ pub struct AttrShouldBeAppliedToFn {
|
||||
pub on_crate: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_naked_tracked_caller, code = E0736)]
|
||||
pub struct NakedTrackedCaller {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_should_be_applied_to_fn, code = E0739)]
|
||||
pub struct TrackedCallerWrongLocation {
|
||||
@ -1124,13 +1117,6 @@ pub struct UnlabeledCfInWhileCondition<'a> {
|
||||
pub cf_type: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_cannot_inline_naked_function)]
|
||||
pub struct CannotInlineNakedFunction {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_undefined_naked_function_abi)]
|
||||
pub struct UndefinedNakedFunctionAbi;
|
||||
@ -1196,6 +1182,17 @@ pub struct NakedFunctionsMustUseNoreturn {
|
||||
pub last_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_naked_functions_incompatible_attribute, code = E0736)]
|
||||
pub struct NakedFunctionIncompatibleAttribute {
|
||||
#[primary_span]
|
||||
#[label]
|
||||
pub span: Span,
|
||||
#[label(passes_naked_attribute)]
|
||||
pub naked_span: Span,
|
||||
pub attr: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_attr_only_in_functions)]
|
||||
pub struct AttrOnlyInFunctions {
|
||||
|
@ -14,9 +14,8 @@
|
||||
use rustc_target::spec::abi::Abi;
|
||||
|
||||
use crate::errors::{
|
||||
CannotInlineNakedFunction, NakedFunctionsAsmBlock, NakedFunctionsAsmOptions,
|
||||
NakedFunctionsMustUseNoreturn, NakedFunctionsOperands, NoPatterns, ParamsNotAllowed,
|
||||
UndefinedNakedFunctionAbi,
|
||||
NakedFunctionsAsmBlock, NakedFunctionsAsmOptions, NakedFunctionsMustUseNoreturn,
|
||||
NakedFunctionsOperands, NoPatterns, ParamsNotAllowed, UndefinedNakedFunctionAbi,
|
||||
};
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers) {
|
||||
@ -53,15 +52,6 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
||||
check_no_patterns(tcx, body.params);
|
||||
check_no_parameters_use(tcx, body);
|
||||
check_asm(tcx, def_id, body);
|
||||
check_inline(tcx, def_id);
|
||||
}
|
||||
}
|
||||
|
||||
/// Check that the function isn't inlined.
|
||||
fn check_inline(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
let attrs = tcx.get_attrs(def_id, sym::inline);
|
||||
for attr in attrs {
|
||||
tcx.dcx().emit_err(CannotInlineNakedFunction { span: attr.span });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,7 +92,6 @@
|
||||
// tidy-alphabetical-start
|
||||
#![cfg_attr(not(no_global_oom_handling), feature(const_alloc_error))]
|
||||
#![cfg_attr(not(no_global_oom_handling), feature(const_btree_len))]
|
||||
#![cfg_attr(test, feature(is_sorted))]
|
||||
#![cfg_attr(test, feature(new_uninit))]
|
||||
#![feature(alloc_layout_extra)]
|
||||
#![feature(allocator_api)]
|
||||
|
@ -3951,8 +3951,6 @@ fn ge<I>(self, other: I) -> bool
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(is_sorted)]
|
||||
///
|
||||
/// assert!([1, 2, 2, 9].iter().is_sorted());
|
||||
/// assert!(![1, 3, 2, 4].iter().is_sorted());
|
||||
/// assert!([0].iter().is_sorted());
|
||||
@ -3960,7 +3958,7 @@ fn ge<I>(self, other: I) -> bool
|
||||
/// assert!(![0.0, 1.0, f32::NAN].iter().is_sorted());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
|
||||
#[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn is_sorted(self) -> bool
|
||||
where
|
||||
@ -3978,8 +3976,6 @@ fn is_sorted(self) -> bool
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(is_sorted)]
|
||||
///
|
||||
/// assert!([1, 2, 2, 9].iter().is_sorted_by(|a, b| a <= b));
|
||||
/// assert!(![1, 2, 2, 9].iter().is_sorted_by(|a, b| a < b));
|
||||
///
|
||||
@ -3989,7 +3985,7 @@ fn is_sorted(self) -> bool
|
||||
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| false));
|
||||
/// assert!(std::iter::empty::<i32>().is_sorted_by(|a, b| true));
|
||||
/// ```
|
||||
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
|
||||
#[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn is_sorted_by<F>(mut self, compare: F) -> bool
|
||||
where
|
||||
@ -4030,13 +4026,11 @@ fn check<'a, T>(
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(is_sorted)]
|
||||
///
|
||||
/// assert!(["c", "bb", "aaa"].iter().is_sorted_by_key(|s| s.len()));
|
||||
/// assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
|
||||
#[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[rustc_do_not_const_check]
|
||||
fn is_sorted_by_key<F, K>(self, f: F) -> bool
|
||||
where
|
||||
|
@ -455,6 +455,12 @@ macro_rules! nonzero_integer {
|
||||
UnsignedPrimitive = $Uint:ty,
|
||||
|
||||
// Used in doc comments.
|
||||
rot = $rot:literal,
|
||||
rot_op = $rot_op:literal,
|
||||
rot_result = $rot_result:literal,
|
||||
swap_op = $swap_op:literal,
|
||||
swapped = $swapped:literal,
|
||||
reversed = $reversed:literal,
|
||||
leading_zeros_test = $leading_zeros_test:expr,
|
||||
) => {
|
||||
/// An integer that is known not to equal zero.
|
||||
@ -604,6 +610,270 @@ pub const fn count_ones(self) -> NonZero<u32> {
|
||||
unsafe { NonZero::new_unchecked(self.get().count_ones()) }
|
||||
}
|
||||
|
||||
/// Shifts the bits to the left by a specified amount, `n`,
|
||||
/// wrapping the truncated bits to the end of the resulting integer.
|
||||
///
|
||||
/// Please note this isn't the same operation as the `<<` shifting operator!
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(nonzero_bitwise)]
|
||||
/// # use std::num::NonZero;
|
||||
/// #
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let n = NonZero::new(", $rot_op, stringify!($Int), ")?;")]
|
||||
#[doc = concat!("let m = NonZero::new(", $rot_result, ")?;")]
|
||||
///
|
||||
#[doc = concat!("assert_eq!(n.rotate_left(", $rot, "), m);")]
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn rotate_left(self, n: u32) -> Self {
|
||||
let result = self.get().rotate_left(n);
|
||||
// SAFETY: Rotating bits preserves the property int > 0.
|
||||
unsafe { Self::new_unchecked(result) }
|
||||
}
|
||||
|
||||
/// Shifts the bits to the right by a specified amount, `n`,
|
||||
/// wrapping the truncated bits to the beginning of the resulting
|
||||
/// integer.
|
||||
///
|
||||
/// Please note this isn't the same operation as the `>>` shifting operator!
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(nonzero_bitwise)]
|
||||
/// # use std::num::NonZero;
|
||||
/// #
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let n = NonZero::new(", $rot_result, stringify!($Int), ")?;")]
|
||||
#[doc = concat!("let m = NonZero::new(", $rot_op, ")?;")]
|
||||
///
|
||||
#[doc = concat!("assert_eq!(n.rotate_right(", $rot, "), m);")]
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn rotate_right(self, n: u32) -> Self {
|
||||
let result = self.get().rotate_right(n);
|
||||
// SAFETY: Rotating bits preserves the property int > 0.
|
||||
unsafe { Self::new_unchecked(result) }
|
||||
}
|
||||
|
||||
/// Reverses the byte order of the integer.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(nonzero_bitwise)]
|
||||
/// # use std::num::NonZero;
|
||||
/// #
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let n = NonZero::new(", $swap_op, stringify!($Int), ")?;")]
|
||||
/// let m = n.swap_bytes();
|
||||
///
|
||||
#[doc = concat!("assert_eq!(m, NonZero::new(", $swapped, ")?);")]
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn swap_bytes(self) -> Self {
|
||||
let result = self.get().swap_bytes();
|
||||
// SAFETY: Shuffling bytes preserves the property int > 0.
|
||||
unsafe { Self::new_unchecked(result) }
|
||||
}
|
||||
|
||||
/// Reverses the order of bits in the integer. The least significant bit becomes the most significant bit,
|
||||
/// second least-significant bit becomes second most-significant bit, etc.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(nonzero_bitwise)]
|
||||
/// # use std::num::NonZero;
|
||||
/// #
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let n = NonZero::new(", $swap_op, stringify!($Int), ")?;")]
|
||||
/// let m = n.reverse_bits();
|
||||
///
|
||||
#[doc = concat!("assert_eq!(m, NonZero::new(", $reversed, ")?);")]
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn reverse_bits(self) -> Self {
|
||||
let result = self.get().reverse_bits();
|
||||
// SAFETY: Reversing bits preserves the property int > 0.
|
||||
unsafe { Self::new_unchecked(result) }
|
||||
}
|
||||
|
||||
/// Converts an integer from big endian to the target's endianness.
|
||||
///
|
||||
/// On big endian this is a no-op. On little endian the bytes are
|
||||
/// swapped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(nonzero_bitwise)]
|
||||
/// # use std::num::NonZero;
|
||||
#[doc = concat!("use std::num::", stringify!($Ty), ";")]
|
||||
/// #
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")]
|
||||
///
|
||||
/// if cfg!(target_endian = "big") {
|
||||
#[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_be(n), n)")]
|
||||
/// } else {
|
||||
#[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_be(n), n.swap_bytes())")]
|
||||
/// }
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
|
||||
#[must_use]
|
||||
#[inline(always)]
|
||||
pub const fn from_be(x: Self) -> Self {
|
||||
let result = $Int::from_be(x.get());
|
||||
// SAFETY: Shuffling bytes preserves the property int > 0.
|
||||
unsafe { Self::new_unchecked(result) }
|
||||
}
|
||||
|
||||
/// Converts an integer from little endian to the target's endianness.
|
||||
///
|
||||
/// On little endian this is a no-op. On big endian the bytes are
|
||||
/// swapped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(nonzero_bitwise)]
|
||||
/// # use std::num::NonZero;
|
||||
#[doc = concat!("use std::num::", stringify!($Ty), ";")]
|
||||
/// #
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")]
|
||||
///
|
||||
/// if cfg!(target_endian = "little") {
|
||||
#[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_le(n), n)")]
|
||||
/// } else {
|
||||
#[doc = concat!(" assert_eq!(", stringify!($Ty), "::from_le(n), n.swap_bytes())")]
|
||||
/// }
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
|
||||
#[must_use]
|
||||
#[inline(always)]
|
||||
pub const fn from_le(x: Self) -> Self {
|
||||
let result = $Int::from_le(x.get());
|
||||
// SAFETY: Shuffling bytes preserves the property int > 0.
|
||||
unsafe { Self::new_unchecked(result) }
|
||||
}
|
||||
|
||||
/// Converts `self` to big endian from the target's endianness.
|
||||
///
|
||||
/// On big endian this is a no-op. On little endian the bytes are
|
||||
/// swapped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(nonzero_bitwise)]
|
||||
/// # use std::num::NonZero;
|
||||
/// #
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")]
|
||||
///
|
||||
/// if cfg!(target_endian = "big") {
|
||||
/// assert_eq!(n.to_be(), n)
|
||||
/// } else {
|
||||
/// assert_eq!(n.to_be(), n.swap_bytes())
|
||||
/// }
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn to_be(self) -> Self {
|
||||
let result = self.get().to_be();
|
||||
// SAFETY: Shuffling bytes preserves the property int > 0.
|
||||
unsafe { Self::new_unchecked(result) }
|
||||
}
|
||||
|
||||
/// Converts `self` to little endian from the target's endianness.
|
||||
///
|
||||
/// On little endian this is a no-op. On big endian the bytes are
|
||||
/// swapped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(nonzero_bitwise)]
|
||||
/// # use std::num::NonZero;
|
||||
/// #
|
||||
/// # fn main() { test().unwrap(); }
|
||||
/// # fn test() -> Option<()> {
|
||||
#[doc = concat!("let n = NonZero::new(0x1A", stringify!($Int), ")?;")]
|
||||
///
|
||||
/// if cfg!(target_endian = "little") {
|
||||
/// assert_eq!(n.to_le(), n)
|
||||
/// } else {
|
||||
/// assert_eq!(n.to_le(), n.swap_bytes())
|
||||
/// }
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "nonzero_bitwise", issue = "128281")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
without modifying the original"]
|
||||
#[inline(always)]
|
||||
pub const fn to_le(self) -> Self {
|
||||
let result = self.get().to_le();
|
||||
// SAFETY: Shuffling bytes preserves the property int > 0.
|
||||
unsafe { Self::new_unchecked(result) }
|
||||
}
|
||||
|
||||
nonzero_integer_signedness_dependent_methods! {
|
||||
Primitive = $signedness $Int,
|
||||
UnsignedPrimitive = $Uint,
|
||||
@ -826,22 +1096,54 @@ fn from_str(src: &str) -> Result<Self, Self::Err> {
|
||||
nonzero_integer_signedness_dependent_impls!($signedness $Int);
|
||||
};
|
||||
|
||||
(Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => {
|
||||
(
|
||||
Self = $Ty:ident,
|
||||
Primitive = unsigned $Int:ident,
|
||||
rot = $rot:literal,
|
||||
rot_op = $rot_op:literal,
|
||||
rot_result = $rot_result:literal,
|
||||
swap_op = $swap_op:literal,
|
||||
swapped = $swapped:literal,
|
||||
reversed = $reversed:literal,
|
||||
$(,)?
|
||||
) => {
|
||||
nonzero_integer! {
|
||||
#[stable(feature = "nonzero", since = "1.28.0")]
|
||||
Self = $Ty,
|
||||
Primitive = unsigned $Int,
|
||||
UnsignedPrimitive = $Int,
|
||||
rot = $rot,
|
||||
rot_op = $rot_op,
|
||||
rot_result = $rot_result,
|
||||
swap_op = $swap_op,
|
||||
swapped = $swapped,
|
||||
reversed = $reversed,
|
||||
leading_zeros_test = concat!(stringify!($Int), "::MAX"),
|
||||
}
|
||||
};
|
||||
|
||||
(Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => {
|
||||
(
|
||||
Self = $Ty:ident,
|
||||
Primitive = signed $Int:ident,
|
||||
UnsignedPrimitive = $UInt:ident,
|
||||
rot = $rot:literal,
|
||||
rot_op = $rot_op:literal,
|
||||
rot_result = $rot_result:literal,
|
||||
swap_op = $swap_op:literal,
|
||||
swapped = $swapped:literal,
|
||||
reversed = $reversed:literal,
|
||||
) => {
|
||||
nonzero_integer! {
|
||||
#[stable(feature = "signed_nonzero", since = "1.34.0")]
|
||||
Self = $Ty,
|
||||
Primitive = signed $Int,
|
||||
$($rest)*
|
||||
UnsignedPrimitive = $UInt,
|
||||
rot = $rot,
|
||||
rot_op = $rot_op,
|
||||
rot_result = $rot_result,
|
||||
swap_op = $swap_op,
|
||||
swapped = $swapped,
|
||||
reversed = $reversed,
|
||||
leading_zeros_test = concat!("-1", stringify!($Int)),
|
||||
}
|
||||
};
|
||||
@ -1241,6 +1543,7 @@ pub const fn is_power_of_two(self) -> bool {
|
||||
/// assert_eq!(ten.isqrt(), three);
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "isqrt", issue = "116226")]
|
||||
#[rustc_const_unstable(feature = "isqrt", issue = "116226")]
|
||||
#[must_use = "this returns the result of the operation, \
|
||||
@ -1704,65 +2007,189 @@ macro_rules! sign_dependent_expr {
|
||||
nonzero_integer! {
|
||||
Self = NonZeroU8,
|
||||
Primitive = unsigned u8,
|
||||
rot = 2,
|
||||
rot_op = "0x82",
|
||||
rot_result = "0xa",
|
||||
swap_op = "0x12",
|
||||
swapped = "0x12",
|
||||
reversed = "0x48",
|
||||
}
|
||||
|
||||
nonzero_integer! {
|
||||
Self = NonZeroU16,
|
||||
Primitive = unsigned u16,
|
||||
rot = 4,
|
||||
rot_op = "0xa003",
|
||||
rot_result = "0x3a",
|
||||
swap_op = "0x1234",
|
||||
swapped = "0x3412",
|
||||
reversed = "0x2c48",
|
||||
}
|
||||
|
||||
nonzero_integer! {
|
||||
Self = NonZeroU32,
|
||||
Primitive = unsigned u32,
|
||||
rot = 8,
|
||||
rot_op = "0x10000b3",
|
||||
rot_result = "0xb301",
|
||||
swap_op = "0x12345678",
|
||||
swapped = "0x78563412",
|
||||
reversed = "0x1e6a2c48",
|
||||
}
|
||||
|
||||
nonzero_integer! {
|
||||
Self = NonZeroU64,
|
||||
Primitive = unsigned u64,
|
||||
rot = 12,
|
||||
rot_op = "0xaa00000000006e1",
|
||||
rot_result = "0x6e10aa",
|
||||
swap_op = "0x1234567890123456",
|
||||
swapped = "0x5634129078563412",
|
||||
reversed = "0x6a2c48091e6a2c48",
|
||||
}
|
||||
|
||||
nonzero_integer! {
|
||||
Self = NonZeroU128,
|
||||
Primitive = unsigned u128,
|
||||
rot = 16,
|
||||
rot_op = "0x13f40000000000000000000000004f76",
|
||||
rot_result = "0x4f7613f4",
|
||||
swap_op = "0x12345678901234567890123456789012",
|
||||
swapped = "0x12907856341290785634129078563412",
|
||||
reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
nonzero_integer! {
|
||||
Self = NonZeroUsize,
|
||||
Primitive = unsigned usize,
|
||||
rot = 4,
|
||||
rot_op = "0xa003",
|
||||
rot_result = "0x3a",
|
||||
swap_op = "0x1234",
|
||||
swapped = "0x3412",
|
||||
reversed = "0x2c48",
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
nonzero_integer! {
|
||||
Self = NonZeroUsize,
|
||||
Primitive = unsigned usize,
|
||||
rot = 8,
|
||||
rot_op = "0x10000b3",
|
||||
rot_result = "0xb301",
|
||||
swap_op = "0x12345678",
|
||||
swapped = "0x78563412",
|
||||
reversed = "0x1e6a2c48",
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
nonzero_integer! {
|
||||
Self = NonZeroUsize,
|
||||
Primitive = unsigned usize,
|
||||
rot = 12,
|
||||
rot_op = "0xaa00000000006e1",
|
||||
rot_result = "0x6e10aa",
|
||||
swap_op = "0x1234567890123456",
|
||||
swapped = "0x5634129078563412",
|
||||
reversed = "0x6a2c48091e6a2c48",
|
||||
}
|
||||
|
||||
nonzero_integer! {
|
||||
Self = NonZeroI8,
|
||||
Primitive = signed i8,
|
||||
UnsignedPrimitive = u8,
|
||||
rot = 2,
|
||||
rot_op = "-0x7e",
|
||||
rot_result = "0xa",
|
||||
swap_op = "0x12",
|
||||
swapped = "0x12",
|
||||
reversed = "0x48",
|
||||
}
|
||||
|
||||
nonzero_integer! {
|
||||
Self = NonZeroI16,
|
||||
Primitive = signed i16,
|
||||
UnsignedPrimitive = u16,
|
||||
rot = 4,
|
||||
rot_op = "-0x5ffd",
|
||||
rot_result = "0x3a",
|
||||
swap_op = "0x1234",
|
||||
swapped = "0x3412",
|
||||
reversed = "0x2c48",
|
||||
}
|
||||
|
||||
nonzero_integer! {
|
||||
Self = NonZeroI32,
|
||||
Primitive = signed i32,
|
||||
UnsignedPrimitive = u32,
|
||||
rot = 8,
|
||||
rot_op = "0x10000b3",
|
||||
rot_result = "0xb301",
|
||||
swap_op = "0x12345678",
|
||||
swapped = "0x78563412",
|
||||
reversed = "0x1e6a2c48",
|
||||
}
|
||||
|
||||
nonzero_integer! {
|
||||
Self = NonZeroI64,
|
||||
Primitive = signed i64,
|
||||
UnsignedPrimitive = u64,
|
||||
rot = 12,
|
||||
rot_op = "0xaa00000000006e1",
|
||||
rot_result = "0x6e10aa",
|
||||
swap_op = "0x1234567890123456",
|
||||
swapped = "0x5634129078563412",
|
||||
reversed = "0x6a2c48091e6a2c48",
|
||||
}
|
||||
|
||||
nonzero_integer! {
|
||||
Self = NonZeroI128,
|
||||
Primitive = signed i128,
|
||||
UnsignedPrimitive = u128,
|
||||
rot = 16,
|
||||
rot_op = "0x13f40000000000000000000000004f76",
|
||||
rot_result = "0x4f7613f4",
|
||||
swap_op = "0x12345678901234567890123456789012",
|
||||
swapped = "0x12907856341290785634129078563412",
|
||||
reversed = "0x48091e6a2c48091e6a2c48091e6a2c48",
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
nonzero_integer! {
|
||||
Self = NonZeroIsize,
|
||||
Primitive = signed isize,
|
||||
UnsignedPrimitive = usize,
|
||||
rot = 4,
|
||||
rot_op = "-0x5ffd",
|
||||
rot_result = "0x3a",
|
||||
swap_op = "0x1234",
|
||||
swapped = "0x3412",
|
||||
reversed = "0x2c48",
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
nonzero_integer! {
|
||||
Self = NonZeroIsize,
|
||||
Primitive = signed isize,
|
||||
UnsignedPrimitive = usize,
|
||||
rot = 8,
|
||||
rot_op = "0x10000b3",
|
||||
rot_result = "0xb301",
|
||||
swap_op = "0x12345678",
|
||||
swapped = "0x78563412",
|
||||
reversed = "0x1e6a2c48",
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
nonzero_integer! {
|
||||
Self = NonZeroIsize,
|
||||
Primitive = signed isize,
|
||||
UnsignedPrimitive = usize,
|
||||
rot = 12,
|
||||
rot_op = "0xaa00000000006e1",
|
||||
rot_result = "0x6e10aa",
|
||||
swap_op = "0x1234567890123456",
|
||||
swapped = "0x5634129078563412",
|
||||
reversed = "0x6a2c48091e6a2c48",
|
||||
}
|
||||
|
@ -4069,7 +4069,6 @@ pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LA
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(is_sorted)]
|
||||
/// let empty: [i32; 0] = [];
|
||||
///
|
||||
/// assert!([1, 2, 2, 9].is_sorted());
|
||||
@ -4079,7 +4078,7 @@ pub fn as_simd_mut<const LANES: usize>(&mut self) -> (&mut [T], &mut [Simd<T, LA
|
||||
/// assert!(![0.0, 1.0, f32::NAN].is_sorted());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
|
||||
#[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use]
|
||||
pub fn is_sorted(&self) -> bool
|
||||
where
|
||||
@ -4096,8 +4095,6 @@ pub fn is_sorted(&self) -> bool
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(is_sorted)]
|
||||
///
|
||||
/// assert!([1, 2, 2, 9].is_sorted_by(|a, b| a <= b));
|
||||
/// assert!(![1, 2, 2, 9].is_sorted_by(|a, b| a < b));
|
||||
///
|
||||
@ -4108,7 +4105,7 @@ pub fn is_sorted(&self) -> bool
|
||||
/// assert!(empty.is_sorted_by(|a, b| false));
|
||||
/// assert!(empty.is_sorted_by(|a, b| true));
|
||||
/// ```
|
||||
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
|
||||
#[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use]
|
||||
pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool
|
||||
where
|
||||
@ -4128,13 +4125,11 @@ pub fn is_sorted_by<'a, F>(&'a self, mut compare: F) -> bool
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(is_sorted)]
|
||||
///
|
||||
/// assert!(["c", "bb", "aaa"].is_sorted_by_key(|s| s.len()));
|
||||
/// assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "is_sorted", reason = "new API", issue = "53485")]
|
||||
#[stable(feature = "is_sorted", since = "CURRENT_RUSTC_VERSION")]
|
||||
#[must_use]
|
||||
pub fn is_sorted_by_key<'a, F, K>(&'a self, f: F) -> bool
|
||||
where
|
||||
|
@ -44,7 +44,6 @@
|
||||
#![feature(hasher_prefixfree_extras)]
|
||||
#![feature(hashmap_internals)]
|
||||
#![feature(try_find)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(layout_for_ptr)]
|
||||
#![feature(pattern)]
|
||||
#![feature(slice_take)]
|
||||
|
@ -15,3 +15,16 @@ rustc +nightly -Z unstable-options --target=wasm32-unknown-unknown --print targe
|
||||
```
|
||||
|
||||
To use a custom target, see the (unstable) [`build-std` feature](../../cargo/reference/unstable.html#build-std) of `cargo`.
|
||||
|
||||
## Custom Target Lookup Path
|
||||
|
||||
When `rustc` is given an option `--target=TARGET` (where `TARGET` is any string), it uses the following logic:
|
||||
1. if `TARGET` is the name of a built-in target, use that
|
||||
2. if `TARGET` is a path to a file, read that file as a json target
|
||||
3. otherwise, search the colon-seperated list of directories found
|
||||
in the `RUST_TARGET_PATH` environment variable from left to right
|
||||
for a file named `TARGET.json`.
|
||||
|
||||
These steps are tried in order, so if there are multple potentially valid
|
||||
interpretations for a target, whichever is found first will take priority.
|
||||
If none of these methods find a target, an error is thrown.
|
||||
|
@ -1,11 +0,0 @@
|
||||
# `is_sorted`
|
||||
|
||||
The tracking issue for this feature is: [#53485]
|
||||
|
||||
[#53485]: https://github.com/rust-lang/rust/issues/53485
|
||||
|
||||
------------------------
|
||||
|
||||
Add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to `[T]`;
|
||||
add the methods `is_sorted`, `is_sorted_by` and `is_sorted_by_key` to
|
||||
`Iterator`.
|
@ -5,7 +5,6 @@
|
||||
#![feature(f128)]
|
||||
#![feature(f16)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(iter_intersperse)]
|
||||
#![feature(iter_partition_in_place)]
|
||||
#![feature(let_chains)]
|
||||
|
@ -1,4 +1,3 @@
|
||||
#![feature(is_sorted)]
|
||||
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
|
||||
#![warn(rust_2018_idioms, unused_lifetimes)]
|
||||
#![allow(unused_extern_crates)]
|
||||
|
@ -2,7 +2,6 @@
|
||||
#![allow(clippy::needless_return)]
|
||||
#![allow(clippy::unused_unit)]
|
||||
#![allow(clippy::useless_vec)]
|
||||
#![feature(is_sorted)]
|
||||
|
||||
struct Struct {
|
||||
field: isize,
|
||||
|
@ -1,11 +1,11 @@
|
||||
error: this closure returns the unit type which also implements Ord
|
||||
--> tests/ui/unit_return_expecting_ord.rs:19:25
|
||||
--> tests/ui/unit_return_expecting_ord.rs:18:25
|
||||
|
|
||||
LL | structs.sort_by_key(|s| {
|
||||
| ^^^
|
||||
|
|
||||
help: probably caused by this trailing semicolon
|
||||
--> tests/ui/unit_return_expecting_ord.rs:21:24
|
||||
--> tests/ui/unit_return_expecting_ord.rs:20:24
|
||||
|
|
||||
LL | double(s.field);
|
||||
| ^
|
||||
@ -13,25 +13,25 @@ LL | double(s.field);
|
||||
= help: to override `-D warnings` add `#[allow(clippy::unit_return_expecting_ord)]`
|
||||
|
||||
error: this closure returns the unit type which also implements PartialOrd
|
||||
--> tests/ui/unit_return_expecting_ord.rs:24:30
|
||||
--> tests/ui/unit_return_expecting_ord.rs:23:30
|
||||
|
|
||||
LL | structs.is_sorted_by_key(|s| {
|
||||
| ^^^
|
||||
|
|
||||
help: probably caused by this trailing semicolon
|
||||
--> tests/ui/unit_return_expecting_ord.rs:26:24
|
||||
--> tests/ui/unit_return_expecting_ord.rs:25:24
|
||||
|
|
||||
LL | double(s.field);
|
||||
| ^
|
||||
|
||||
error: this closure returns the unit type which also implements PartialOrd
|
||||
--> tests/ui/unit_return_expecting_ord.rs:28:30
|
||||
--> tests/ui/unit_return_expecting_ord.rs:27:30
|
||||
|
|
||||
LL | structs.is_sorted_by_key(|s| {
|
||||
| ^^^
|
||||
|
||||
error: this closure returns the unit type which also implements Ord
|
||||
--> tests/ui/unit_return_expecting_ord.rs:39:25
|
||||
--> tests/ui/unit_return_expecting_ord.rs:38:25
|
||||
|
|
||||
LL | structs.sort_by_key(|s| unit(s.field));
|
||||
| ^^^
|
||||
|
34
src/tools/rustbook/README.md
Normal file
34
src/tools/rustbook/README.md
Normal file
@ -0,0 +1,34 @@
|
||||
# Rustbook
|
||||
|
||||
This is a wrapper around [`mdbook`](https://github.com/rust-lang/mdBook/), which is used to generate the book-style documentation in the Rust project. This wrapper serves a few purposes:
|
||||
|
||||
- Avoids some of mdbook's large, optional dependencies (like tokio, webserver, etc.).
|
||||
- Makes it a little easier to customize and override some of mdbook's behaviors (like swapping in custom preprocessors).
|
||||
- Supports vendoring of the source via Rust's normal release process.
|
||||
|
||||
This is invoked automatically when building mdbook-style documentation, for example via `./x doc`.
|
||||
|
||||
## Cargo workspace
|
||||
|
||||
This package defines a separate cargo workspace from the main Rust workspace for a few reasons (ref [#127786](https://github.com/rust-lang/rust/pull/127786):
|
||||
|
||||
- Avoids requiring checking out submodules for developers who are not working on the documentation. Otherwise, some submodules such as those that have custom preprocessors would be required for cargo to find the dependencies.
|
||||
- Avoids problems with updating dependencies. Unfortunately this workspace has a rather large set of dependencies, which can make coordinating updates difficult (see [#127890](https://github.com/rust-lang/rust/issues/127890)).
|
||||
|
||||
## Custom preprocessors
|
||||
|
||||
Some books have custom mdbook preprocessors that need to be integrated with both the book's repository, and the build system here in the `rust-lang/rust` repository. To add a new preprocessor, there are few things to do:
|
||||
|
||||
1. Implement the preprocessor as a cargo library in the book's repository.
|
||||
2. Add the `[preprocessor]` table to the book's `book.toml` file. I recommend setting the command so that the preprocessor gets built automatically. It may look something like:
|
||||
```toml
|
||||
[preprocessor.spec]
|
||||
command = "cargo run --manifest-path my-cool-extension/Cargo.toml"
|
||||
|
||||
[build]
|
||||
extra-watch-dirs = ["my-cool-extension/src"]
|
||||
```
|
||||
3. Add the preprocessor as a dependency in rustbook's `Cargo.toml`.
|
||||
4. Call `with_preprocessor` in `rustbook/src/main.rs`.
|
||||
5. Be sure to test that it generates correctly, such as running `./x doc MY-BOOK-NAME --open` and verify the content looks correct.
|
||||
6. Also test tidy and your book, such as running `./x test tidy` and `./x test MY-BOOK-NAME`.
|
@ -1,8 +1,6 @@
|
||||
//@ check-pass
|
||||
// regression test for https://github.com/rust-lang/rust/issues/53485#issuecomment-885393452
|
||||
|
||||
#![feature(is_sorted)]
|
||||
|
||||
struct A {
|
||||
name: String,
|
||||
}
|
||||
|
38
tests/ui/asm/naked-functions-inline.rs
Normal file
38
tests/ui/asm/naked-functions-inline.rs
Normal file
@ -0,0 +1,38 @@
|
||||
//@ needs-asm-support
|
||||
#![feature(naked_functions)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn inline_none() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline]
|
||||
//~^ ERROR [E0736]
|
||||
pub unsafe extern "C" fn inline_hint() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline(always)]
|
||||
//~^ ERROR [E0736]
|
||||
pub unsafe extern "C" fn inline_always() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline(never)]
|
||||
//~^ ERROR [E0736]
|
||||
pub unsafe extern "C" fn inline_never() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[cfg_attr(all(), inline(never))]
|
||||
//~^ ERROR [E0736]
|
||||
pub unsafe extern "C" fn conditional_inline_never() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
35
tests/ui/asm/naked-functions-inline.stderr
Normal file
35
tests/ui/asm/naked-functions-inline.stderr
Normal file
@ -0,0 +1,35 @@
|
||||
error[E0736]: attribute incompatible with `#[naked]`
|
||||
--> $DIR/naked-functions-inline.rs:13:1
|
||||
|
|
||||
LL | #[naked]
|
||||
| -------- function marked with `#[naked]` here
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^ the `inline` attribute is incompatible with `#[naked]`
|
||||
|
||||
error[E0736]: attribute incompatible with `#[naked]`
|
||||
--> $DIR/naked-functions-inline.rs:20:1
|
||||
|
|
||||
LL | #[naked]
|
||||
| -------- function marked with `#[naked]` here
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[naked]`
|
||||
|
||||
error[E0736]: attribute incompatible with `#[naked]`
|
||||
--> $DIR/naked-functions-inline.rs:27:1
|
||||
|
|
||||
LL | #[naked]
|
||||
| -------- function marked with `#[naked]` here
|
||||
LL | #[inline(never)]
|
||||
| ^^^^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[naked]`
|
||||
|
||||
error[E0736]: attribute incompatible with `#[naked]`
|
||||
--> $DIR/naked-functions-inline.rs:34:19
|
||||
|
|
||||
LL | #[naked]
|
||||
| -------- function marked with `#[naked]` here
|
||||
LL | #[cfg_attr(all(), inline(never))]
|
||||
| ^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[naked]`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0736`.
|
30
tests/ui/asm/naked-functions-instruction-set.rs
Normal file
30
tests/ui/asm/naked-functions-instruction-set.rs
Normal file
@ -0,0 +1,30 @@
|
||||
//@ compile-flags: --target armv5te-unknown-linux-gnueabi
|
||||
//@ needs-llvm-components: arm
|
||||
//@ needs-asm-support
|
||||
//@ build-pass
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(no_core, lang_items, rustc_attrs, naked_functions)]
|
||||
#![no_core]
|
||||
|
||||
#[rustc_builtin_macro]
|
||||
macro_rules! asm {
|
||||
() => {};
|
||||
}
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
#[instruction_set(arm::t32)]
|
||||
unsafe extern "C" fn test_thumb() {
|
||||
asm!("bx lr", options(noreturn));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
#[instruction_set(arm::t32)]
|
||||
unsafe extern "C" fn test_arm() {
|
||||
asm!("bx lr", options(noreturn));
|
||||
}
|
39
tests/ui/asm/naked-functions-testattrs.rs
Normal file
39
tests/ui/asm/naked-functions-testattrs.rs
Normal file
@ -0,0 +1,39 @@
|
||||
//@ needs-asm-support
|
||||
//@ compile-flags: --test
|
||||
|
||||
#![allow(undefined_naked_function_abi)]
|
||||
#![feature(naked_functions)]
|
||||
#![feature(test)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
#[test]
|
||||
#[naked]
|
||||
//~^ ERROR [E0736]
|
||||
fn test_naked() {
|
||||
unsafe { asm!("", options(noreturn)) };
|
||||
}
|
||||
|
||||
#[should_panic]
|
||||
#[test]
|
||||
#[naked]
|
||||
//~^ ERROR [E0736]
|
||||
fn test_naked_should_panic() {
|
||||
unsafe { asm!("", options(noreturn)) };
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
#[naked]
|
||||
//~^ ERROR [E0736]
|
||||
fn test_naked_ignore() {
|
||||
unsafe { asm!("", options(noreturn)) };
|
||||
}
|
||||
|
||||
#[bench]
|
||||
#[naked]
|
||||
//~^ ERROR [E0736]
|
||||
fn bench_naked() {
|
||||
unsafe { asm!("", options(noreturn)) };
|
||||
}
|
35
tests/ui/asm/naked-functions-testattrs.stderr
Normal file
35
tests/ui/asm/naked-functions-testattrs.stderr
Normal file
@ -0,0 +1,35 @@
|
||||
error[E0736]: cannot use `#[naked]` with testing attributes
|
||||
--> $DIR/naked-functions-testattrs.rs:12:1
|
||||
|
|
||||
LL | #[test]
|
||||
| ------- function marked with testing attribute here
|
||||
LL | #[naked]
|
||||
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes
|
||||
|
||||
error[E0736]: cannot use `#[naked]` with testing attributes
|
||||
--> $DIR/naked-functions-testattrs.rs:20:1
|
||||
|
|
||||
LL | #[test]
|
||||
| ------- function marked with testing attribute here
|
||||
LL | #[naked]
|
||||
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes
|
||||
|
||||
error[E0736]: cannot use `#[naked]` with testing attributes
|
||||
--> $DIR/naked-functions-testattrs.rs:28:1
|
||||
|
|
||||
LL | #[test]
|
||||
| ------- function marked with testing attribute here
|
||||
LL | #[naked]
|
||||
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes
|
||||
|
||||
error[E0736]: cannot use `#[naked]` with testing attributes
|
||||
--> $DIR/naked-functions-testattrs.rs:35:1
|
||||
|
|
||||
LL | #[bench]
|
||||
| -------- function marked with testing attribute here
|
||||
LL | #[naked]
|
||||
| ^^^^^^^^ `#[naked]` is incompatible with testing attributes
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0736`.
|
@ -3,7 +3,7 @@
|
||||
//@ ignore-spirv
|
||||
|
||||
#![feature(naked_functions)]
|
||||
#![feature(asm_const, asm_unwind)]
|
||||
#![feature(asm_const, asm_unwind, linkage)]
|
||||
#![crate_type = "lib"]
|
||||
|
||||
use std::arch::asm;
|
||||
@ -163,42 +163,6 @@ pub extern "C" fn valid_b() {
|
||||
}
|
||||
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn inline_none() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline]
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
pub unsafe extern "C" fn inline_hint() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline(always)]
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
pub unsafe extern "C" fn inline_always() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline(never)]
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
pub unsafe extern "C" fn inline_never() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[inline]
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
#[inline(always)]
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
#[inline(never)]
|
||||
//~^ ERROR naked functions cannot be inlined
|
||||
pub unsafe extern "C" fn inline_all() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn allow_compile_error(a: u32) -> u32 {
|
||||
compile_error!("this is a user specified error")
|
||||
@ -217,3 +181,71 @@ pub extern "C" fn valid_b() {
|
||||
asm!(invalid_syntax)
|
||||
//~^ ERROR asm template must be a string literal
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[cfg_attr(target_pointer_width = "64", no_mangle)]
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn compatible_cfg_attributes() {
|
||||
asm!("", options(noreturn, att_syntax));
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[warn(dead_code)]
|
||||
#[deny(dead_code)]
|
||||
#[forbid(dead_code)]
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn compatible_diagnostic_attributes() {
|
||||
asm!("", options(noreturn, raw));
|
||||
}
|
||||
|
||||
#[deprecated = "test"]
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn compatible_deprecated_attributes() {
|
||||
asm!("", options(noreturn, raw));
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[must_use]
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn compatible_must_use_attributes() -> u64 {
|
||||
asm!(
|
||||
"
|
||||
mov rax, 42
|
||||
ret
|
||||
",
|
||||
options(noreturn)
|
||||
)
|
||||
}
|
||||
|
||||
#[export_name = "exported_function_name"]
|
||||
#[link_section = ".custom_section"]
|
||||
#[no_mangle]
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn compatible_ffi_attributes_1() {
|
||||
asm!("", options(noreturn, raw));
|
||||
}
|
||||
|
||||
#[cold]
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn compatible_codegen_attributes() {
|
||||
asm!("", options(noreturn, raw));
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[target_feature(enable = "sse2")]
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn compatible_target_feature() {
|
||||
asm!("", options(noreturn));
|
||||
}
|
||||
|
||||
#[doc = "foo bar baz"]
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn compatible_doc_attributes() {
|
||||
asm!("", options(noreturn, raw));
|
||||
}
|
||||
|
||||
#[linkage = "external"]
|
||||
#[naked]
|
||||
pub unsafe extern "C" fn compatible_linkage() {
|
||||
asm!("", options(noreturn, raw));
|
||||
}
|
||||
|
@ -5,19 +5,19 @@ LL | asm!("", options(readonly, nostack), options(pure));
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^
|
||||
|
||||
error: this is a user specified error
|
||||
--> $DIR/naked-functions.rs:204:5
|
||||
--> $DIR/naked-functions.rs:168:5
|
||||
|
|
||||
LL | compile_error!("this is a user specified error")
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this is a user specified error
|
||||
--> $DIR/naked-functions.rs:210:5
|
||||
--> $DIR/naked-functions.rs:174:5
|
||||
|
|
||||
LL | compile_error!("this is a user specified error");
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: asm template must be a string literal
|
||||
--> $DIR/naked-functions.rs:217:10
|
||||
--> $DIR/naked-functions.rs:181:10
|
||||
|
|
||||
LL | asm!(invalid_syntax)
|
||||
| ^^^^^^^^^^^^^^
|
||||
@ -249,42 +249,6 @@ warning: Rust ABI is unsupported in naked functions
|
||||
LL | pub unsafe fn rust_abi() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:171:1
|
||||
|
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:178:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:185:1
|
||||
|
|
||||
LL | #[inline(never)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:192:1
|
||||
|
|
||||
LL | #[inline]
|
||||
| ^^^^^^^^^
|
||||
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:194:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: naked functions cannot be inlined
|
||||
--> $DIR/naked-functions.rs:196:1
|
||||
|
|
||||
LL | #[inline(never)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 33 previous errors; 2 warnings emitted
|
||||
error: aborting due to 27 previous errors; 2 warnings emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0787`.
|
||||
|
@ -1,13 +0,0 @@
|
||||
fn main() {
|
||||
// Assert `Iterator` methods are unstable
|
||||
assert!([1, 2, 2, 9].iter().is_sorted());
|
||||
//~^ ERROR: use of unstable library feature 'is_sorted': new API
|
||||
assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
|
||||
//~^ ERROR: use of unstable library feature 'is_sorted': new API
|
||||
|
||||
// Assert `[T]` methods are unstable
|
||||
assert!([1, 2, 2, 9].is_sorted());
|
||||
//~^ ERROR: use of unstable library feature 'is_sorted': new API
|
||||
assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
|
||||
//~^ ERROR: use of unstable library feature 'is_sorted': new API
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
error[E0658]: use of unstable library feature 'is_sorted': new API
|
||||
--> $DIR/feature-gate-is_sorted.rs:3:33
|
||||
|
|
||||
LL | assert!([1, 2, 2, 9].iter().is_sorted());
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #53485 <https://github.com/rust-lang/rust/issues/53485> for more information
|
||||
= help: add `#![feature(is_sorted)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature 'is_sorted': new API
|
||||
--> $DIR/feature-gate-is_sorted.rs:5:39
|
||||
|
|
||||
LL | assert!(![-2i32, -1, 0, 3].iter().is_sorted_by_key(|n| n.abs()));
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #53485 <https://github.com/rust-lang/rust/issues/53485> for more information
|
||||
= help: add `#![feature(is_sorted)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature 'is_sorted': new API
|
||||
--> $DIR/feature-gate-is_sorted.rs:9:26
|
||||
|
|
||||
LL | assert!([1, 2, 2, 9].is_sorted());
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: see issue #53485 <https://github.com/rust-lang/rust/issues/53485> for more information
|
||||
= help: add `#![feature(is_sorted)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error[E0658]: use of unstable library feature 'is_sorted': new API
|
||||
--> $DIR/feature-gate-is_sorted.rs:11:32
|
||||
|
|
||||
LL | assert!(![-2i32, -1, 0, 3].is_sorted_by_key(|n| n.abs()));
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: see issue #53485 <https://github.com/rust-lang/rust/issues/53485> for more information
|
||||
= help: add `#![feature(is_sorted)]` to the crate attributes to enable
|
||||
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
@ -3,7 +3,7 @@
|
||||
|
||||
use std::arch::asm;
|
||||
|
||||
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
|
||||
#[track_caller] //~ ERROR [E0736]
|
||||
//~^ ERROR `#[track_caller]` requires Rust ABI
|
||||
#[naked]
|
||||
extern "C" fn f() {
|
||||
@ -15,7 +15,7 @@ extern "C" fn f() {
|
||||
struct S;
|
||||
|
||||
impl S {
|
||||
#[track_caller] //~ ERROR cannot use `#[track_caller]` with `#[naked]`
|
||||
#[track_caller] //~ ERROR [E0736]
|
||||
//~^ ERROR `#[track_caller]` requires Rust ABI
|
||||
#[naked]
|
||||
extern "C" fn g() {
|
||||
|
@ -1,14 +1,20 @@
|
||||
error[E0736]: cannot use `#[track_caller]` with `#[naked]`
|
||||
error[E0736]: attribute incompatible with `#[naked]`
|
||||
--> $DIR/error-with-naked.rs:6:1
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[naked]`
|
||||
LL |
|
||||
LL | #[naked]
|
||||
| -------- function marked with `#[naked]` here
|
||||
|
||||
error[E0736]: cannot use `#[track_caller]` with `#[naked]`
|
||||
error[E0736]: attribute incompatible with `#[naked]`
|
||||
--> $DIR/error-with-naked.rs:18:5
|
||||
|
|
||||
LL | #[track_caller]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[naked]`
|
||||
LL |
|
||||
LL | #[naked]
|
||||
| -------- function marked with `#[naked]` here
|
||||
|
||||
error[E0737]: `#[track_caller]` requires Rust ABI
|
||||
--> $DIR/error-with-naked.rs:6:1
|
||||
|
Loading…
Reference in New Issue
Block a user