diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_ast_passes/Cargo.toml | 1 | ||||
| -rw-r--r-- | compiler/rustc_ast_passes/messages.ftl | 23 | ||||
| -rw-r--r-- | compiler/rustc_ast_passes/src/ast_validation.rs | 87 | ||||
| -rw-r--r-- | compiler/rustc_ast_passes/src/errors.rs | 22 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/messages.ftl | 2 |
5 files changed, 104 insertions, 31 deletions
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml index c738cb2aa2f..1940628b44a 100644 --- a/compiler/rustc_ast_passes/Cargo.toml +++ b/compiler/rustc_ast_passes/Cargo.toml @@ -18,5 +18,6 @@ rustc_macros = { path = "../rustc_macros" } rustc_parse = { path = "../rustc_parse" } rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } thin-vec = "0.2.12" # tidy-alphabetical-end diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 9a267501230..6eddce7b590 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -1,20 +1,25 @@ -ast_passes_abi_custom_coroutine = - functions with the `"custom"` ABI cannot be `{$coroutine_kind_str}` +ast_passes_abi_cannot_be_coroutine = + functions with the {$abi} 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 + 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 + functions with the "custom" ABI must be unsafe .suggestion = add the `unsafe` keyword to this definition +ast_passes_abi_must_not_have_parameters_or_return_type= + invalid signature for `extern {$abi}` function + .note = functions with the {$abi} ABI cannot have any parameters or return type + .suggestion = remove the parameters and return type + +ast_passes_abi_must_not_have_return_type= + invalid signature for `extern {$abi}` function + .note = functions with the "custom" ABI cannot have a return type + .help = remove the return type + ast_passes_assoc_const_without_body = associated constant in `impl` without body .suggestion = provide a definition for the constant diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index b69a91e2f5f..da248251203 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -21,7 +21,7 @@ use std::ops::{Deref, DerefMut}; use std::str::FromStr; use itertools::{Either, Itertools}; -use rustc_abi::ExternAbi; +use rustc_abi::{CanonAbi, ExternAbi, InterruptKind}; use rustc_ast::ptr::P; use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list}; use rustc_ast::*; @@ -37,6 +37,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::lint::{BuiltinLintDiag, LintBuffer}; use rustc_span::{Ident, Span, kw, sym}; +use rustc_target::spec::{AbiMap, AbiMapping}; use thin_vec::thin_vec; use crate::errors::{self, TildeConstReason}; @@ -365,31 +366,77 @@ 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) { + /// Check that the signature of this function does not violate the constraints of its ABI. + fn check_extern_fn_signature(&self, abi: ExternAbi, ctxt: FnCtxt, ident: &Ident, sig: &FnSig) { + match AbiMap::from_target(&self.sess.target).canonize_abi(abi, false) { + AbiMapping::Direct(canon_abi) | AbiMapping::Deprecated(canon_abi) => { + match canon_abi { + CanonAbi::C + | CanonAbi::Rust + | CanonAbi::RustCold + | CanonAbi::Arm(_) + | CanonAbi::GpuKernel + | CanonAbi::X86(_) => { /* nothing to check */ } + + CanonAbi::Custom => { + // An `extern "custom"` function must be unsafe. + self.reject_safe_fn(abi, ctxt, sig); + + // An `extern "custom"` function cannot be `async` and/or `gen`. + self.reject_coroutine(abi, sig); + + // An `extern "custom"` function must have type `fn()`. + self.reject_params_or_return(abi, ident, sig); + } + + CanonAbi::Interrupt(interrupt_kind) => { + // An interrupt handler cannot be `async` and/or `gen`. + self.reject_coroutine(abi, sig); + + if let InterruptKind::X86 = interrupt_kind { + // "x86-interrupt" is special because it does have arguments. + // FIXME(workingjubilee): properly lint on acceptable input types. + if let FnRetTy::Ty(ref ret_ty) = sig.decl.output { + self.dcx().emit_err(errors::AbiMustNotHaveReturnType { + span: ret_ty.span, + abi, + }); + } + } else { + // An `extern "interrupt"` function must have type `fn()`. + self.reject_params_or_return(abi, ident, sig); + } + } + } + } + AbiMapping::Invalid => { /* ignore */ } + } + } + + fn reject_safe_fn(&self, abi: ExternAbi, ctxt: FnCtxt, 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)); + let source_map = self.sess.psess.source_map(); + let safe_span = 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 { + dcx.emit_err(errors::AbiCustomSafeFunction { span: sig.span, + abi, unsafe_span: sig.span.shrink_to_lo(), }); } }, } + } - // An `extern "custom"` function cannot be `async` and/or `gen`. + fn reject_coroutine(&self, abi: ExternAbi, sig: &FnSig) { if let Some(coroutine_kind) = sig.header.coroutine_kind { let coroutine_kind_span = self .sess @@ -397,14 +444,16 @@ impl<'a> AstValidator<'a> { .source_map() .span_until_non_whitespace(coroutine_kind.span().to(sig.span)); - self.dcx().emit_err(errors::AbiCustomCoroutine { + self.dcx().emit_err(errors::AbiCannotBeCoroutine { span: sig.span, + abi, coroutine_kind_span, coroutine_kind_str: coroutine_kind.as_str(), }); } + } - // An `extern "custom"` function must not have any parameters or return type. + fn reject_params_or_return(&self, abi: ExternAbi, ident: &Ident, sig: &FnSig) { 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); @@ -415,11 +464,12 @@ impl<'a> AstValidator<'a> { 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 { + self.dcx().emit_err(errors::AbiMustNotHaveParametersOrReturnType { spans, symbol: ident.name, suggestion_span, padding, + abi, }); } } @@ -1199,9 +1249,12 @@ 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); - } + self.check_extern_fn_signature( + self.extern_mod_abi.unwrap_or(ExternAbi::FALLBACK), + FnCtxt::Foreign, + ident, + sig, + ); } ForeignItemKind::TyAlias(box TyAlias { defaultness, @@ -1411,9 +1464,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { 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()) + && let Ok(abi) = ExternAbi::from_str(str_lit.symbol.as_str()) { - self.check_custom_abi(ctxt, &fun.ident, &fun.sig); + self.check_extern_fn_signature(abi, ctxt, &fun.ident, &fun.sig); } self.check_c_variadic_type(fk); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index c437e62f4d3..d387a4a310e 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,5 +1,6 @@ //! Errors emitted by ast_passes. +use rustc_abi::ExternAbi; use rustc_ast::ParamKindOrd; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, EmissionGuarantee, Subdiagnostic}; @@ -845,6 +846,7 @@ pub(crate) struct AbiCustomSafeForeignFunction { pub(crate) struct AbiCustomSafeFunction { #[primary_span] pub span: Span, + pub abi: ExternAbi, #[suggestion( ast_passes_suggestion, @@ -856,10 +858,11 @@ pub(crate) struct AbiCustomSafeFunction { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_coroutine)] -pub(crate) struct AbiCustomCoroutine { +#[diag(ast_passes_abi_cannot_be_coroutine)] +pub(crate) struct AbiCannotBeCoroutine { #[primary_span] pub span: Span, + pub abi: ExternAbi, #[suggestion( ast_passes_suggestion, @@ -872,11 +875,12 @@ pub(crate) struct AbiCustomCoroutine { } #[derive(Diagnostic)] -#[diag(ast_passes_abi_custom_invalid_signature)] +#[diag(ast_passes_abi_must_not_have_parameters_or_return_type)] #[note] -pub(crate) struct AbiCustomInvalidSignature { +pub(crate) struct AbiMustNotHaveParametersOrReturnType { #[primary_span] pub spans: Vec<Span>, + pub abi: ExternAbi, #[suggestion( ast_passes_suggestion, @@ -888,3 +892,13 @@ pub(crate) struct AbiCustomInvalidSignature { pub symbol: Symbol, pub padding: &'static str, } + +#[derive(Diagnostic)] +#[diag(ast_passes_abi_must_not_have_return_type)] +#[note] +pub(crate) struct AbiMustNotHaveReturnType { + #[primary_span] + #[help] + pub span: Span, + pub abi: ExternAbi, +} diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index bd2252c1bf8..8c43d10b9e4 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -1,5 +1,5 @@ hir_analysis_abi_custom_clothed_function = - items with the `"custom"` ABI can only be declared externally or defined via naked functions + 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}` |
