Auto merge of #142443 - matthiaskrgr:rollup-l1l6d0v, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang/rust#128425 (Make `missing_fragment_specifier` an unconditional error) - rust-lang/rust#135927 (retpoline and retpoline-external-thunk flags (target modifiers) to enable retpoline-related target features) - rust-lang/rust#140770 (add `extern "custom"` functions) - rust-lang/rust#142176 (tests: Split dont-shuffle-bswaps along opt-levels and arches) - rust-lang/rust#142248 (Add supported asm types for LoongArch32) - rust-lang/rust#142267 (assert more in release in `rustc_ast_lowering`) - rust-lang/rust#142274 (Update the stdarch submodule) - rust-lang/rust#142276 (Update dependencies in `library/Cargo.lock`) - rust-lang/rust#142308 (Upgrade `object`, `addr2line`, and `unwinding` in the standard library) Failed merges: - rust-lang/rust#140920 (Extract some shared code from codegen backend target feature handling) r? `@ghost` `@rustbot` modify labels: rollup try-job: aarch64-apple try-job: x86_64-msvc-1 try-job: x86_64-gnu try-job: dist-i586-gnu-i586-i686-musl try-job: test-various
This commit is contained in:
commit
8da623945f
91 changed files with 1450 additions and 535 deletions
|
|
@ -28,6 +28,9 @@ pub enum CanonAbi {
|
|||
Rust,
|
||||
RustCold,
|
||||
|
||||
/// An ABI that rustc does not know how to call or define.
|
||||
Custom,
|
||||
|
||||
/// ABIs relevant to 32-bit Arm targets
|
||||
Arm(ArmCall),
|
||||
/// ABI relevant to GPUs: the entry point for a GPU kernel
|
||||
|
|
@ -57,6 +60,7 @@ impl fmt::Display for CanonAbi {
|
|||
CanonAbi::C => ExternAbi::C { unwind: false },
|
||||
CanonAbi::Rust => ExternAbi::Rust,
|
||||
CanonAbi::RustCold => ExternAbi::RustCold,
|
||||
CanonAbi::Custom => ExternAbi::Custom,
|
||||
CanonAbi::Arm(arm_call) => match arm_call {
|
||||
ArmCall::Aapcs => ExternAbi::Aapcs { unwind: false },
|
||||
ArmCall::CCmseNonSecureCall => ExternAbi::CCmseNonSecureCall,
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@ pub enum ExternAbi {
|
|||
/// Even normally-compatible Rust types can become ABI-incompatible with this ABI!
|
||||
Unadjusted,
|
||||
|
||||
/// An ABI that rustc does not know how to call or define. Functions with this ABI can
|
||||
/// only be created using `#[naked]` functions or `extern "custom"` blocks, and can only
|
||||
/// be called from inline assembly.
|
||||
Custom,
|
||||
|
||||
/// UEFI ABI, usually an alias of C, but sometimes an arch-specific alias
|
||||
/// and only valid on platforms that have a UEFI standard
|
||||
EfiApi,
|
||||
|
|
@ -141,6 +146,7 @@ abi_impls! {
|
|||
AvrNonBlockingInterrupt =><= "avr-non-blocking-interrupt",
|
||||
Cdecl { unwind: false } =><= "cdecl",
|
||||
Cdecl { unwind: true } =><= "cdecl-unwind",
|
||||
Custom =><= "custom",
|
||||
EfiApi =><= "efiapi",
|
||||
Fastcall { unwind: false } =><= "fastcall",
|
||||
Fastcall { unwind: true } =><= "fastcall-unwind",
|
||||
|
|
|
|||
|
|
@ -3542,6 +3542,38 @@ impl FnHeader {
|
|||
|| matches!(constness, Const::Yes(_))
|
||||
|| !matches!(ext, Extern::None)
|
||||
}
|
||||
|
||||
/// Return a span encompassing the header, or none if all options are default.
|
||||
pub fn span(&self) -> Option<Span> {
|
||||
fn append(a: &mut Option<Span>, b: Span) {
|
||||
*a = match a {
|
||||
None => Some(b),
|
||||
Some(x) => Some(x.to(b)),
|
||||
}
|
||||
}
|
||||
|
||||
let mut full_span = None;
|
||||
|
||||
match self.safety {
|
||||
Safety::Unsafe(span) | Safety::Safe(span) => append(&mut full_span, span),
|
||||
Safety::Default => {}
|
||||
};
|
||||
|
||||
if let Some(coroutine_kind) = self.coroutine_kind {
|
||||
append(&mut full_span, coroutine_kind.span());
|
||||
}
|
||||
|
||||
if let Const::Yes(span) = self.constness {
|
||||
append(&mut full_span, span);
|
||||
}
|
||||
|
||||
match self.ext {
|
||||
Extern::Implicit(span) | Extern::Explicit(_, span) => append(&mut full_span, span),
|
||||
Extern::None => {}
|
||||
}
|
||||
|
||||
full_span
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for FnHeader {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
|
||||
for (def_id, info) in lctx.children {
|
||||
let owner = self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom);
|
||||
debug_assert!(
|
||||
assert!(
|
||||
matches!(owner, hir::MaybeOwner::Phantom),
|
||||
"duplicate copy of {def_id:?} in lctx.children"
|
||||
);
|
||||
|
|
@ -78,7 +78,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
|
|||
match node {
|
||||
AstOwner::NonOwner => {}
|
||||
AstOwner::Crate(c) => {
|
||||
debug_assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
|
||||
assert_eq!(self.resolver.node_id_to_def_id[&CRATE_NODE_ID], CRATE_DEF_ID);
|
||||
self.with_lctx(CRATE_NODE_ID, |lctx| {
|
||||
let module = lctx.lower_mod(&c.items, &c.spans);
|
||||
// FIXME(jdonszelman): is dummy span ever a problem here?
|
||||
|
|
@ -1160,7 +1160,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
) -> hir::BodyId {
|
||||
let body = hir::Body { params, value: self.arena.alloc(value) };
|
||||
let id = body.id();
|
||||
debug_assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
|
||||
assert_eq!(id.hir_id.owner, self.current_hir_id_owner);
|
||||
self.bodies.push((id.hir_id.local_id, self.arena.alloc(body)));
|
||||
id
|
||||
}
|
||||
|
|
@ -1673,8 +1673,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
itctx: ImplTraitContext,
|
||||
f: impl FnOnce(&mut Self) -> T,
|
||||
) -> (&'hir hir::Generics<'hir>, T) {
|
||||
debug_assert!(self.impl_trait_defs.is_empty());
|
||||
debug_assert!(self.impl_trait_bounds.is_empty());
|
||||
assert!(self.impl_trait_defs.is_empty());
|
||||
assert!(self.impl_trait_bounds.is_empty());
|
||||
|
||||
// Error if `?Trait` bounds in where clauses don't refer directly to type parameters.
|
||||
// Note: we used to clone these bounds directly onto the type parameter (and avoid lowering
|
||||
|
|
|
|||
|
|
@ -523,7 +523,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
span: Span,
|
||||
) -> LocalDefId {
|
||||
let parent = self.current_hir_id_owner.def_id;
|
||||
debug_assert_ne!(node_id, ast::DUMMY_NODE_ID);
|
||||
assert_ne!(node_id, ast::DUMMY_NODE_ID);
|
||||
assert!(
|
||||
self.opt_local_def_id(node_id).is_none(),
|
||||
"adding a def'n for node-id {:?} and def kind {:?} but a previous def'n exists: {:?}",
|
||||
|
|
@ -607,10 +607,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
|
||||
let item = f(self);
|
||||
debug_assert_eq!(owner_id, item.def_id());
|
||||
assert_eq!(owner_id, item.def_id());
|
||||
// `f` should have consumed all the elements in these vectors when constructing `item`.
|
||||
debug_assert!(self.impl_trait_defs.is_empty());
|
||||
debug_assert!(self.impl_trait_bounds.is_empty());
|
||||
assert!(self.impl_trait_defs.is_empty());
|
||||
assert!(self.impl_trait_bounds.is_empty());
|
||||
let info = self.make_owner_info(item);
|
||||
|
||||
self.attrs = current_attrs;
|
||||
|
|
@ -918,7 +918,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
} else {
|
||||
let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span), id);
|
||||
|
||||
debug_assert_eq!(id.owner, self.current_hir_id_owner);
|
||||
assert_eq!(id.owner, self.current_hir_id_owner);
|
||||
let ret = self.arena.alloc_from_iter(lowered_attrs);
|
||||
|
||||
// this is possible if an item contained syntactical attribute,
|
||||
|
|
@ -956,10 +956,10 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
}
|
||||
|
||||
fn alias_attrs(&mut self, id: HirId, target_id: HirId) {
|
||||
debug_assert_eq!(id.owner, self.current_hir_id_owner);
|
||||
debug_assert_eq!(target_id.owner, self.current_hir_id_owner);
|
||||
assert_eq!(id.owner, self.current_hir_id_owner);
|
||||
assert_eq!(target_id.owner, self.current_hir_id_owner);
|
||||
if let Some(&a) = self.attrs.get(&target_id.local_id) {
|
||||
debug_assert!(!a.is_empty());
|
||||
assert!(!a.is_empty());
|
||||
self.attrs.insert(id.local_id, a);
|
||||
}
|
||||
}
|
||||
|
|
@ -1438,7 +1438,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let id = if let Some(LifetimeRes::ElidedAnchor { start, end }) =
|
||||
self.resolver.get_lifetime_res(t.id)
|
||||
{
|
||||
debug_assert_eq!(start.plus(1), end);
|
||||
assert_eq!(start.plus(1), end);
|
||||
start
|
||||
} else {
|
||||
self.next_node_id()
|
||||
|
|
@ -1846,16 +1846,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
let res = match res {
|
||||
LifetimeRes::Param { param, .. } => hir::LifetimeKind::Param(param),
|
||||
LifetimeRes::Fresh { param, .. } => {
|
||||
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
|
||||
assert_eq!(ident.name, kw::UnderscoreLifetime);
|
||||
let param = self.local_def_id(param);
|
||||
hir::LifetimeKind::Param(param)
|
||||
}
|
||||
LifetimeRes::Infer => {
|
||||
debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
|
||||
assert_eq!(ident.name, kw::UnderscoreLifetime);
|
||||
hir::LifetimeKind::Infer
|
||||
}
|
||||
LifetimeRes::Static { .. } => {
|
||||
debug_assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime));
|
||||
assert!(matches!(ident.name, kw::StaticLifetime | kw::UnderscoreLifetime));
|
||||
hir::LifetimeKind::Static
|
||||
}
|
||||
LifetimeRes::Error => hir::LifetimeKind::Error,
|
||||
|
|
@ -2285,7 +2285,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
) -> hir::Stmt<'hir> {
|
||||
let hir_id = self.next_id();
|
||||
if let Some(a) = attrs {
|
||||
debug_assert!(!a.is_empty());
|
||||
assert!(!a.is_empty());
|
||||
self.attrs.insert(hir_id.local_id, a);
|
||||
}
|
||||
let local = hir::LetStmt {
|
||||
|
|
|
|||
|
|
@ -134,5 +134,8 @@ pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
|
|||
feature: sym::cmse_nonsecure_entry,
|
||||
explain: GateReason::Experimental,
|
||||
}),
|
||||
ExternAbi::Custom => {
|
||||
Err(UnstableAbi { abi, feature: sym::abi_custom, explain: GateReason::Experimental })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,20 @@
|
|||
ast_passes_abi_custom_coroutine =
|
||||
functions with the `"custom"` ABI cannot be `{$coroutine_kind_str}`
|
||||
.suggestion = remove the `{$coroutine_kind_str}` keyword from this definiton
|
||||
|
||||
ast_passes_abi_custom_invalid_signature =
|
||||
invalid signature for `extern "custom"` function
|
||||
.note = functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
.suggestion = remove the parameters and return type
|
||||
|
||||
ast_passes_abi_custom_safe_foreign_function =
|
||||
foreign functions with the `"custom"` ABI cannot be safe
|
||||
.suggestion = remove the `safe` keyword from this definition
|
||||
|
||||
ast_passes_abi_custom_safe_function =
|
||||
functions with the `"custom"` ABI must be unsafe
|
||||
.suggestion = add the `unsafe` keyword to this definition
|
||||
|
||||
ast_passes_assoc_const_without_body =
|
||||
associated constant in `impl` without body
|
||||
.suggestion = provide a definition for the constant
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
use std::mem;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::str::FromStr;
|
||||
|
||||
use itertools::{Either, Itertools};
|
||||
use rustc_abi::ExternAbi;
|
||||
|
|
@ -81,6 +82,7 @@ struct AstValidator<'a> {
|
|||
|
||||
/// Used to ban explicit safety on foreign items when the extern block is not marked as unsafe.
|
||||
extern_mod_safety: Option<Safety>,
|
||||
extern_mod_abi: Option<ExternAbi>,
|
||||
|
||||
lint_node_id: NodeId,
|
||||
|
||||
|
|
@ -121,10 +123,17 @@ impl<'a> AstValidator<'a> {
|
|||
self.outer_trait_or_trait_impl = old;
|
||||
}
|
||||
|
||||
fn with_in_extern_mod(&mut self, extern_mod_safety: Safety, f: impl FnOnce(&mut Self)) {
|
||||
let old = mem::replace(&mut self.extern_mod_safety, Some(extern_mod_safety));
|
||||
fn with_in_extern_mod(
|
||||
&mut self,
|
||||
extern_mod_safety: Safety,
|
||||
abi: Option<ExternAbi>,
|
||||
f: impl FnOnce(&mut Self),
|
||||
) {
|
||||
let old_safety = mem::replace(&mut self.extern_mod_safety, Some(extern_mod_safety));
|
||||
let old_abi = mem::replace(&mut self.extern_mod_abi, abi);
|
||||
f(self);
|
||||
self.extern_mod_safety = old;
|
||||
self.extern_mod_safety = old_safety;
|
||||
self.extern_mod_abi = old_abi;
|
||||
}
|
||||
|
||||
fn with_tilde_const(
|
||||
|
|
@ -370,6 +379,65 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// An `extern "custom"` function must be unsafe, and must not have any parameters or return
|
||||
/// type.
|
||||
fn check_custom_abi(&self, ctxt: FnCtxt, ident: &Ident, sig: &FnSig) {
|
||||
let dcx = self.dcx();
|
||||
|
||||
// An `extern "custom"` function must be unsafe.
|
||||
match sig.header.safety {
|
||||
Safety::Unsafe(_) => { /* all good */ }
|
||||
Safety::Safe(safe_span) => {
|
||||
let safe_span =
|
||||
self.sess.psess.source_map().span_until_non_whitespace(safe_span.to(sig.span));
|
||||
dcx.emit_err(errors::AbiCustomSafeForeignFunction { span: sig.span, safe_span });
|
||||
}
|
||||
Safety::Default => match ctxt {
|
||||
FnCtxt::Foreign => { /* all good */ }
|
||||
FnCtxt::Free | FnCtxt::Assoc(_) => {
|
||||
self.dcx().emit_err(errors::AbiCustomSafeFunction {
|
||||
span: sig.span,
|
||||
unsafe_span: sig.span.shrink_to_lo(),
|
||||
});
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// An `extern "custom"` function cannot be `async` and/or `gen`.
|
||||
if let Some(coroutine_kind) = sig.header.coroutine_kind {
|
||||
let coroutine_kind_span = self
|
||||
.sess
|
||||
.psess
|
||||
.source_map()
|
||||
.span_until_non_whitespace(coroutine_kind.span().to(sig.span));
|
||||
|
||||
self.dcx().emit_err(errors::AbiCustomCoroutine {
|
||||
span: sig.span,
|
||||
coroutine_kind_span,
|
||||
coroutine_kind_str: coroutine_kind.as_str(),
|
||||
});
|
||||
}
|
||||
|
||||
// An `extern "custom"` function must not have any parameters or return type.
|
||||
let mut spans: Vec<_> = sig.decl.inputs.iter().map(|p| p.span).collect();
|
||||
if let FnRetTy::Ty(ref ret_ty) = sig.decl.output {
|
||||
spans.push(ret_ty.span);
|
||||
}
|
||||
|
||||
if !spans.is_empty() {
|
||||
let header_span = sig.header.span().unwrap_or(sig.span.shrink_to_lo());
|
||||
let suggestion_span = header_span.shrink_to_hi().to(sig.decl.output.span());
|
||||
let padding = if header_span.is_empty() { "" } else { " " };
|
||||
|
||||
self.dcx().emit_err(errors::AbiCustomInvalidSignature {
|
||||
spans,
|
||||
symbol: ident.name,
|
||||
suggestion_span,
|
||||
padding,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// This ensures that items can only be `unsafe` (or unmarked) outside of extern
|
||||
/// blocks.
|
||||
///
|
||||
|
|
@ -1005,7 +1073,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
if abi.is_none() {
|
||||
self.handle_missing_abi(*extern_span, item.id);
|
||||
}
|
||||
self.with_in_extern_mod(*safety, |this| {
|
||||
|
||||
let extern_abi = abi.and_then(|abi| ExternAbi::from_str(abi.symbol.as_str()).ok());
|
||||
self.with_in_extern_mod(*safety, extern_abi, |this| {
|
||||
visit::walk_item(this, item);
|
||||
});
|
||||
self.extern_mod_span = old_item;
|
||||
|
|
@ -1145,6 +1215,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.check_foreign_fn_bodyless(*ident, body.as_deref());
|
||||
self.check_foreign_fn_headerless(sig.header);
|
||||
self.check_foreign_item_ascii_only(*ident);
|
||||
if self.extern_mod_abi == Some(ExternAbi::Custom) {
|
||||
self.check_custom_abi(FnCtxt::Foreign, ident, sig);
|
||||
}
|
||||
}
|
||||
ForeignItemKind::TyAlias(box TyAlias {
|
||||
defaultness,
|
||||
|
|
@ -1352,6 +1425,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.check_item_safety(span, safety);
|
||||
}
|
||||
|
||||
if let FnKind::Fn(ctxt, _, fun) = fk
|
||||
&& let Extern::Explicit(str_lit, _) = fun.sig.header.ext
|
||||
&& let Ok(ExternAbi::Custom) = ExternAbi::from_str(str_lit.symbol.as_str())
|
||||
{
|
||||
self.check_custom_abi(ctxt, &fun.ident, &fun.sig);
|
||||
}
|
||||
|
||||
self.check_c_variadic_type(fk);
|
||||
|
||||
// Functions cannot both be `const async` or `const gen`
|
||||
|
|
@ -1703,6 +1783,7 @@ pub fn check_crate(
|
|||
outer_impl_trait_span: None,
|
||||
disallow_tilde_const: Some(TildeConstReason::Item),
|
||||
extern_mod_safety: None,
|
||||
extern_mod_abi: None,
|
||||
lint_node_id: CRATE_NODE_ID,
|
||||
is_sdylib_interface,
|
||||
lint_buffer: lints,
|
||||
|
|
|
|||
|
|
@ -824,3 +824,67 @@ pub(crate) struct MissingAbi {
|
|||
#[suggestion(code = "extern \"<abi>\"", applicability = "has-placeholders")]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_abi_custom_safe_foreign_function)]
|
||||
pub(crate) struct AbiCustomSafeForeignFunction {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
#[suggestion(
|
||||
ast_passes_suggestion,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub safe_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_abi_custom_safe_function)]
|
||||
pub(crate) struct AbiCustomSafeFunction {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
#[suggestion(
|
||||
ast_passes_suggestion,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "unsafe ",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub unsafe_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_abi_custom_coroutine)]
|
||||
pub(crate) struct AbiCustomCoroutine {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
|
||||
#[suggestion(
|
||||
ast_passes_suggestion,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub coroutine_kind_span: Span,
|
||||
pub coroutine_kind_str: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(ast_passes_abi_custom_invalid_signature)]
|
||||
#[note]
|
||||
pub(crate) struct AbiCustomInvalidSignature {
|
||||
#[primary_span]
|
||||
pub spans: Vec<Span>,
|
||||
|
||||
#[suggestion(
|
||||
ast_passes_suggestion,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "{padding}fn {symbol}()",
|
||||
style = "verbose"
|
||||
)]
|
||||
pub suggestion_span: Span,
|
||||
pub symbol: Symbol,
|
||||
pub padding: &'static str,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,11 @@ pub(crate) fn conv_to_call_conv(
|
|||
CanonAbi::Rust | CanonAbi::C => default_call_conv,
|
||||
CanonAbi::RustCold => CallConv::Cold,
|
||||
|
||||
// Functions with this calling convention can only be called from assembly, but it is
|
||||
// possible to declare an `extern "custom"` block, so the backend still needs a calling
|
||||
// convention for declaring foreign functions.
|
||||
CanonAbi::Custom => default_call_conv,
|
||||
|
||||
CanonAbi::X86(x86_call) => match x86_call {
|
||||
X86Call::SysV64 => CallConv::SystemV,
|
||||
X86Call::Win64 => CallConv::WindowsFastcall,
|
||||
|
|
|
|||
|
|
@ -2,9 +2,6 @@ codegen_gcc_unknown_ctarget_feature_prefix =
|
|||
unknown feature specified for `-Ctarget-feature`: `{$feature}`
|
||||
.note = features must begin with a `+` to enable or `-` to disable it
|
||||
|
||||
codegen_gcc_forbidden_ctarget_feature =
|
||||
target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason}
|
||||
|
||||
codegen_gcc_unwinding_inline_asm =
|
||||
GCC backend does not support unwinding from inline asm
|
||||
|
||||
|
|
@ -26,10 +23,6 @@ codegen_gcc_unknown_ctarget_feature =
|
|||
.possible_feature = you might have meant: `{$rust_feature}`
|
||||
.consider_filing_feature_request = consider filing a feature request
|
||||
|
||||
codegen_gcc_unstable_ctarget_feature =
|
||||
unstable feature specified for `-Ctarget-feature`: `{$feature}`
|
||||
.note = this feature is not stably supported; its behavior can change in the future
|
||||
|
||||
codegen_gcc_missing_features =
|
||||
add the missing features in a `target_feature` attribute
|
||||
|
||||
|
|
|
|||
|
|
@ -239,12 +239,16 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||
pub fn conv_to_fn_attribute<'gcc>(conv: CanonAbi, arch: &str) -> Option<FnAttribute<'gcc>> {
|
||||
let attribute = match conv {
|
||||
CanonAbi::C | CanonAbi::Rust => return None,
|
||||
CanonAbi::RustCold => FnAttribute::Cold,
|
||||
// Functions with this calling convention can only be called from assembly, but it is
|
||||
// possible to declare an `extern "custom"` block, so the backend still needs a calling
|
||||
// convention for declaring foreign functions.
|
||||
CanonAbi::Custom => return None,
|
||||
CanonAbi::Arm(arm_call) => match arm_call {
|
||||
ArmCall::CCmseNonSecureCall => FnAttribute::ArmCmseNonsecureCall,
|
||||
ArmCall::CCmseNonSecureEntry => FnAttribute::ArmCmseNonsecureEntry,
|
||||
ArmCall::Aapcs => FnAttribute::ArmPcs("aapcs"),
|
||||
},
|
||||
CanonAbi::RustCold => FnAttribute::Cold,
|
||||
CanonAbi::GpuKernel => {
|
||||
if arch == "amdgpu" {
|
||||
FnAttribute::GcnAmdGpuHsaKernel
|
||||
|
|
|
|||
|
|
@ -17,21 +17,6 @@ pub(crate) struct UnknownCTargetFeature<'a> {
|
|||
pub rust_feature: PossibleFeature<'a>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_unstable_ctarget_feature)]
|
||||
#[note]
|
||||
pub(crate) struct UnstableCTargetFeature<'a> {
|
||||
pub feature: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_gcc_forbidden_ctarget_feature)]
|
||||
pub(crate) struct ForbiddenCTargetFeature<'a> {
|
||||
pub feature: &'a str,
|
||||
pub enabled: &'a str,
|
||||
pub reason: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum PossibleFeature<'a> {
|
||||
#[help(codegen_gcc_possible_feature)]
|
||||
|
|
|
|||
|
|
@ -5,13 +5,17 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable;
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::features::{StabilityExt, retpoline_features_by_flags};
|
||||
use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
|
||||
use crate::errors::{
|
||||
ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix,
|
||||
UnstableCTargetFeature,
|
||||
};
|
||||
use crate::errors::{PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix};
|
||||
|
||||
fn gcc_features_by_flags(sess: &Session) -> Vec<&str> {
|
||||
let mut features: Vec<&str> = Vec::new();
|
||||
retpoline_features_by_flags(sess, &mut features);
|
||||
features
|
||||
}
|
||||
|
||||
/// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
|
||||
/// `--target` and similar).
|
||||
|
|
@ -45,7 +49,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
|||
|
||||
// Compute implied features
|
||||
let mut all_rust_features = vec![];
|
||||
for feature in sess.opts.cg.target_feature.split(',') {
|
||||
for feature in sess.opts.cg.target_feature.split(',').chain(gcc_features_by_flags(sess)) {
|
||||
if let Some(feature) = feature.strip_prefix('+') {
|
||||
all_rust_features.extend(
|
||||
UnordSet::from(sess.target.implied_target_features(feature))
|
||||
|
|
@ -94,18 +98,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
|
|||
sess.dcx().emit_warn(unknown_feature);
|
||||
}
|
||||
Some(&(_, stability, _)) => {
|
||||
if let Err(reason) = stability.toggle_allowed() {
|
||||
sess.dcx().emit_warn(ForbiddenCTargetFeature {
|
||||
feature,
|
||||
enabled: if enable { "enabled" } else { "disabled" },
|
||||
reason,
|
||||
});
|
||||
} else if stability.requires_nightly().is_some() {
|
||||
// An unstable feature. Warn about using it. (It makes little sense
|
||||
// to hard-error here since we just warn about fully unknown
|
||||
// features above).
|
||||
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
|
||||
}
|
||||
stability.verify_feature_enabled_by_flag(sess, enable, feature);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,11 +10,6 @@ codegen_llvm_dynamic_linking_with_lto =
|
|||
|
||||
codegen_llvm_fixed_x18_invalid_arch = the `-Zfixed-x18` flag is not supported on the `{$arch}` architecture
|
||||
|
||||
codegen_llvm_forbidden_ctarget_feature =
|
||||
target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason}
|
||||
.note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
codegen_llvm_forbidden_ctarget_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
|
||||
|
||||
codegen_llvm_from_llvm_diag = {$message}
|
||||
|
||||
codegen_llvm_from_llvm_optimization_diag = {$filename}:{$line}:{$column} {$pass_name} ({$kind}): {$message}
|
||||
|
|
@ -76,10 +71,6 @@ codegen_llvm_unknown_ctarget_feature_prefix =
|
|||
|
||||
codegen_llvm_unknown_debuginfo_compression = unknown debuginfo compression algorithm {$algorithm} - will fall back to uncompressed debuginfo
|
||||
|
||||
codegen_llvm_unstable_ctarget_feature =
|
||||
unstable feature specified for `-Ctarget-feature`: `{$feature}`
|
||||
.note = this feature is not stably supported; its behavior can change in the future
|
||||
|
||||
codegen_llvm_write_bytecode = failed to write bytecode to {$path}: {$err}
|
||||
|
||||
codegen_llvm_write_ir = failed to write LLVM IR to {$path}
|
||||
|
|
|
|||
|
|
@ -649,6 +649,10 @@ impl llvm::CallConv {
|
|||
match conv {
|
||||
CanonAbi::C | CanonAbi::Rust => llvm::CCallConv,
|
||||
CanonAbi::RustCold => llvm::PreserveMost,
|
||||
// Functions with this calling convention can only be called from assembly, but it is
|
||||
// possible to declare an `extern "custom"` block, so the backend still needs a calling
|
||||
// convention for declaring foreign functions.
|
||||
CanonAbi::Custom => llvm::CCallConv,
|
||||
CanonAbi::GpuKernel => {
|
||||
if arch == "amdgpu" {
|
||||
llvm::AmdgpuKernel
|
||||
|
|
|
|||
|
|
@ -24,23 +24,6 @@ pub(crate) struct UnknownCTargetFeature<'a> {
|
|||
pub rust_feature: PossibleFeature<'a>,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_unstable_ctarget_feature)]
|
||||
#[note]
|
||||
pub(crate) struct UnstableCTargetFeature<'a> {
|
||||
pub feature: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(codegen_llvm_forbidden_ctarget_feature)]
|
||||
#[note]
|
||||
#[note(codegen_llvm_forbidden_ctarget_feature_issue)]
|
||||
pub(crate) struct ForbiddenCTargetFeature<'a> {
|
||||
pub feature: &'a str,
|
||||
pub enabled: &'a str,
|
||||
pub reason: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum PossibleFeature<'a> {
|
||||
#[help(codegen_llvm_possible_feature)]
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ use rustc_fs_util::path_to_c_string;
|
|||
use rustc_middle::bug;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::config::{PrintKind, PrintRequest};
|
||||
use rustc_session::features::{StabilityExt, retpoline_features_by_flags};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
|
||||
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
|
||||
|
|
@ -23,8 +24,7 @@ use smallvec::{SmallVec, smallvec};
|
|||
|
||||
use crate::back::write::create_informational_target_machine;
|
||||
use crate::errors::{
|
||||
FixedX18InvalidArch, ForbiddenCTargetFeature, PossibleFeature, UnknownCTargetFeature,
|
||||
UnknownCTargetFeaturePrefix, UnstableCTargetFeature,
|
||||
FixedX18InvalidArch, PossibleFeature, UnknownCTargetFeature, UnknownCTargetFeaturePrefix,
|
||||
};
|
||||
use crate::llvm;
|
||||
|
||||
|
|
@ -707,6 +707,12 @@ pub(crate) fn target_cpu(sess: &Session) -> &str {
|
|||
handle_native(cpu_name)
|
||||
}
|
||||
|
||||
fn llvm_features_by_flags(sess: &Session) -> Vec<&str> {
|
||||
let mut features: Vec<&str> = Vec::new();
|
||||
retpoline_features_by_flags(sess, &mut features);
|
||||
features
|
||||
}
|
||||
|
||||
/// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
|
||||
/// `--target` and similar).
|
||||
pub(crate) fn global_llvm_features(
|
||||
|
|
@ -787,7 +793,7 @@ pub(crate) fn global_llvm_features(
|
|||
|
||||
// Compute implied features
|
||||
let mut all_rust_features = vec![];
|
||||
for feature in sess.opts.cg.target_feature.split(',') {
|
||||
for feature in sess.opts.cg.target_feature.split(',').chain(llvm_features_by_flags(sess)) {
|
||||
if let Some(feature) = feature.strip_prefix('+') {
|
||||
all_rust_features.extend(
|
||||
UnordSet::from(sess.target.implied_target_features(feature))
|
||||
|
|
@ -840,18 +846,7 @@ pub(crate) fn global_llvm_features(
|
|||
sess.dcx().emit_warn(unknown_feature);
|
||||
}
|
||||
Some((_, stability, _)) => {
|
||||
if let Err(reason) = stability.toggle_allowed() {
|
||||
sess.dcx().emit_warn(ForbiddenCTargetFeature {
|
||||
feature,
|
||||
enabled: if enable { "enabled" } else { "disabled" },
|
||||
reason,
|
||||
});
|
||||
} else if stability.requires_nightly().is_some() {
|
||||
// An unstable feature. Warn about using it. It makes little sense
|
||||
// to hard-error here since we just warn about fully unknown
|
||||
// features above.
|
||||
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
|
||||
}
|
||||
stability.verify_feature_enabled_by_flag(sess, enable, feature);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
|
|||
use rustc_middle::middle::codegen_fn_attrs::TargetFeature;
|
||||
use rustc_middle::query::Providers;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::features::StabilityExt;
|
||||
use rustc_session::lint::builtin::AARCH64_SOFTFLOAT_NEON;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_span::{Span, Symbol, sym};
|
||||
|
|
@ -66,7 +67,7 @@ pub(crate) fn from_target_feature_attr(
|
|||
|
||||
// Only allow target features whose feature gates have been enabled
|
||||
// and which are permitted to be toggled.
|
||||
if let Err(reason) = stability.toggle_allowed() {
|
||||
if let Err(reason) = stability.is_toggle_permitted(tcx.sess) {
|
||||
tcx.dcx().emit_err(errors::ForbiddenTargetFeatureAttr {
|
||||
span: item.span(),
|
||||
feature,
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ expand_meta_var_expr_unrecognized_var =
|
|||
variable `{$key}` is not recognized in meta-variable expression
|
||||
|
||||
expand_missing_fragment_specifier = missing fragment specifier
|
||||
.note = fragment specifiers must be specified in the 2024 edition
|
||||
.note = fragment specifiers must be provided
|
||||
.suggestion_add_fragspec = try adding a specifier here
|
||||
.valid = {$valid}
|
||||
|
||||
|
|
|
|||
|
|
@ -112,9 +112,8 @@ use rustc_ast::{DUMMY_NODE_ID, NodeId};
|
|||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_errors::MultiSpan;
|
||||
use rustc_lint_defs::BuiltinLintDiag;
|
||||
use rustc_session::lint::builtin::{META_VARIABLE_MISUSE, MISSING_FRAGMENT_SPECIFIER};
|
||||
use rustc_session::lint::builtin::META_VARIABLE_MISUSE;
|
||||
use rustc_session::parse::ParseSess;
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_span::{ErrorGuaranteed, MacroRulesNormalizedIdent, Span, kw};
|
||||
use smallvec::SmallVec;
|
||||
|
||||
|
|
@ -266,23 +265,11 @@ fn check_binders(
|
|||
// Similarly, this can only happen when checking a toplevel macro.
|
||||
TokenTree::MetaVarDecl(span, name, kind) => {
|
||||
if kind.is_none() && node_id != DUMMY_NODE_ID {
|
||||
// FIXME: Report this as a hard error eventually and remove equivalent errors from
|
||||
// `parse_tt_inner` and `nameize`. Until then the error may be reported twice, once
|
||||
// as a hard error and then once as a buffered lint.
|
||||
if span.edition() >= Edition::Edition2024 {
|
||||
psess.dcx().emit_err(errors::MissingFragmentSpecifier {
|
||||
span,
|
||||
add_span: span.shrink_to_hi(),
|
||||
valid: VALID_FRAGMENT_NAMES_MSG,
|
||||
});
|
||||
} else {
|
||||
psess.buffer_lint(
|
||||
MISSING_FRAGMENT_SPECIFIER,
|
||||
span,
|
||||
node_id,
|
||||
BuiltinLintDiag::MissingFragmentSpecifier,
|
||||
);
|
||||
}
|
||||
psess.dcx().emit_err(errors::MissingFragmentSpecifier {
|
||||
span,
|
||||
add_span: span.shrink_to_hi(),
|
||||
valid: VALID_FRAGMENT_NAMES_MSG,
|
||||
});
|
||||
}
|
||||
if !macros.is_empty() {
|
||||
psess.dcx().span_bug(span, "unexpected MetaVarDecl in nested lhs");
|
||||
|
|
|
|||
|
|
@ -353,6 +353,8 @@ declare_features! (
|
|||
(unstable, abi_avr_interrupt, "1.45.0", Some(69664)),
|
||||
/// Allows `extern "C-cmse-nonsecure-call" fn()`.
|
||||
(unstable, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391)),
|
||||
/// Allows `extern "custom" fn()`.
|
||||
(unstable, abi_custom, "CURRENT_RUSTC_VERSION", Some(140829)),
|
||||
/// Allows `extern "gpu-kernel" fn()`.
|
||||
(unstable, abi_gpu_kernel, "1.86.0", Some(135467)),
|
||||
/// Allows `extern "msp430-interrupt" fn()`.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
hir_analysis_abi_custom_clothed_function =
|
||||
items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
.suggestion = convert this to an `#[unsafe(naked)]` function
|
||||
|
||||
hir_analysis_ambiguous_assoc_item = ambiguous associated {$assoc_kind} `{$assoc_ident}` in bounds of `{$qself}`
|
||||
.label = ambiguous associated {$assoc_kind} `{$assoc_ident}`
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ use rustc_middle::ty::error::TypeErrorToStringExt;
|
|||
use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
|
||||
use rustc_middle::ty::util::Discr;
|
||||
use rustc_middle::ty::{
|
||||
AdtDef, BottomUpFolder, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable,
|
||||
AdtDef, BottomUpFolder, FnSig, GenericArgKind, RegionKind, TypeFoldable, TypeSuperVisitable,
|
||||
TypeVisitable, TypeVisitableExt, fold_regions,
|
||||
};
|
||||
use rustc_session::lint::builtin::UNINHABITED_STATIC;
|
||||
|
|
@ -100,6 +100,18 @@ pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ex
|
|||
}
|
||||
}
|
||||
|
||||
pub fn check_custom_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, fn_sig: FnSig<'_>, fn_sig_span: Span) {
|
||||
if fn_sig.abi == ExternAbi::Custom {
|
||||
// Function definitions that use `extern "custom"` must be naked functions.
|
||||
if !tcx.has_attr(def_id, sym::naked) {
|
||||
tcx.dcx().emit_err(crate::errors::AbiCustomClothedFunction {
|
||||
span: fn_sig_span,
|
||||
naked_span: tcx.def_span(def_id).shrink_to_lo(),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_struct(tcx: TyCtxt<'_>, def_id: LocalDefId) {
|
||||
let def = tcx.adt_def(def_id);
|
||||
let span = tcx.def_span(def_id);
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ pub mod wfcheck;
|
|||
|
||||
use std::num::NonZero;
|
||||
|
||||
pub use check::{check_abi, check_abi_fn_ptr};
|
||||
pub use check::{check_abi, check_abi_fn_ptr, check_custom_abi};
|
||||
use rustc_abi::{ExternAbi, VariantIdx};
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err};
|
||||
|
|
|
|||
|
|
@ -1698,3 +1698,17 @@ pub(crate) struct SelfInTypeAlias {
|
|||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_analysis_abi_custom_clothed_function)]
|
||||
pub(crate) struct AbiCustomClothedFunction {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[suggestion(
|
||||
hir_analysis_suggestion,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "#[unsafe(naked)]\n",
|
||||
style = "short"
|
||||
)]
|
||||
pub naked_span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,7 @@
|
|||
hir_typeck_abi_custom_call =
|
||||
functions with the `"custom"` ABI cannot be called
|
||||
.note = an `extern "custom"` function can only be called from within inline assembly
|
||||
|
||||
hir_typeck_add_missing_parentheses_in_range = you must surround the range in parentheses to call its `{$func_name}` function
|
||||
|
||||
hir_typeck_add_return_type_add = try adding a return type
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use std::iter;
|
||||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::util::parser::ExprPrecedence;
|
||||
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey};
|
||||
use rustc_hir::def::{self, CtorKind, Namespace, Res};
|
||||
|
|
@ -83,6 +84,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
while result.is_none() && autoderef.next().is_some() {
|
||||
result = self.try_overloaded_call_step(call_expr, callee_expr, arg_exprs, &autoderef);
|
||||
}
|
||||
self.check_call_custom_abi(autoderef.final_ty(false), call_expr.span);
|
||||
self.register_predicates(autoderef.into_obligations());
|
||||
|
||||
let output = match result {
|
||||
|
|
@ -135,6 +137,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
output
|
||||
}
|
||||
|
||||
/// Functions of type `extern "custom" fn(/* ... */)` cannot be called using `ExprKind::Call`.
|
||||
///
|
||||
/// These functions have a calling convention that is unknown to rust, hence it cannot generate
|
||||
/// code for the call. The only way to execute such a function is via inline assembly.
|
||||
fn check_call_custom_abi(&self, callee_ty: Ty<'tcx>, span: Span) {
|
||||
let abi = match callee_ty.kind() {
|
||||
ty::FnDef(def_id, _) => self.tcx.fn_sig(def_id).skip_binder().skip_binder().abi,
|
||||
ty::FnPtr(_, header) => header.abi,
|
||||
_ => return,
|
||||
};
|
||||
|
||||
if let ExternAbi::Custom = abi {
|
||||
self.tcx.dcx().emit_err(errors::AbiCustomCall { span });
|
||||
}
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(self, call_expr, callee_expr, arg_exprs, autoderef), ret)]
|
||||
fn try_overloaded_call_step(
|
||||
&self,
|
||||
|
|
|
|||
|
|
@ -1163,3 +1163,10 @@ pub(crate) struct NakedFunctionsMustNakedAsm {
|
|||
#[label]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(hir_typeck_abi_custom_call)]
|
||||
pub(crate) struct AbiCustomCall {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
//!
|
||||
//! See [`rustc_hir_analysis::check`] for more context on type checking in general.
|
||||
|
||||
use rustc_abi::{FIRST_VARIANT, FieldIdx};
|
||||
use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||
use rustc_data_structures::unord::UnordMap;
|
||||
|
|
@ -1627,6 +1627,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
Some(method.def_id),
|
||||
);
|
||||
|
||||
// Functions of type `extern "custom" fn(/* ... */)` cannot be called using
|
||||
// `ExprKind::MethodCall`. These functions have a calling convention that is
|
||||
// unknown to rust, hence it cannot generate code for the call. The only way
|
||||
// to execute such a function is via inline assembly.
|
||||
if let ExternAbi::Custom = method.sig.abi {
|
||||
self.tcx.dcx().emit_err(crate::errors::AbiCustomCall { span: expr.span });
|
||||
}
|
||||
|
||||
method.sig.output()
|
||||
}
|
||||
Err(error) => {
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_e
|
|||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::{HirId, HirIdMap, Node};
|
||||
use rustc_hir_analysis::check::check_abi;
|
||||
use rustc_hir_analysis::check::{check_abi, check_custom_abi};
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
|
||||
use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
|
||||
use rustc_middle::query::Providers;
|
||||
|
|
@ -138,7 +138,7 @@ fn typeck_with_inspect<'tcx>(
|
|||
// for visit the asm expr of the body.
|
||||
let ty = fcx.check_expr(body.value);
|
||||
fcx.write_ty(id, ty);
|
||||
} else if let Some(hir::FnSig { header, decl, .. }) = node.fn_sig() {
|
||||
} else if let Some(hir::FnSig { header, decl, span: fn_sig_span }) = node.fn_sig() {
|
||||
let fn_sig = if decl.output.is_suggestable_infer_ty().is_some() {
|
||||
// In the case that we're recovering `fn() -> W<_>` or some other return
|
||||
// type that has an infer in it, lower the type directly so that it'll
|
||||
|
|
@ -150,6 +150,8 @@ fn typeck_with_inspect<'tcx>(
|
|||
};
|
||||
|
||||
check_abi(tcx, id, span, fn_sig.abi());
|
||||
check_custom_abi(tcx, def_id, fn_sig.skip_binder(), *fn_sig_span);
|
||||
|
||||
loops::check(tcx, def_id, body);
|
||||
|
||||
// Compute the function signature from point of view of inside the fn.
|
||||
|
|
|
|||
|
|
@ -530,8 +530,6 @@ lint_mismatched_lifetime_syntaxes_suggestion_implicit =
|
|||
lint_mismatched_lifetime_syntaxes_suggestion_mixed =
|
||||
one option is to remove the lifetime for references and use the anonymous lifetime for paths
|
||||
|
||||
lint_missing_fragment_specifier = missing fragment specifier
|
||||
|
||||
lint_missing_unsafe_on_extern = extern blocks should be unsafe
|
||||
.suggestion = needs `unsafe` before the extern keyword
|
||||
|
||||
|
|
|
|||
|
|
@ -432,9 +432,6 @@ pub fn decorate_builtin_lint(
|
|||
BuiltinLintDiag::CfgAttrNoAttributes => {
|
||||
lints::CfgAttrNoAttributes.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::MissingFragmentSpecifier => {
|
||||
lints::MissingFragmentSpecifier.decorate_lint(diag);
|
||||
}
|
||||
BuiltinLintDiag::MetaVariableStillRepeating(name) => {
|
||||
lints::MetaVariableStillRepeating { name }.decorate_lint(diag);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -618,6 +618,11 @@ fn register_builtins(store: &mut LintStore) {
|
|||
"converted into hard error, \
|
||||
see <https://github.com/rust-lang/rust/issues/116558> for more information",
|
||||
);
|
||||
store.register_removed(
|
||||
"missing_fragment_specifier",
|
||||
"converted into hard error, \
|
||||
see <https://github.com/rust-lang/rust/issues/40107> for more information",
|
||||
);
|
||||
}
|
||||
|
||||
fn register_internals(store: &mut LintStore) {
|
||||
|
|
|
|||
|
|
@ -2590,10 +2590,6 @@ pub(crate) struct DuplicateMacroAttribute;
|
|||
#[diag(lint_cfg_attr_no_attributes)]
|
||||
pub(crate) struct CfgAttrNoAttributes;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_missing_fragment_specifier)]
|
||||
pub(crate) struct MissingFragmentSpecifier;
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_metavariable_still_repeating)]
|
||||
pub(crate) struct MetaVariableStillRepeating {
|
||||
|
|
|
|||
|
|
@ -65,7 +65,6 @@ declare_lint_pass! {
|
|||
MACRO_USE_EXTERN_CRATE,
|
||||
META_VARIABLE_MISUSE,
|
||||
MISSING_ABI,
|
||||
MISSING_FRAGMENT_SPECIFIER,
|
||||
MISSING_UNSAFE_ON_EXTERN,
|
||||
MUST_NOT_SUSPEND,
|
||||
NAMED_ARGUMENTS_USED_POSITIONALLY,
|
||||
|
|
@ -1417,51 +1416,6 @@ declare_lint! {
|
|||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `missing_fragment_specifier` lint is issued when an unused pattern in a
|
||||
/// `macro_rules!` macro definition has a meta-variable (e.g. `$e`) that is not
|
||||
/// followed by a fragment specifier (e.g. `:expr`).
|
||||
///
|
||||
/// This warning can always be fixed by removing the unused pattern in the
|
||||
/// `macro_rules!` macro definition.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust,compile_fail,edition2021
|
||||
/// macro_rules! foo {
|
||||
/// () => {};
|
||||
/// ($name) => { };
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// foo!();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// To fix this, remove the unused pattern from the `macro_rules!` macro definition:
|
||||
///
|
||||
/// ```rust
|
||||
/// macro_rules! foo {
|
||||
/// () => {};
|
||||
/// }
|
||||
/// fn main() {
|
||||
/// foo!();
|
||||
/// }
|
||||
/// ```
|
||||
pub MISSING_FRAGMENT_SPECIFIER,
|
||||
Deny,
|
||||
"detects missing fragment specifiers in unused `macro_rules!` patterns",
|
||||
@future_incompatible = FutureIncompatibleInfo {
|
||||
reason: FutureIncompatibilityReason::FutureReleaseError,
|
||||
reference: "issue #40107 <https://github.com/rust-lang/rust/issues/40107>",
|
||||
report_in_deps: true,
|
||||
};
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `late_bound_lifetime_arguments` lint detects generic lifetime
|
||||
/// arguments in path segments with late bound lifetime parameters.
|
||||
|
|
|
|||
|
|
@ -778,7 +778,6 @@ pub enum BuiltinLintDiag {
|
|||
UnnameableTestItems,
|
||||
DuplicateMacroAttribute,
|
||||
CfgAttrNoAttributes,
|
||||
MissingFragmentSpecifier,
|
||||
MetaVariableStillRepeating(MacroRulesNormalizedIdent),
|
||||
MetaVariableWrongOperator,
|
||||
DuplicateMatcherBinding,
|
||||
|
|
|
|||
|
|
@ -1266,6 +1266,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: ExternAbi)
|
|||
| RiscvInterruptS
|
||||
| CCmseNonSecureCall
|
||||
| CCmseNonSecureEntry
|
||||
| Custom
|
||||
| Unadjusted => false,
|
||||
Rust | RustCall | RustCold => tcx.sess.panic_strategy() == PanicStrategy::Unwind,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,11 @@ session_file_is_not_writeable = output file {$file} is not writeable -- check it
|
|||
|
||||
session_file_write_fail = failed to write `{$path}` due to error `{$err}`
|
||||
|
||||
session_forbidden_ctarget_feature =
|
||||
target feature `{$feature}` cannot be {$enabled} with `-Ctarget-feature`: {$reason}
|
||||
.note = this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
session_forbidden_ctarget_feature_issue = for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
|
||||
|
||||
session_function_return_requires_x86_or_x86_64 = `-Zfunction-return` (except `keep`) is only supported on x86 and x86_64
|
||||
|
||||
session_function_return_thunk_extern_requires_non_large_code_model = `-Zfunction-return=thunk-extern` is only supported on non-large code models
|
||||
|
|
@ -132,6 +137,9 @@ session_target_stack_protector_not_supported = `-Z stack-protector={$stack_prote
|
|||
session_unleashed_feature_help_named = skipping check for `{$gate}` feature
|
||||
session_unleashed_feature_help_unnamed = skipping check that does not even have a feature gate
|
||||
|
||||
session_unstable_ctarget_feature =
|
||||
unstable feature specified for `-Ctarget-feature`: `{$feature}`
|
||||
.note = this feature is not stably supported; its behavior can change in the future
|
||||
session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto`
|
||||
|
||||
session_unsupported_crate_type_for_target =
|
||||
|
|
|
|||
|
|
@ -2649,6 +2649,15 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
|
|||
|
||||
let prints = collect_print_requests(early_dcx, &mut cg, &unstable_opts, matches);
|
||||
|
||||
// -Zretpoline-external-thunk also requires -Zretpoline
|
||||
if unstable_opts.retpoline_external_thunk {
|
||||
unstable_opts.retpoline = true;
|
||||
target_modifiers.insert(
|
||||
OptionsTargetModifiers::UnstableOptions(UnstableOptionsTargetModifiers::retpoline),
|
||||
"true".to_string(),
|
||||
);
|
||||
}
|
||||
|
||||
let cg = cg;
|
||||
|
||||
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
|
||||
|
|
|
|||
|
|
@ -501,3 +501,20 @@ pub(crate) struct SoftFloatIgnored;
|
|||
#[note]
|
||||
#[note(session_soft_float_deprecated_issue)]
|
||||
pub(crate) struct SoftFloatDeprecated;
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(session_forbidden_ctarget_feature)]
|
||||
#[note]
|
||||
#[note(session_forbidden_ctarget_feature_issue)]
|
||||
pub(crate) struct ForbiddenCTargetFeature<'a> {
|
||||
pub feature: &'a str,
|
||||
pub enabled: &'a str,
|
||||
pub reason: &'a str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(session_unstable_ctarget_feature)]
|
||||
#[note]
|
||||
pub(crate) struct UnstableCTargetFeature<'a> {
|
||||
pub feature: &'a str,
|
||||
}
|
||||
|
|
|
|||
59
compiler/rustc_session/src/features.rs
Normal file
59
compiler/rustc_session/src/features.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
use rustc_target::target_features::Stability;
|
||||
|
||||
use crate::Session;
|
||||
use crate::errors::{ForbiddenCTargetFeature, UnstableCTargetFeature};
|
||||
|
||||
pub trait StabilityExt {
|
||||
/// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
|
||||
/// Otherwise, some features also may only be enabled by flag (target modifier).
|
||||
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
|
||||
/// `requires_nightly`.)
|
||||
fn is_toggle_permitted(&self, sess: &Session) -> Result<(), &'static str>;
|
||||
|
||||
/// Check that feature is correctly enabled/disabled by command line flag (emits warnings)
|
||||
fn verify_feature_enabled_by_flag(&self, sess: &Session, enable: bool, feature: &str);
|
||||
}
|
||||
|
||||
impl StabilityExt for Stability {
|
||||
fn is_toggle_permitted(&self, sess: &Session) -> Result<(), &'static str> {
|
||||
match self {
|
||||
Stability::Forbidden { reason } => Err(reason),
|
||||
Stability::TargetModifierOnly { reason, flag } => {
|
||||
if !sess.opts.target_feature_flag_enabled(*flag) { Err(reason) } else { Ok(()) }
|
||||
}
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
fn verify_feature_enabled_by_flag(&self, sess: &Session, enable: bool, feature: &str) {
|
||||
if let Err(reason) = self.is_toggle_permitted(sess) {
|
||||
sess.dcx().emit_warn(ForbiddenCTargetFeature {
|
||||
feature,
|
||||
enabled: if enable { "enabled" } else { "disabled" },
|
||||
reason,
|
||||
});
|
||||
} else if self.requires_nightly().is_some() {
|
||||
// An unstable feature. Warn about using it. It makes little sense
|
||||
// to hard-error here since we just warn about fully unknown
|
||||
// features above.
|
||||
sess.dcx().emit_warn(UnstableCTargetFeature { feature });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn retpoline_features_by_flags(sess: &Session, features: &mut Vec<&str>) {
|
||||
// -Zretpoline without -Zretpoline-external-thunk enables
|
||||
// retpoline-indirect-branches and retpoline-indirect-calls target features
|
||||
let unstable_opts = &sess.opts.unstable_opts;
|
||||
if unstable_opts.retpoline && !unstable_opts.retpoline_external_thunk {
|
||||
features.push("+retpoline-indirect-branches");
|
||||
features.push("+retpoline-indirect-calls");
|
||||
}
|
||||
// -Zretpoline-external-thunk (maybe, with -Zretpoline too) enables
|
||||
// retpoline-external-thunk, retpoline-indirect-branches and
|
||||
// retpoline-indirect-calls target features
|
||||
if unstable_opts.retpoline_external_thunk {
|
||||
features.push("+retpoline-external-thunk");
|
||||
features.push("+retpoline-indirect-branches");
|
||||
features.push("+retpoline-indirect-calls");
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,7 @@ pub use session::*;
|
|||
pub mod output;
|
||||
|
||||
pub use getopts;
|
||||
pub mod features;
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
|
|
|
|||
|
|
@ -290,6 +290,14 @@ macro_rules! top_level_options {
|
|||
mods.sort_by(|a, b| a.opt.cmp(&b.opt));
|
||||
mods
|
||||
}
|
||||
|
||||
pub fn target_feature_flag_enabled(&self, flag: &str) -> bool {
|
||||
match flag {
|
||||
"retpoline" => self.unstable_opts.retpoline,
|
||||
"retpoline-external-thunk" => self.unstable_opts.retpoline_external_thunk,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
@ -2448,6 +2456,11 @@ options! {
|
|||
remark_dir: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
|
||||
"directory into which to write optimization remarks (if not specified, they will be \
|
||||
written to standard error output)"),
|
||||
retpoline: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
|
||||
"enables retpoline-indirect-branches and retpoline-indirect-calls target features (default: no)"),
|
||||
retpoline_external_thunk: bool = (false, parse_bool, [TRACKED TARGET_MODIFIER],
|
||||
"enables retpoline-external-thunk, retpoline-indirect-branches and retpoline-indirect-calls \
|
||||
target features (default: no)"),
|
||||
sanitizer: SanitizerSet = (SanitizerSet::empty(), parse_sanitizers, [TRACKED],
|
||||
"use a sanitizer"),
|
||||
sanitizer_cfi_canonical_jump_tables: Option<bool> = (Some(true), parse_opt_bool, [TRACKED],
|
||||
|
|
|
|||
|
|
@ -496,6 +496,7 @@ impl RustcInternal for Abi {
|
|||
Abi::RustCold => rustc_abi::ExternAbi::RustCold,
|
||||
Abi::RiscvInterruptM => rustc_abi::ExternAbi::RiscvInterruptM,
|
||||
Abi::RiscvInterruptS => rustc_abi::ExternAbi::RiscvInterruptS,
|
||||
Abi::Custom => rustc_abi::ExternAbi::Custom,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ impl<'tcx> Stable<'tcx> for CanonAbi {
|
|||
CanonAbi::C => CallConvention::C,
|
||||
CanonAbi::Rust => CallConvention::Rust,
|
||||
CanonAbi::RustCold => CallConvention::Cold,
|
||||
CanonAbi::Custom => CallConvention::Custom,
|
||||
CanonAbi::Arm(arm_call) => match arm_call {
|
||||
ArmCall::Aapcs => CallConvention::ArmAapcs,
|
||||
ArmCall::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
|
||||
|
|
|
|||
|
|
@ -879,6 +879,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::ExternAbi {
|
|||
ExternAbi::RustCold => Abi::RustCold,
|
||||
ExternAbi::RiscvInterruptM => Abi::RiscvInterruptM,
|
||||
ExternAbi::RiscvInterruptS => Abi::RiscvInterruptS,
|
||||
ExternAbi::Custom => Abi::Custom,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -430,6 +430,8 @@ pub enum CallConvention {
|
|||
PreserveMost,
|
||||
PreserveAll,
|
||||
|
||||
Custom,
|
||||
|
||||
// Target-specific calling conventions.
|
||||
ArmAapcs,
|
||||
CCmseNonSecureCall,
|
||||
|
|
|
|||
|
|
@ -1111,6 +1111,7 @@ pub enum Abi {
|
|||
RustCold,
|
||||
RiscvInterruptM,
|
||||
RiscvInterruptS,
|
||||
Custom,
|
||||
}
|
||||
|
||||
/// A binder represents a possibly generic type and its bound vars.
|
||||
|
|
|
|||
|
|
@ -407,6 +407,7 @@ symbols! {
|
|||
abi_amdgpu_kernel,
|
||||
abi_avr_interrupt,
|
||||
abi_c_cmse_nonsecure_call,
|
||||
abi_custom,
|
||||
abi_efiapi,
|
||||
abi_gpu_kernel,
|
||||
abi_msp430_interrupt,
|
||||
|
|
|
|||
|
|
@ -34,11 +34,13 @@ impl LoongArchInlineAsmRegClass {
|
|||
|
||||
pub fn supported_types(
|
||||
self,
|
||||
_arch: InlineAsmArch,
|
||||
arch: InlineAsmArch,
|
||||
) -> &'static [(InlineAsmType, Option<Symbol>)] {
|
||||
match self {
|
||||
Self::reg => types! { _: I8, I16, I32, I64, F32, F64; },
|
||||
Self::freg => types! { f: F32; d: F64; },
|
||||
match (self, arch) {
|
||||
(Self::reg, InlineAsmArch::LoongArch64) => types! { _: I8, I16, I32, I64, F32, F64; },
|
||||
(Self::reg, InlineAsmArch::LoongArch32) => types! { _: I8, I16, I32, F32; },
|
||||
(Self::freg, _) => types! { f: F32; d: F64; },
|
||||
_ => unreachable!("unsupported register class"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ impl AbiMap {
|
|||
(ExternAbi::RustCold, _) if self.os == OsKind::Windows => CanonAbi::Rust,
|
||||
(ExternAbi::RustCold, _) => CanonAbi::RustCold,
|
||||
|
||||
(ExternAbi::Custom, _) => CanonAbi::Custom,
|
||||
|
||||
(ExternAbi::System { .. }, Arch::X86) if os == OsKind::Windows && !has_c_varargs => {
|
||||
CanonAbi::X86(X86Call::Stdcall)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ pub enum Stability {
|
|||
/// particular for features are actually ABI configuration flags (not all targets are as nice as
|
||||
/// RISC-V and have an explicit way to set the ABI separate from target features).
|
||||
Forbidden { reason: &'static str },
|
||||
/// This feature can not be set via `-Ctarget-feature` or `#[target_feature]`, it can only be set
|
||||
/// by target modifier flag. Target modifier flags are tracked to be consistent in linked modules.
|
||||
TargetModifierOnly { reason: &'static str, flag: &'static str },
|
||||
}
|
||||
use Stability::*;
|
||||
|
||||
|
|
@ -49,6 +52,7 @@ impl<CTX> HashStable<CTX> for Stability {
|
|||
Stability::Forbidden { reason } => {
|
||||
reason.hash_stable(hcx, hasher);
|
||||
}
|
||||
Stability::TargetModifierOnly { .. } => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -74,16 +78,7 @@ impl Stability {
|
|||
Stability::Unstable(nightly_feature) => Some(nightly_feature),
|
||||
Stability::Stable { .. } => None,
|
||||
Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`.
|
||||
/// (It might still be nightly-only even if this returns `true`, so make sure to also check
|
||||
/// `requires_nightly`.)
|
||||
pub fn toggle_allowed(&self) -> Result<(), &'static str> {
|
||||
match self {
|
||||
Stability::Forbidden { reason } => Err(reason),
|
||||
_ => Ok(()),
|
||||
Stability::TargetModifierOnly { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -453,6 +448,30 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
|
|||
("prfchw", Unstable(sym::prfchw_target_feature), &[]),
|
||||
("rdrand", Stable, &[]),
|
||||
("rdseed", Stable, &[]),
|
||||
(
|
||||
"retpoline-external-thunk",
|
||||
Stability::TargetModifierOnly {
|
||||
reason: "use `retpoline-external-thunk` target modifier flag instead",
|
||||
flag: "retpoline-external-thunk",
|
||||
},
|
||||
&[],
|
||||
),
|
||||
(
|
||||
"retpoline-indirect-branches",
|
||||
Stability::TargetModifierOnly {
|
||||
reason: "use `retpoline` target modifier flag instead",
|
||||
flag: "retpoline",
|
||||
},
|
||||
&[],
|
||||
),
|
||||
(
|
||||
"retpoline-indirect-calls",
|
||||
Stability::TargetModifierOnly {
|
||||
reason: "use `retpoline` target modifier flag instead",
|
||||
flag: "retpoline",
|
||||
},
|
||||
&[],
|
||||
),
|
||||
("rtm", Unstable(sym::rtm_target_feature), &[]),
|
||||
("sha", Stable, &["sse2"]),
|
||||
("sha512", Stable, &["avx2"]),
|
||||
|
|
|
|||
|
|
@ -4,11 +4,10 @@ version = 4
|
|||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.24.2"
|
||||
version = "0.25.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
|
||||
checksum = "9acbfca36652500c911ddb767ed433e3ed99b032b5d935be73c6923662db1d43"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
|
|
@ -16,11 +15,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "adler2"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
|
||||
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
|
|
@ -51,11 +49,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
|
|
@ -81,12 +78,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "dlmalloc"
|
||||
version = "0.2.8"
|
||||
version = "0.2.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8cff88b751e7a276c4ab0e222c3f355190adc6dde9ce39c851db39da34990df7"
|
||||
checksum = "d01597dde41c0b9da50d5f8c219023d63d8f27f39a27095070fd191fddc83891"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-core",
|
||||
"windows-sys",
|
||||
|
|
@ -104,9 +100,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
version = "0.2.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5"
|
||||
checksum = "cba6ae63eb948698e300f645f87c70f76630d505f23b8907cf1e193ee85048c1"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
|
|
@ -115,11 +111,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.31.1"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
checksum = "93563d740bc9ef04104f9ed6f86f1e3275c2cdafb95664e26584b9ca807a8ffe"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
|
@ -136,11 +131,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f154ce46856750ed433c8649605bf7ed2de3bc35fd9d2a9f30cddd873c80cb08"
|
||||
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
|
@ -156,33 +150,30 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
version = "2.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.8.8"
|
||||
version = "0.8.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a"
|
||||
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
|
||||
dependencies = [
|
||||
"adler2",
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
version = "0.37.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
|
||||
checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"memchr",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
|
|
@ -273,11 +264,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.24"
|
||||
version = "0.1.25"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
|
|
@ -352,7 +342,6 @@ name = "std_detect"
|
|||
version = "0.1.5"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"compiler_builtins",
|
||||
"libc",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
|
|
@ -380,11 +369,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.14"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
"rustc-std-workspace-std",
|
||||
]
|
||||
|
|
@ -402,9 +390,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unwinding"
|
||||
version = "0.2.6"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8393f2782b6060a807337ff353780c1ca15206f9ba2424df18cb6e733bd7b345"
|
||||
checksum = "7d80f6c2bfede213d9a90b4a14f3eb99b84e33c52df6c1a15de0a100f5a88751"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"gimli",
|
||||
|
|
@ -413,11 +401,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
version = "0.11.1+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ rustc-demangle = { version = "0.1.24", features = ['rustc-dep-of-std'] }
|
|||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc", not(target_vendor = "uwp"))))'.dependencies]
|
||||
miniz_oxide = { version = "0.8.0", optional = true, default-features = false }
|
||||
addr2line = { version = "0.24.0", optional = true, default-features = false }
|
||||
addr2line = { version = "0.25.0", optional = true, default-features = false }
|
||||
|
||||
[target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies]
|
||||
libc = { version = "0.2.172", default-features = false, features = [
|
||||
|
|
@ -40,7 +40,7 @@ libc = { version = "0.2.172", default-features = false, features = [
|
|||
], public = true }
|
||||
|
||||
[target.'cfg(all(not(target_os = "aix"), not(all(windows, target_env = "msvc", not(target_vendor = "uwp")))))'.dependencies]
|
||||
object = { version = "0.36.0", default-features = false, optional = true, features = [
|
||||
object = { version = "0.37.1", default-features = false, optional = true, features = [
|
||||
'read_core',
|
||||
'elf',
|
||||
'macho',
|
||||
|
|
@ -50,7 +50,7 @@ object = { version = "0.36.0", default-features = false, optional = true, featur
|
|||
] }
|
||||
|
||||
[target.'cfg(target_os = "aix")'.dependencies]
|
||||
object = { version = "0.36.0", default-features = false, optional = true, features = [
|
||||
object = { version = "0.37.1", default-features = false, optional = true, features = [
|
||||
'read_core',
|
||||
'xcoff',
|
||||
'unaligned',
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5c1c436524c0bbc8db83577f42f8bea9006a7b75
|
||||
Subproject commit 1b4d15df12079504942d0a3f1030b2039b8a776c
|
||||
|
|
@ -22,7 +22,7 @@ cfg-if = "1.0"
|
|||
libc = { version = "0.2.140", features = ['rustc-dep-of-std'], default-features = false }
|
||||
|
||||
[target.'cfg(target_os = "xous")'.dependencies]
|
||||
unwinding = { version = "0.2.6", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false }
|
||||
unwinding = { version = "0.2.7", features = ['rustc-dep-of-std', 'unwinder', 'fde-custom'], default-features = false }
|
||||
|
||||
[features]
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||
- M68k
|
||||
- CSKY
|
||||
- SPARC
|
||||
- LoongArch32
|
||||
|
||||
## Register classes
|
||||
|
||||
|
|
@ -53,6 +54,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||
| CSKY | `freg` | `f[0-31]` | `f` |
|
||||
| SPARC | `reg` | `r[2-29]` | `r` |
|
||||
| SPARC | `yreg` | `y` | Only clobbers |
|
||||
| LoongArch32 | `reg` | `$r1`, `$r[4-20]`, `$r[23,30]` | `r` |
|
||||
| LoongArch32 | `freg` | `$f[0-31]` | `f` |
|
||||
|
||||
> **Notes**:
|
||||
> - NVPTX doesn't have a fixed register set, so named registers are not supported.
|
||||
|
|
@ -91,6 +94,8 @@ This feature tracks `asm!` and `global_asm!` support for the following architect
|
|||
| CSKY | `freg` | None | `f32`, |
|
||||
| SPARC | `reg` | None | `i8`, `i16`, `i32`, `i64` (SPARC64 only) |
|
||||
| SPARC | `yreg` | N/A | Only clobbers |
|
||||
| LoongArch32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |
|
||||
| LoongArch32 | `freg` | None | `f32`, `f64` |
|
||||
|
||||
## Register aliases
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use rustc_data_structures::fx::FxHashSet;
|
|||
use rustc_hir::def_id::{DefId, DefIdSet};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::features::StabilityExt;
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use rustdoc_json_types as types;
|
||||
// It's important to use the FxHashMap from rustdoc_json_types here, instead of
|
||||
|
|
@ -148,7 +149,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
|
|||
.copied()
|
||||
.filter(|(_, stability, _)| {
|
||||
// Describe only target features which the user can toggle
|
||||
stability.toggle_allowed().is_ok()
|
||||
stability.is_toggle_permitted(sess).is_ok()
|
||||
})
|
||||
.map(|(name, stability, implied_features)| {
|
||||
types::TargetFeature {
|
||||
|
|
@ -164,7 +165,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
|
|||
// Imply only target features which the user can toggle
|
||||
feature_stability
|
||||
.get(name)
|
||||
.map(|stability| stability.toggle_allowed().is_ok())
|
||||
.map(|stability| stability.is_toggle_permitted(sess).is_ok())
|
||||
.unwrap_or(false)
|
||||
})
|
||||
.map(String::from)
|
||||
|
|
|
|||
31
tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs
Normal file
31
tests/codegen/autovec/dont-shuffle-bswaps-opt2.rs
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
//@ compile-flags: -Copt-level=2
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![no_std]
|
||||
|
||||
// This test is paired with the arch-specific -opt3.rs test.
|
||||
|
||||
// The code is from https://github.com/rust-lang/rust/issues/122805.
|
||||
// Ensure we do not generate the shufflevector instruction
|
||||
// to avoid complicating the code.
|
||||
|
||||
// CHECK-LABEL: define{{.*}}void @convert(
|
||||
// CHECK-NOT: shufflevector
|
||||
#[no_mangle]
|
||||
pub fn convert(value: [u16; 8]) -> [u8; 16] {
|
||||
#[cfg(target_endian = "little")]
|
||||
let bswap = u16::to_be;
|
||||
#[cfg(target_endian = "big")]
|
||||
let bswap = u16::to_le;
|
||||
let addr16 = [
|
||||
bswap(value[0]),
|
||||
bswap(value[1]),
|
||||
bswap(value[2]),
|
||||
bswap(value[3]),
|
||||
bswap(value[4]),
|
||||
bswap(value[5]),
|
||||
bswap(value[6]),
|
||||
bswap(value[7]),
|
||||
];
|
||||
unsafe { core::mem::transmute::<_, [u8; 16]>(addr16) }
|
||||
}
|
||||
|
|
@ -1,29 +1,27 @@
|
|||
//@ revisions: OPT2 OPT3 OPT3_S390X
|
||||
//@[OPT2] compile-flags: -Copt-level=2
|
||||
//@[OPT3] compile-flags: -C opt-level=3
|
||||
// some targets don't do the opt we are looking for
|
||||
//@[OPT3] only-64bit
|
||||
//@[OPT3] ignore-s390x
|
||||
//@[OPT3_S390X] compile-flags: -C opt-level=3 -C target-cpu=z13
|
||||
//@[OPT3_S390X] only-s390x
|
||||
//@ revisions: AARCH64 X86_64 Z13
|
||||
//@ compile-flags: -Copt-level=3
|
||||
//@[AARCH64] only-aarch64
|
||||
//@[X86_64] only-x86_64
|
||||
//@[Z13] only-s390x
|
||||
//@[Z13] compile-flags: -Ctarget-cpu=z13
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![no_std]
|
||||
|
||||
// This test is paired with the arch-neutral -opt2.rs test
|
||||
|
||||
// The code is from https://github.com/rust-lang/rust/issues/122805.
|
||||
// Ensure we do not generate the shufflevector instruction
|
||||
// to avoid complicating the code.
|
||||
|
||||
// CHECK-LABEL: define{{.*}}void @convert(
|
||||
// CHECK-NOT: shufflevector
|
||||
|
||||
// On higher opt levels, this should just be a bswap:
|
||||
// OPT3: load <8 x i16>
|
||||
// OPT3-NEXT: call <8 x i16> @llvm.bswap
|
||||
// OPT3-NEXT: store <8 x i16>
|
||||
// OPT3-NEXT: ret void
|
||||
// OPT3_S390X: load <8 x i16>
|
||||
// OPT3_S390X-NEXT: call <8 x i16> @llvm.bswap
|
||||
// OPT3_S390X-NEXT: store <8 x i16>
|
||||
// OPT3_S390X-NEXT: ret void
|
||||
// CHECK: load <8 x i16>
|
||||
// CHECK-NEXT: call <8 x i16> @llvm.bswap
|
||||
// CHECK-NEXT: store <8 x i16>
|
||||
// CHECK-NEXT: ret void
|
||||
#[no_mangle]
|
||||
pub fn convert(value: [u16; 8]) -> [u8; 16] {
|
||||
#[cfg(target_endian = "little")]
|
||||
29
tests/codegen/retpoline.rs
Normal file
29
tests/codegen/retpoline.rs
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
// ignore-tidy-linelength
|
||||
// Test that the
|
||||
// `retpoline-external-thunk`, `retpoline-indirect-branches`, `retpoline-indirect-calls`
|
||||
// target features are (not) emitted when the `retpoline/retpoline-external-thunk` flag is (not) set.
|
||||
|
||||
//@ revisions: disabled enabled_retpoline enabled_retpoline_external_thunk
|
||||
//@ needs-llvm-components: x86
|
||||
//@ compile-flags: --target x86_64-unknown-linux-gnu
|
||||
//@ [enabled_retpoline] compile-flags: -Zretpoline
|
||||
//@ [enabled_retpoline_external_thunk] compile-flags: -Zretpoline-external-thunk
|
||||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(no_core, lang_items)]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "sized"]
|
||||
trait Sized {}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn foo() {
|
||||
// CHECK: @foo() unnamed_addr #0
|
||||
|
||||
// disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-external-thunk{{.*}} }
|
||||
// disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-branches{{.*}} }
|
||||
// disabled-NOT: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-calls{{.*}} }
|
||||
|
||||
// enabled_retpoline: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-indirect-branches,+retpoline-indirect-calls{{.*}} }
|
||||
// enabled_retpoline_external_thunk: attributes #0 = { {{.*}}"target-features"="{{[^"]*}}+retpoline-external-thunk,+retpoline-indirect-branches,+retpoline-indirect-calls{{.*}} }
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
macro_rules! morestuff {
|
||||
(
|
||||
<= "space between most kinds of tokens" : 1 $x + @ :: >>= 'static
|
||||
"no space inside paren or bracket" : (2 a) [2 a] $(2 $a:tt)*
|
||||
<= "space between most kinds of tokens" : 1 $x:ident + @ :: >>=
|
||||
'static "no space inside paren or bracket" : (2 a) [2 a] $(2 $a:tt)*
|
||||
"space inside curly brace" : { 2 a }
|
||||
"no space inside empty delimiters" : () [] {}
|
||||
"no space before comma or semicolon" : a, (a), { a }, a; [T; 0];
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ make_macro!(linebreak 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
|||
|
||||
//@ snapshot macro_morestuff_pre macro_generated_macro/macro.morestuff.html //pre/text()
|
||||
make_macro!(morestuff
|
||||
"space between most kinds of tokens": 1 $x + @ :: >>= 'static
|
||||
"space between most kinds of tokens": 1 $x:ident + @ :: >>= 'static
|
||||
"no space inside paren or bracket": (2 a) [2 a] $(2 $a:tt)*
|
||||
"space inside curly brace": { 2 a }
|
||||
"no space inside empty delimiters": () [] {}
|
||||
|
|
|
|||
121
tests/ui/abi/bad-custom.rs
Normal file
121
tests/ui/abi/bad-custom.rs
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
//@ edition: 2021
|
||||
//@ check-fail
|
||||
//@ needs-asm-support
|
||||
#![feature(abi_custom)]
|
||||
|
||||
#[unsafe(naked)]
|
||||
extern "custom" fn must_be_unsafe(a: i64) -> i64 {
|
||||
//~^ ERROR functions with the `"custom"` ABI must be unsafe
|
||||
//~| ERROR invalid signature for `extern "custom"` function
|
||||
std::arch::naked_asm!("")
|
||||
}
|
||||
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "custom" fn no_parameters(a: i64) {
|
||||
//~^ ERROR invalid signature for `extern "custom"` function
|
||||
std::arch::naked_asm!("")
|
||||
}
|
||||
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "custom" fn no_return_type() -> i64 {
|
||||
//~^ ERROR invalid signature for `extern "custom"` function
|
||||
std::arch::naked_asm!("")
|
||||
}
|
||||
|
||||
unsafe extern "custom" fn double(a: i64) -> i64 {
|
||||
//~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
//~| ERROR invalid signature for `extern "custom"` function
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
struct Thing(i64);
|
||||
|
||||
impl Thing {
|
||||
unsafe extern "custom" fn is_even(self) -> bool {
|
||||
//~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
//~| ERROR invalid signature for `extern "custom"` function
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
trait BitwiseNot {
|
||||
unsafe extern "custom" fn bitwise_not(a: i64) -> i64 {
|
||||
//~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
//~| ERROR invalid signature for `extern "custom"` function
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
impl BitwiseNot for Thing {}
|
||||
|
||||
trait Negate {
|
||||
extern "custom" fn negate(a: i64) -> i64;
|
||||
//~^ ERROR functions with the `"custom"` ABI must be unsafe
|
||||
//~| ERROR invalid signature for `extern "custom"` function
|
||||
}
|
||||
|
||||
impl Negate for Thing {
|
||||
extern "custom" fn negate(a: i64) -> i64 {
|
||||
//~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
//~| ERROR functions with the `"custom"` ABI must be unsafe
|
||||
//~| ERROR invalid signature for `extern "custom"` function
|
||||
-a
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "custom" {
|
||||
fn increment(a: i64) -> i64;
|
||||
//~^ ERROR invalid signature for `extern "custom"` function
|
||||
|
||||
safe fn extern_cannot_be_safe();
|
||||
//~^ ERROR foreign functions with the `"custom"` ABI cannot be safe
|
||||
}
|
||||
|
||||
fn caller(f: unsafe extern "custom" fn(i64) -> i64, mut x: i64) -> i64 {
|
||||
unsafe { f(x) }
|
||||
//~^ ERROR functions with the `"custom"` ABI cannot be called
|
||||
}
|
||||
|
||||
fn caller_by_ref(f: &unsafe extern "custom" fn(i64) -> i64, mut x: i64) -> i64 {
|
||||
unsafe { f(x) }
|
||||
//~^ ERROR functions with the `"custom"` ABI cannot be called
|
||||
}
|
||||
|
||||
type Custom = unsafe extern "custom" fn(i64) -> i64;
|
||||
|
||||
fn caller_alias(f: Custom, mut x: i64) -> i64 {
|
||||
unsafe { f(x) }
|
||||
//~^ ERROR functions with the `"custom"` ABI cannot be called
|
||||
}
|
||||
|
||||
#[unsafe(naked)]
|
||||
const unsafe extern "custom" fn no_const_fn() {
|
||||
std::arch::naked_asm!("")
|
||||
//~^ ERROR inline assembly is not allowed in constant functions
|
||||
}
|
||||
|
||||
async unsafe extern "custom" fn no_async_fn() {
|
||||
//~^ ERROR items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
//~| ERROR functions with the `"custom"` ABI cannot be `async`
|
||||
}
|
||||
|
||||
fn no_promotion_to_fn_trait(f: unsafe extern "custom" fn()) -> impl Fn() {
|
||||
//~^ ERROR expected a `Fn()` closure, found `unsafe extern "custom" fn()`
|
||||
f
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
unsafe {
|
||||
assert_eq!(double(21), 42);
|
||||
//~^ ERROR functions with the `"custom"` ABI cannot be called
|
||||
|
||||
assert_eq!(unsafe { increment(41) }, 42);
|
||||
//~^ ERROR functions with the `"custom"` ABI cannot be called
|
||||
|
||||
assert!(Thing(41).is_even());
|
||||
//~^ ERROR functions with the `"custom"` ABI cannot be called
|
||||
|
||||
assert_eq!(Thing::bitwise_not(42), !42);
|
||||
//~^ ERROR functions with the `"custom"` ABI cannot be called
|
||||
}
|
||||
}
|
||||
299
tests/ui/abi/bad-custom.stderr
Normal file
299
tests/ui/abi/bad-custom.stderr
Normal file
|
|
@ -0,0 +1,299 @@
|
|||
error: functions with the `"custom"` ABI must be unsafe
|
||||
--> $DIR/bad-custom.rs:7:1
|
||||
|
|
||||
LL | extern "custom" fn must_be_unsafe(a: i64) -> i64 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "custom" fn must_be_unsafe(a: i64) -> i64 {
|
||||
| ++++++
|
||||
|
||||
error: invalid signature for `extern "custom"` function
|
||||
--> $DIR/bad-custom.rs:7:35
|
||||
|
|
||||
LL | extern "custom" fn must_be_unsafe(a: i64) -> i64 {
|
||||
| ^^^^^^ ^^^
|
||||
|
|
||||
= note: functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
help: remove the parameters and return type
|
||||
|
|
||||
LL - extern "custom" fn must_be_unsafe(a: i64) -> i64 {
|
||||
LL + extern "custom" fn must_be_unsafe() {
|
||||
|
|
||||
|
||||
error: invalid signature for `extern "custom"` function
|
||||
--> $DIR/bad-custom.rs:14:41
|
||||
|
|
||||
LL | unsafe extern "custom" fn no_parameters(a: i64) {
|
||||
| ^^^^^^
|
||||
|
|
||||
= note: functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
help: remove the parameters and return type
|
||||
|
|
||||
LL - unsafe extern "custom" fn no_parameters(a: i64) {
|
||||
LL + unsafe extern "custom" fn no_parameters() {
|
||||
|
|
||||
|
||||
error: invalid signature for `extern "custom"` function
|
||||
--> $DIR/bad-custom.rs:20:47
|
||||
|
|
||||
LL | unsafe extern "custom" fn no_return_type() -> i64 {
|
||||
| ^^^
|
||||
|
|
||||
= note: functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
help: remove the parameters and return type
|
||||
|
|
||||
LL - unsafe extern "custom" fn no_return_type() -> i64 {
|
||||
LL + unsafe extern "custom" fn no_return_type() {
|
||||
|
|
||||
|
||||
error: invalid signature for `extern "custom"` function
|
||||
--> $DIR/bad-custom.rs:25:34
|
||||
|
|
||||
LL | unsafe extern "custom" fn double(a: i64) -> i64 {
|
||||
| ^^^^^^ ^^^
|
||||
|
|
||||
= note: functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
help: remove the parameters and return type
|
||||
|
|
||||
LL - unsafe extern "custom" fn double(a: i64) -> i64 {
|
||||
LL + unsafe extern "custom" fn double() {
|
||||
|
|
||||
|
||||
error: invalid signature for `extern "custom"` function
|
||||
--> $DIR/bad-custom.rs:34:39
|
||||
|
|
||||
LL | unsafe extern "custom" fn is_even(self) -> bool {
|
||||
| ^^^^ ^^^^
|
||||
|
|
||||
= note: functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
help: remove the parameters and return type
|
||||
|
|
||||
LL - unsafe extern "custom" fn is_even(self) -> bool {
|
||||
LL + unsafe extern "custom" fn is_even() {
|
||||
|
|
||||
|
||||
error: invalid signature for `extern "custom"` function
|
||||
--> $DIR/bad-custom.rs:42:43
|
||||
|
|
||||
LL | unsafe extern "custom" fn bitwise_not(a: i64) -> i64 {
|
||||
| ^^^^^^ ^^^
|
||||
|
|
||||
= note: functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
help: remove the parameters and return type
|
||||
|
|
||||
LL - unsafe extern "custom" fn bitwise_not(a: i64) -> i64 {
|
||||
LL + unsafe extern "custom" fn bitwise_not() {
|
||||
|
|
||||
|
||||
error: functions with the `"custom"` ABI must be unsafe
|
||||
--> $DIR/bad-custom.rs:52:5
|
||||
|
|
||||
LL | extern "custom" fn negate(a: i64) -> i64;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "custom" fn negate(a: i64) -> i64;
|
||||
| ++++++
|
||||
|
||||
error: invalid signature for `extern "custom"` function
|
||||
--> $DIR/bad-custom.rs:52:31
|
||||
|
|
||||
LL | extern "custom" fn negate(a: i64) -> i64;
|
||||
| ^^^^^^ ^^^
|
||||
|
|
||||
= note: functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
help: remove the parameters and return type
|
||||
|
|
||||
LL - extern "custom" fn negate(a: i64) -> i64;
|
||||
LL + extern "custom" fn negate();
|
||||
|
|
||||
|
||||
error: functions with the `"custom"` ABI must be unsafe
|
||||
--> $DIR/bad-custom.rs:58:5
|
||||
|
|
||||
LL | extern "custom" fn negate(a: i64) -> i64 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "custom" fn negate(a: i64) -> i64 {
|
||||
| ++++++
|
||||
|
||||
error: invalid signature for `extern "custom"` function
|
||||
--> $DIR/bad-custom.rs:58:31
|
||||
|
|
||||
LL | extern "custom" fn negate(a: i64) -> i64 {
|
||||
| ^^^^^^ ^^^
|
||||
|
|
||||
= note: functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
help: remove the parameters and return type
|
||||
|
|
||||
LL - extern "custom" fn negate(a: i64) -> i64 {
|
||||
LL + extern "custom" fn negate() {
|
||||
|
|
||||
|
||||
error: invalid signature for `extern "custom"` function
|
||||
--> $DIR/bad-custom.rs:67:18
|
||||
|
|
||||
LL | fn increment(a: i64) -> i64;
|
||||
| ^^^^^^ ^^^
|
||||
|
|
||||
= note: functions with the `"custom"` ABI cannot have any parameters or return type
|
||||
help: remove the parameters and return type
|
||||
|
|
||||
LL - fn increment(a: i64) -> i64;
|
||||
LL + fn increment();
|
||||
|
|
||||
|
||||
error: foreign functions with the `"custom"` ABI cannot be safe
|
||||
--> $DIR/bad-custom.rs:70:5
|
||||
|
|
||||
LL | safe fn extern_cannot_be_safe();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the `safe` keyword from this definition
|
||||
|
|
||||
LL - safe fn extern_cannot_be_safe();
|
||||
LL + fn extern_cannot_be_safe();
|
||||
|
|
||||
|
||||
error: functions with the `"custom"` ABI cannot be `async`
|
||||
--> $DIR/bad-custom.rs:97:1
|
||||
|
|
||||
LL | async unsafe extern "custom" fn no_async_fn() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: remove the `async` keyword from this definiton
|
||||
|
|
||||
LL - async unsafe extern "custom" fn no_async_fn() {
|
||||
LL + unsafe extern "custom" fn no_async_fn() {
|
||||
|
|
||||
|
||||
error: items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
--> $DIR/bad-custom.rs:97:1
|
||||
|
|
||||
LL | async unsafe extern "custom" fn no_async_fn() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: convert this to an `#[unsafe(naked)]` function
|
||||
|
|
||||
LL + #[unsafe(naked)]
|
||||
LL | async unsafe extern "custom" fn no_async_fn() {
|
||||
|
|
||||
|
||||
error[E0277]: expected a `Fn()` closure, found `unsafe extern "custom" fn()`
|
||||
--> $DIR/bad-custom.rs:102:64
|
||||
|
|
||||
LL | fn no_promotion_to_fn_trait(f: unsafe extern "custom" fn()) -> impl Fn() {
|
||||
| ^^^^^^^^^ call the function in a closure: `|| unsafe { /* code */ }`
|
||||
LL |
|
||||
LL | f
|
||||
| - return type was inferred to be `unsafe extern "custom" fn()` here
|
||||
|
|
||||
= help: the trait `Fn()` is not implemented for `unsafe extern "custom" fn()`
|
||||
= note: unsafe function cannot be called generically without an unsafe block
|
||||
= note: wrap the `unsafe extern "custom" fn()` in a closure with no arguments: `|| { /* code */ }`
|
||||
|
||||
error: items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
--> $DIR/bad-custom.rs:25:1
|
||||
|
|
||||
LL | unsafe extern "custom" fn double(a: i64) -> i64 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: convert this to an `#[unsafe(naked)]` function
|
||||
|
|
||||
LL + #[unsafe(naked)]
|
||||
LL | unsafe extern "custom" fn double(a: i64) -> i64 {
|
||||
|
|
||||
|
||||
error: items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
--> $DIR/bad-custom.rs:34:5
|
||||
|
|
||||
LL | unsafe extern "custom" fn is_even(self) -> bool {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: convert this to an `#[unsafe(naked)]` function
|
||||
|
|
||||
LL + #[unsafe(naked)]
|
||||
LL | unsafe extern "custom" fn is_even(self) -> bool {
|
||||
|
|
||||
|
||||
error: items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
--> $DIR/bad-custom.rs:42:5
|
||||
|
|
||||
LL | unsafe extern "custom" fn bitwise_not(a: i64) -> i64 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: convert this to an `#[unsafe(naked)]` function
|
||||
|
|
||||
LL + #[unsafe(naked)]
|
||||
LL | unsafe extern "custom" fn bitwise_not(a: i64) -> i64 {
|
||||
|
|
||||
|
||||
error: items with the `"custom"` ABI can only be declared externally or defined via naked functions
|
||||
--> $DIR/bad-custom.rs:58:5
|
||||
|
|
||||
LL | extern "custom" fn negate(a: i64) -> i64 {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: convert this to an `#[unsafe(naked)]` function
|
||||
|
|
||||
LL + #[unsafe(naked)]
|
||||
LL | extern "custom" fn negate(a: i64) -> i64 {
|
||||
|
|
||||
|
||||
error: functions with the `"custom"` ABI cannot be called
|
||||
--> $DIR/bad-custom.rs:75:14
|
||||
|
|
||||
LL | unsafe { f(x) }
|
||||
| ^^^^
|
||||
|
||||
error: functions with the `"custom"` ABI cannot be called
|
||||
--> $DIR/bad-custom.rs:80:14
|
||||
|
|
||||
LL | unsafe { f(x) }
|
||||
| ^^^^
|
||||
|
||||
error: functions with the `"custom"` ABI cannot be called
|
||||
--> $DIR/bad-custom.rs:87:14
|
||||
|
|
||||
LL | unsafe { f(x) }
|
||||
| ^^^^
|
||||
|
||||
error: functions with the `"custom"` ABI cannot be called
|
||||
--> $DIR/bad-custom.rs:109:20
|
||||
|
|
||||
LL | assert_eq!(double(21), 42);
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: functions with the `"custom"` ABI cannot be called
|
||||
--> $DIR/bad-custom.rs:112:29
|
||||
|
|
||||
LL | assert_eq!(unsafe { increment(41) }, 42);
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: functions with the `"custom"` ABI cannot be called
|
||||
--> $DIR/bad-custom.rs:115:17
|
||||
|
|
||||
LL | assert!(Thing(41).is_even());
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: functions with the `"custom"` ABI cannot be called
|
||||
--> $DIR/bad-custom.rs:118:20
|
||||
|
|
||||
LL | assert_eq!(Thing::bitwise_not(42), !42);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0015]: inline assembly is not allowed in constant functions
|
||||
--> $DIR/bad-custom.rs:93:5
|
||||
|
|
||||
LL | std::arch::naked_asm!("")
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 28 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0015, E0277.
|
||||
For more information about an error, try `rustc --explain E0015`.
|
||||
88
tests/ui/abi/custom.rs
Normal file
88
tests/ui/abi/custom.rs
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
// Test that `extern "custom"` functions can be called from assembly, and defined using a naked
|
||||
// function, and `global_asm!` with an `extern "custom"` block.
|
||||
//
|
||||
//@ run-pass
|
||||
//@ only-x86_64
|
||||
#![feature(abi_custom)]
|
||||
|
||||
use std::arch::{asm, global_asm, naked_asm};
|
||||
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "custom" fn double() {
|
||||
naked_asm!("add rax, rax", "ret");
|
||||
}
|
||||
|
||||
global_asm!(
|
||||
// work around macOS prefixing symbols with _
|
||||
" .globl {0}",
|
||||
"{0}:",
|
||||
" add rax, 1",
|
||||
" ret",
|
||||
sym increment,
|
||||
);
|
||||
|
||||
unsafe extern "custom" {
|
||||
fn increment();
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
struct Thing(u64);
|
||||
|
||||
impl Thing {
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "custom" fn is_even() {
|
||||
naked_asm!("test al, 1", "sete al", "ret");
|
||||
}
|
||||
}
|
||||
|
||||
trait BitwiseNot {
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "custom" fn bitwise_not() {
|
||||
naked_asm!("not rax", "ret");
|
||||
}
|
||||
}
|
||||
|
||||
impl BitwiseNot for Thing {}
|
||||
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn const_generic<const N: u64>() {
|
||||
naked_asm!(
|
||||
"mov rax, {}",
|
||||
"ret",
|
||||
const N,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let mut x: u64 = 21;
|
||||
unsafe { asm!("call {}", sym double, inout("rax") x) };
|
||||
assert_eq!(x, 42);
|
||||
|
||||
let mut x: u64 = 41;
|
||||
unsafe { asm!("call {}", sym increment, inout("rax") x) };
|
||||
assert_eq!(x, 42);
|
||||
|
||||
let mut x: u8;
|
||||
unsafe { asm!("call {}", sym Thing::is_even, inout("al") 42u8 => x) };
|
||||
assert!(x != 0);
|
||||
|
||||
let mut x: u64 = 42;
|
||||
unsafe { asm!("call {}", sym Thing::bitwise_not, inout("rax") x) };
|
||||
assert_eq!(x, !42);
|
||||
|
||||
// Create and call in `asm!` an `extern "custom"` function pointer.
|
||||
fn caller(f: unsafe extern "custom" fn(), mut x: u64) -> u64 {
|
||||
unsafe { asm!("call {}", in(reg) f, inout("rax") x) };
|
||||
x
|
||||
}
|
||||
|
||||
assert_eq!(caller(double, 2), 4);
|
||||
|
||||
let x: u64;
|
||||
unsafe { asm!("call {}", sym const_generic::<42>, out("rax") x) };
|
||||
assert_eq!(x, 42);
|
||||
|
||||
let x: u64;
|
||||
unsafe { asm!("call {}", sym const_generic::<84>, out("rax") x) };
|
||||
assert_eq!(x, 84);
|
||||
}
|
||||
|
|
@ -212,6 +212,9 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
|
|||
`relax`
|
||||
`relaxed-simd`
|
||||
`reserve-x18`
|
||||
`retpoline-external-thunk`
|
||||
`retpoline-indirect-branches`
|
||||
`retpoline-indirect-calls`
|
||||
`rtm`
|
||||
`sb`
|
||||
`scq`
|
||||
|
|
|
|||
51
tests/ui/feature-gates/feature-gate-abi-custom.rs
Normal file
51
tests/ui/feature-gates/feature-gate-abi-custom.rs
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
//@ add-core-stubs
|
||||
//@ needs-asm-support
|
||||
#![no_core]
|
||||
#![feature(no_core, lang_items)]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
extern crate minicore;
|
||||
use minicore::*;
|
||||
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "custom" fn f7() {
|
||||
//~^ ERROR "custom" ABI is experimental
|
||||
naked_asm!("")
|
||||
}
|
||||
trait Tr {
|
||||
extern "custom" fn m7();
|
||||
//~^ ERROR "custom" ABI is experimental
|
||||
//~| ERROR functions with the `"custom"` ABI must be unsafe
|
||||
#[unsafe(naked)]
|
||||
extern "custom" fn dm7() {
|
||||
//~^ ERROR "custom" ABI is experimental
|
||||
//~| ERROR functions with the `"custom"` ABI must be unsafe
|
||||
naked_asm!("")
|
||||
}
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
// Methods in trait impl
|
||||
impl Tr for S {
|
||||
#[unsafe(naked)]
|
||||
extern "custom" fn m7() {
|
||||
//~^ ERROR "custom" ABI is experimental
|
||||
//~| ERROR functions with the `"custom"` ABI must be unsafe
|
||||
naked_asm!("")
|
||||
}
|
||||
}
|
||||
|
||||
// Methods in inherent impl
|
||||
impl S {
|
||||
#[unsafe(naked)]
|
||||
extern "custom" fn im7() {
|
||||
//~^ ERROR "custom" ABI is experimental
|
||||
//~| ERROR functions with the `"custom"` ABI must be unsafe
|
||||
naked_asm!("")
|
||||
}
|
||||
}
|
||||
|
||||
type A7 = extern "custom" fn(); //~ ERROR "custom" ABI is experimental
|
||||
|
||||
extern "custom" {} //~ ERROR "custom" ABI is experimental
|
||||
117
tests/ui/feature-gates/feature-gate-abi-custom.stderr
Normal file
117
tests/ui/feature-gates/feature-gate-abi-custom.stderr
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
error: functions with the `"custom"` ABI must be unsafe
|
||||
--> $DIR/feature-gate-abi-custom.rs:16:5
|
||||
|
|
||||
LL | extern "custom" fn m7();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "custom" fn m7();
|
||||
| ++++++
|
||||
|
||||
error: functions with the `"custom"` ABI must be unsafe
|
||||
--> $DIR/feature-gate-abi-custom.rs:20:5
|
||||
|
|
||||
LL | extern "custom" fn dm7() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "custom" fn dm7() {
|
||||
| ++++++
|
||||
|
||||
error: functions with the `"custom"` ABI must be unsafe
|
||||
--> $DIR/feature-gate-abi-custom.rs:32:5
|
||||
|
|
||||
LL | extern "custom" fn m7() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "custom" fn m7() {
|
||||
| ++++++
|
||||
|
||||
error: functions with the `"custom"` ABI must be unsafe
|
||||
--> $DIR/feature-gate-abi-custom.rs:42:5
|
||||
|
|
||||
LL | extern "custom" fn im7() {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add the `unsafe` keyword to this definition
|
||||
|
|
||||
LL | unsafe extern "custom" fn im7() {
|
||||
| ++++++
|
||||
|
||||
error[E0658]: the extern "custom" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi-custom.rs:11:15
|
||||
|
|
||||
LL | unsafe extern "custom" fn f7() {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #140829 <https://github.com/rust-lang/rust/issues/140829> for more information
|
||||
= help: add `#![feature(abi_custom)]` 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]: the extern "custom" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi-custom.rs:16:12
|
||||
|
|
||||
LL | extern "custom" fn m7();
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #140829 <https://github.com/rust-lang/rust/issues/140829> for more information
|
||||
= help: add `#![feature(abi_custom)]` 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]: the extern "custom" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi-custom.rs:20:12
|
||||
|
|
||||
LL | extern "custom" fn dm7() {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #140829 <https://github.com/rust-lang/rust/issues/140829> for more information
|
||||
= help: add `#![feature(abi_custom)]` 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]: the extern "custom" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi-custom.rs:32:12
|
||||
|
|
||||
LL | extern "custom" fn m7() {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #140829 <https://github.com/rust-lang/rust/issues/140829> for more information
|
||||
= help: add `#![feature(abi_custom)]` 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]: the extern "custom" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi-custom.rs:42:12
|
||||
|
|
||||
LL | extern "custom" fn im7() {
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #140829 <https://github.com/rust-lang/rust/issues/140829> for more information
|
||||
= help: add `#![feature(abi_custom)]` 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]: the extern "custom" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi-custom.rs:49:18
|
||||
|
|
||||
LL | type A7 = extern "custom" fn();
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #140829 <https://github.com/rust-lang/rust/issues/140829> for more information
|
||||
= help: add `#![feature(abi_custom)]` 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]: the extern "custom" ABI is experimental and subject to change
|
||||
--> $DIR/feature-gate-abi-custom.rs:51:8
|
||||
|
|
||||
LL | extern "custom" {}
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: see issue #140829 <https://github.com/rust-lang/rust/issues/140829> for more information
|
||||
= help: add `#![feature(abi_custom)]` 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 11 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
||||
|
|
@ -5,10 +5,6 @@ macro_rules! foo {
|
|||
( $($i:ident)* ) => { $($i)+ }; //~ WARN meta-variable repeats with different Kleene operator
|
||||
}
|
||||
|
||||
#[warn(missing_fragment_specifier)]
|
||||
macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier
|
||||
//~| WARN this was previously accepted
|
||||
|
||||
#[deprecated = "reason"]
|
||||
macro_rules! deprecated {
|
||||
() => {}
|
||||
|
|
|
|||
|
|
@ -12,20 +12,6 @@ note: the lint level is defined here
|
|||
LL | #[warn(meta_variable_misuse)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: missing fragment specifier
|
||||
--> $DIR/expansion-time.rs:9:19
|
||||
|
|
||||
LL | macro_rules! m { ($i) => {} }
|
||||
| ^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/expansion-time.rs:8:8
|
||||
|
|
||||
LL | #[warn(missing_fragment_specifier)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: include macro expected single expression in source
|
||||
--> $DIR/expansion-time-include.rs:4:1
|
||||
|
|
||||
|
|
@ -33,25 +19,10 @@ LL | 2
|
|||
| ^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/expansion-time.rs:22:8
|
||||
--> $DIR/expansion-time.rs:18:8
|
||||
|
|
||||
LL | #[warn(incomplete_include)]
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: 3 warnings emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: missing fragment specifier
|
||||
--> $DIR/expansion-time.rs:9:19
|
||||
|
|
||||
LL | macro_rules! m { ($i) => {} }
|
||||
| ^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/expansion-time.rs:8:8
|
||||
|
|
||||
LL | #[warn(missing_fragment_specifier)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
warning: 2 warnings emitted
|
||||
|
||||
|
|
|
|||
|
|
@ -4,14 +4,23 @@
|
|||
// lints for changes that are not tied to an edition
|
||||
#![deny(future_incompatible)]
|
||||
|
||||
// Error since this is a `future_incompatible` lint
|
||||
macro_rules! m {
|
||||
($i) => {};
|
||||
//~^ ERROR missing fragment specifier
|
||||
enum E { V }
|
||||
|
||||
trait Tr1 {
|
||||
type V;
|
||||
fn foo() -> Self::V;
|
||||
}
|
||||
|
||||
impl Tr1 for E {
|
||||
type V = u8;
|
||||
|
||||
// Error since this is a `future_incompatible` lint
|
||||
fn foo() -> Self::V { 0 }
|
||||
//~^ ERROR ambiguous associated item
|
||||
//~| WARN this was previously accepted
|
||||
}
|
||||
|
||||
trait Tr {
|
||||
trait Tr2 {
|
||||
// Warn only since this is not a `future_incompatible` lint
|
||||
fn f(u8) {}
|
||||
//~^ WARN anonymous parameters are deprecated
|
||||
|
|
|
|||
|
|
@ -1,20 +1,5 @@
|
|||
error: missing fragment specifier
|
||||
--> $DIR/future-incompatible-lint-group.rs:9:6
|
||||
|
|
||||
LL | ($i) => {};
|
||||
| ^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/future-incompatible-lint-group.rs:5:9
|
||||
|
|
||||
LL | #![deny(future_incompatible)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]`
|
||||
|
||||
warning: anonymous parameters are deprecated and will be removed in the next edition
|
||||
--> $DIR/future-incompatible-lint-group.rs:16:10
|
||||
--> $DIR/future-incompatible-lint-group.rs:25:10
|
||||
|
|
||||
LL | fn f(u8) {}
|
||||
| ^^ help: try naming the parameter or explicitly ignoring it: `_: u8`
|
||||
|
|
@ -23,21 +8,30 @@ LL | fn f(u8) {}
|
|||
= note: for more information, see issue #41686 <https://github.com/rust-lang/rust/issues/41686>
|
||||
= note: `#[warn(anonymous_parameters)]` on by default
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
error: missing fragment specifier
|
||||
--> $DIR/future-incompatible-lint-group.rs:9:6
|
||||
error: ambiguous associated item
|
||||
--> $DIR/future-incompatible-lint-group.rs:18:17
|
||||
|
|
||||
LL | ($i) => {};
|
||||
| ^^
|
||||
LL | fn foo() -> Self::V { 0 }
|
||||
| ^^^^^^^ help: use fully-qualified syntax: `<E as Tr1>::V`
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: for more information, see issue #57644 <https://github.com/rust-lang/rust/issues/57644>
|
||||
note: `V` could refer to the variant defined here
|
||||
--> $DIR/future-incompatible-lint-group.rs:7:10
|
||||
|
|
||||
LL | enum E { V }
|
||||
| ^
|
||||
note: `V` could also refer to the associated type defined here
|
||||
--> $DIR/future-incompatible-lint-group.rs:10:5
|
||||
|
|
||||
LL | type V;
|
||||
| ^^^^^^
|
||||
note: the lint level is defined here
|
||||
--> $DIR/future-incompatible-lint-group.rs:5:9
|
||||
|
|
||||
LL | #![deny(future_incompatible)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
= note: `#[deny(missing_fragment_specifier)]` implied by `#[deny(future_incompatible)]`
|
||||
= note: `#[deny(ambiguous_associated_items)]` implied by `#[deny(future_incompatible)]`
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#![allow(unused)]
|
||||
|
||||
macro_rules! m { ($i) => {} }
|
||||
//~^ ERROR missing fragment specifier
|
||||
//~| WARN previously accepted
|
||||
macro_rules! m {
|
||||
($i) => {}; //~ ERROR missing fragment specifier
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -1,23 +1,15 @@
|
|||
error: missing fragment specifier
|
||||
--> $DIR/issue-39404.rs:3:19
|
||||
--> $DIR/issue-39404.rs:4:6
|
||||
|
|
||||
LL | macro_rules! m { ($i) => {} }
|
||||
| ^^
|
||||
LL | ($i) => {};
|
||||
| ^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
= note: fragment specifiers must be provided
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
LL | ($i:spec) => {};
|
||||
| +++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
error: missing fragment specifier
|
||||
--> $DIR/issue-39404.rs:3:19
|
||||
|
|
||||
LL | macro_rules! m { ($i) => {} }
|
||||
| ^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,6 @@ macro_rules! test {
|
|||
//~^ ERROR missing fragment
|
||||
//~| ERROR missing fragment
|
||||
//~| ERROR missing fragment
|
||||
//~| WARN this was previously accepted
|
||||
//~| WARN this was previously accepted
|
||||
()
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,18 +1,15 @@
|
|||
error: missing fragment specifier
|
||||
--> $DIR/macro-match-nonterminal.rs:2:6
|
||||
|
|
||||
LL | ($a, $b) => {
|
||||
| ^^
|
||||
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-match-nonterminal.rs:2:6
|
||||
|
|
||||
LL | ($a, $b) => {
|
||||
| ^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
= note: fragment specifiers must be provided
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
LL | ($a:spec, $b) => {
|
||||
| +++++
|
||||
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-match-nonterminal.rs:2:10
|
||||
|
|
@ -20,30 +17,18 @@ error: missing fragment specifier
|
|||
LL | ($a, $b) => {
|
||||
| ^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: fragment specifiers must be provided
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
LL | ($a, $b:spec) => {
|
||||
| +++++
|
||||
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-match-nonterminal.rs:2:6
|
||||
|
|
||||
LL | ($a, $b) => {
|
||||
| ^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-match-nonterminal.rs:2:6
|
||||
|
|
||||
LL | ($a, $b) => {
|
||||
| ^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
|
||||
Future breakage diagnostic:
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-match-nonterminal.rs:2:10
|
||||
|
|
||||
LL | ($a, $b) => {
|
||||
| ^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
|
||||
|
|
|
|||
|
|
@ -1,10 +1,8 @@
|
|||
//@ compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
|
||||
macro_rules! m {
|
||||
($name) => {}
|
||||
//~^ ERROR missing fragment
|
||||
//~| ERROR missing fragment
|
||||
//~| WARN this was previously accepted
|
||||
($name) => {}; //~ ERROR missing fragment
|
||||
//~| ERROR missing fragment
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,29 +1,21 @@
|
|||
error: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment-deduplication.rs:4:6
|
||||
|
|
||||
LL | ($name) => {}
|
||||
LL | ($name) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= note: fragment specifiers must be provided
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
LL | ($name:spec) => {};
|
||||
| +++++
|
||||
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment-deduplication.rs:4:6
|
||||
|
|
||||
LL | ($name) => {}
|
||||
LL | ($name) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment-deduplication.rs:4:6
|
||||
|
|
||||
LL | ($name) => {}
|
||||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
|
||||
|
|
|
|||
|
|
@ -1,85 +0,0 @@
|
|||
error: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:8:20
|
||||
|
|
||||
LL | ( $( any_token $field_rust_type )* ) => {};
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:8:20
|
||||
|
|
||||
LL | ( $( any_token $field_rust_type )* ) => {};
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/macro-missing-fragment.rs:5:9
|
||||
|
|
||||
LL | #![warn(missing_fragment_specifier)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:18:7
|
||||
|
|
||||
LL | ( $name ) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
|
||||
warning: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:25:7
|
||||
|
|
||||
LL | ( $name ) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
|
||||
error: aborting due to 1 previous error; 3 warnings emitted
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
warning: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:8:20
|
||||
|
|
||||
LL | ( $( any_token $field_rust_type )* ) => {};
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/macro-missing-fragment.rs:5:9
|
||||
|
|
||||
LL | #![warn(missing_fragment_specifier)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:18:7
|
||||
|
|
||||
LL | ( $name ) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/macro-missing-fragment.rs:5:9
|
||||
|
|
||||
LL | #![warn(missing_fragment_specifier)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
Future breakage diagnostic:
|
||||
warning: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:25:7
|
||||
|
|
||||
LL | ( $name ) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/macro-missing-fragment.rs:5:9
|
||||
|
|
||||
LL | #![warn(missing_fragment_specifier)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
@ -1,31 +1,17 @@
|
|||
//@ revisions: e2015 e2024
|
||||
//@[e2015] edition:2015
|
||||
//@[e2024] edition:2024
|
||||
|
||||
#![warn(missing_fragment_specifier)]
|
||||
//! Ensure that macros produce an error if fragment specifiers are missing.
|
||||
|
||||
macro_rules! used_arm {
|
||||
( $( any_token $field_rust_type )* ) => {};
|
||||
//[e2015]~^ ERROR missing fragment
|
||||
//[e2015]~| WARN missing fragment
|
||||
//[e2015]~| WARN this was previously accepted
|
||||
//[e2024]~^^^^ ERROR missing fragment
|
||||
//[e2024]~| ERROR missing fragment
|
||||
( $( any_token $field_rust_type )* ) => {}; //~ ERROR missing fragment
|
||||
//~| ERROR missing fragment
|
||||
}
|
||||
|
||||
macro_rules! used_macro_unused_arm {
|
||||
() => {};
|
||||
( $name ) => {};
|
||||
//[e2015]~^ WARN missing fragment
|
||||
//[e2015]~| WARN this was previously accepted
|
||||
//[e2024]~^^^ ERROR missing fragment
|
||||
( $name ) => {}; //~ ERROR missing fragment
|
||||
}
|
||||
|
||||
macro_rules! unused_macro {
|
||||
( $name ) => {};
|
||||
//[e2015]~^ WARN missing fragment
|
||||
//[e2015]~| WARN this was previously accepted
|
||||
//[e2024]~^^^ ERROR missing fragment
|
||||
( $name ) => {}; //~ ERROR missing fragment
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
error: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:8:20
|
||||
--> $DIR/macro-missing-fragment.rs:4:20
|
||||
|
|
||||
LL | ( $( any_token $field_rust_type )* ) => {};
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: fragment specifiers must be specified in the 2024 edition
|
||||
= note: fragment specifiers must be provided
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
|
|
@ -12,12 +12,12 @@ LL | ( $( any_token $field_rust_type:spec )* ) => {};
|
|||
| +++++
|
||||
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:18:7
|
||||
--> $DIR/macro-missing-fragment.rs:10:7
|
||||
|
|
||||
LL | ( $name ) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= note: fragment specifiers must be specified in the 2024 edition
|
||||
= note: fragment specifiers must be provided
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
|
|
@ -25,12 +25,12 @@ LL | ( $name:spec ) => {};
|
|||
| +++++
|
||||
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:25:7
|
||||
--> $DIR/macro-missing-fragment.rs:14:7
|
||||
|
|
||||
LL | ( $name ) => {};
|
||||
| ^^^^^
|
||||
|
|
||||
= note: fragment specifiers must be specified in the 2024 edition
|
||||
= note: fragment specifiers must be provided
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
|
|
@ -38,7 +38,7 @@ LL | ( $name:spec ) => {};
|
|||
| +++++
|
||||
|
||||
error: missing fragment specifier
|
||||
--> $DIR/macro-missing-fragment.rs:8:20
|
||||
--> $DIR/macro-missing-fragment.rs:4:20
|
||||
|
|
||||
LL | ( $( any_token $field_rust_type )* ) => {};
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
@ -2,7 +2,6 @@ macro_rules! foo {
|
|||
{ $+ } => { //~ ERROR expected identifier, found `+`
|
||||
//~^ ERROR missing fragment specifier
|
||||
//~| ERROR missing fragment specifier
|
||||
//~| WARN this was previously accepted
|
||||
$(x)(y) //~ ERROR expected one of: `*`, `+`, or `?`
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ LL | { $+ } => {
|
|||
| ^
|
||||
|
||||
error: expected one of: `*`, `+`, or `?`
|
||||
--> $DIR/issue-33569.rs:6:13
|
||||
--> $DIR/issue-33569.rs:5:13
|
||||
|
|
||||
LL | $(x)(y)
|
||||
| ^^^
|
||||
|
|
@ -15,27 +15,19 @@ error: missing fragment specifier
|
|||
|
|
||||
LL | { $+ } => {
|
||||
| ^
|
||||
|
|
||||
= note: fragment specifiers must be provided
|
||||
= help: valid fragment specifiers are `ident`, `block`, `stmt`, `expr`, `pat`, `ty`, `lifetime`, `literal`, `path`, `meta`, `tt`, `item` and `vis`, along with `expr_2021` and `pat_param` for edition compatibility
|
||||
help: try adding a specifier here
|
||||
|
|
||||
LL | { $+:spec } => {
|
||||
| +++++
|
||||
|
||||
error: missing fragment specifier
|
||||
--> $DIR/issue-33569.rs:2:8
|
||||
|
|
||||
LL | { $+ } => {
|
||||
| ^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
Future incompatibility report: Future breakage diagnostic:
|
||||
error: missing fragment specifier
|
||||
--> $DIR/issue-33569.rs:2:8
|
||||
|
|
||||
LL | { $+ } => {
|
||||
| ^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #40107 <https://github.com/rust-lang/rust/issues/40107>
|
||||
= note: `#[deny(missing_fragment_specifier)]` on by default
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ avr-interrupt
|
|||
avr-non-blocking-interrupt
|
||||
cdecl
|
||||
cdecl-unwind
|
||||
custom
|
||||
efiapi
|
||||
fastcall
|
||||
fastcall-unwind
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
warning: target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `x86-retpoline` target modifier flag instead
|
||||
|
|
||||
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
warning: target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `retpoline-external-thunk` target modifier flag instead
|
||||
|
|
||||
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
warning: target feature `retpoline-indirect-branches` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead
|
||||
|
|
||||
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
warning: target feature `retpoline-indirect-calls` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead
|
||||
|
|
||||
= note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= note: for more information, see issue #116344 <https://github.com/rust-lang/rust/issues/116344>
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
23
tests/ui/target-feature/retpoline-target-feature-flag.rs
Normal file
23
tests/ui/target-feature/retpoline-target-feature-flag.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
//@ revisions: by_flag by_feature1 by_feature2 by_feature3
|
||||
//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib
|
||||
//@ needs-llvm-components: x86
|
||||
//@ [by_flag]compile-flags: -Zretpoline
|
||||
|
||||
//@ [by_feature1]compile-flags: -Ctarget-feature=+retpoline-external-thunk
|
||||
//@ [by_feature2]compile-flags: -Ctarget-feature=+retpoline-indirect-branches
|
||||
//@ [by_feature3]compile-flags: -Ctarget-feature=+retpoline-indirect-calls
|
||||
//@ [by_flag]build-pass
|
||||
// For now this is just a warning.
|
||||
//@ [by_feature1]build-pass
|
||||
//@ [by_feature2]build-pass
|
||||
//@ [by_feature3]build-pass
|
||||
#![feature(no_core, lang_items)]
|
||||
#![no_std]
|
||||
#![no_core]
|
||||
|
||||
#[lang = "sized"]
|
||||
pub trait Sized {}
|
||||
|
||||
//[by_feature1]~? WARN target feature `retpoline-external-thunk` cannot be enabled with `-Ctarget-feature`: use `retpoline-external-thunk` target modifier flag instead
|
||||
//[by_feature2]~? WARN target feature `retpoline-indirect-branches` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead
|
||||
//[by_feature3]~? WARN target feature `retpoline-indirect-calls` cannot be enabled with `-Ctarget-feature`: use `retpoline` target modifier flag instead
|
||||
Loading…
Add table
Add a link
Reference in a new issue