-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Reject unsupported extern "{abi}"
s consistently in all positions
#142134
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
19eb44c
f9fa3b1
0b35295
780a4c7
b8f74cf
515277d
f2c6e27
3113bce
4ee93d5
7f2b672
4ca0bcc
0feba60
4306efa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
use std::cell::LazyCell; | ||
use std::ops::ControlFlow; | ||
|
||
use rustc_abi::FieldIdx; | ||
use rustc_abi::{ExternAbi, FieldIdx}; | ||
use rustc_attr_data_structures::ReprAttr::ReprPacked; | ||
use rustc_data_structures::unord::{UnordMap, UnordSet}; | ||
use rustc_errors::codes::*; | ||
|
@@ -12,7 +12,6 @@ use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; | |
use rustc_infer::traits::{Obligation, ObligationCauseCode}; | ||
use rustc_lint_defs::builtin::{ | ||
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_CALLING_CONVENTIONS, | ||
UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, | ||
}; | ||
use rustc_middle::hir::nested_filter; | ||
use rustc_middle::middle::resolve_bound_vars::ResolvedArg; | ||
|
@@ -37,54 +36,32 @@ use {rustc_attr_data_structures as attrs, rustc_hir as hir}; | |
use super::compare_impl_item::check_type_bounds; | ||
use super::*; | ||
|
||
fn add_abi_diag_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) { | ||
if let ExternAbi::Cdecl { unwind } = abi { | ||
let c_abi = ExternAbi::C { unwind }; | ||
diag.help(format!("use `extern {c_abi}` instead",)); | ||
} else if let ExternAbi::Stdcall { unwind } = abi { | ||
let c_abi = ExternAbi::C { unwind }; | ||
let system_abi = ExternAbi::System { unwind }; | ||
diag.help(format!( | ||
"if you need `extern {abi}` on win32 and `extern {c_abi}` everywhere else, \ | ||
use `extern {system_abi}`" | ||
)); | ||
} | ||
} | ||
|
||
pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I understand this PR correctly, we still do not call this function for trait declarations. This means that UNSUPPORTED_CALLING_CONVENTIONS is not emitted for them, and so moving cdecl and friends to How hard would it be to find a place in hir_analysis (or wherever) to call this on trait declarations, too? |
||
// FIXME: this should be checked earlier, e.g. in `rustc_ast_lowering`, to fix | ||
// things like #86232. | ||
fn add_help<T: EmissionGuarantee>(abi: ExternAbi, diag: &mut Diag<'_, T>) { | ||
if let ExternAbi::Cdecl { unwind } = abi { | ||
let c_abi = ExternAbi::C { unwind }; | ||
diag.help(format!("use `extern {c_abi}` instead",)); | ||
} else if let ExternAbi::Stdcall { unwind } = abi { | ||
let c_abi = ExternAbi::C { unwind }; | ||
let system_abi = ExternAbi::System { unwind }; | ||
diag.help(format!( | ||
"if you need `extern {abi}` on win32 and `extern {c_abi}` everywhere else, \ | ||
use `extern {system_abi}`" | ||
)); | ||
} | ||
} | ||
|
||
match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) { | ||
AbiMapping::Direct(..) => (), | ||
AbiMapping::Invalid => { | ||
let mut err = struct_span_code_err!( | ||
tcx.dcx(), | ||
span, | ||
E0570, | ||
"`{abi}` is not a supported ABI for the current target", | ||
); | ||
add_help(abi, &mut err); | ||
err.emit(); | ||
} | ||
// already erred in rustc_ast_lowering | ||
AbiMapping::Invalid => (), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given the history of leaky checks, maybe add a delay_span_bug here? |
||
AbiMapping::Deprecated(..) => { | ||
tcx.node_span_lint(UNSUPPORTED_CALLING_CONVENTIONS, hir_id, span, |lint| { | ||
lint.primary_message("use of calling convention not supported on this target"); | ||
add_help(abi, lint); | ||
}); | ||
} | ||
} | ||
} | ||
|
||
pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi) { | ||
// This is always an FCW, even for `AbiMapping::Invalid`, since we started linting later than | ||
// in `check_abi` above. | ||
match AbiMap::from_target(&tcx.sess.target).canonize_abi(abi, false) { | ||
AbiMapping::Direct(..) => (), | ||
AbiMapping::Deprecated(..) | AbiMapping::Invalid => { | ||
tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| { | ||
lint.primary_message(format!( | ||
"the calling convention {abi} is not supported on this target" | ||
)); | ||
add_abi_diag_help(abi, lint); | ||
}); | ||
} | ||
} | ||
|
@@ -845,6 +822,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) { | |
let hir::ItemKind::ForeignMod { abi, items } = it.kind else { | ||
return; | ||
}; | ||
|
||
check_abi(tcx, it.hir_id(), it.span, abi); | ||
|
||
for item in items { | ||
|
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#![feature(abi_vectorcall)] | ||
//@ only-x86_64 | ||
|
||
//@ is "$.index[?(@.name=='AbiVectorcall')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall\""' | ||
pub type AbiVectorcall = extern "vectorcall" fn(); | ||
|
||
//@ is "$.index[?(@.name=='AbiVectorcallUnwind')].inner.type_alias.type.function_pointer.header.abi.Other" '"\"vectorcall-unwind\""' | ||
pub type AbiVectorcallUnwind = extern "vectorcall-unwind" fn(); | ||
|
||
//@ has "$.index[?(@.name=='Foo')]" | ||
pub struct Foo; | ||
|
||
impl Foo { | ||
//@ is "$.index[?(@.name=='abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' | ||
pub extern "vectorcall" fn abi_vectorcall() {} | ||
|
||
//@ is "$.index[?(@.name=='abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' | ||
pub extern "vectorcall-unwind" fn abi_vectorcall_unwind() {} | ||
} | ||
|
||
pub trait Bar { | ||
//@ is "$.index[?(@.name=='trait_abi_vectorcall')].inner.function.header.abi.Other" '"\"vectorcall\""' | ||
extern "vectorcall" fn trait_abi_vectorcall() {} | ||
|
||
//@ is "$.index[?(@.name=='trait_abi_vectorcall_unwind')].inner.function.header.abi.Other" '"\"vectorcall-unwind\""' | ||
extern "vectorcall-unwind" fn trait_abi_vectorcall_unwind() {} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All these tests seem to assume that "gpu-kernel" is not a valid ABI. But that's target-specific, so this will fail when the test suite is run on a GPU target, right? Like the other unsupported ABI tests, I think this should use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hm, I mean technically GPUs shouldn't ever be hosts so I wouldn't think we would build tests for them, but then Aaron Hsu's codfns compiler exists so maybe I shouldn't think that. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#![feature(abi_gpu_kernel)] | ||
// Check we error before unsupported ABIs reach codegen stages. | ||
|
||
fn main() { | ||
let a = unsafe { core::mem::transmute::<usize, extern "gpu-kernel" fn(i32)>(4) }(2); | ||
//~^ ERROR E0570 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target | ||
--> $DIR/unsupported-abi-transmute.rs:5:59 | ||
| | ||
LL | let a = unsafe { core::mem::transmute::<usize, extern "gpu-kernel" fn(i32)>(4) }(2); | ||
| ^^^^^^^^^^^^ | ||
|
||
error: aborting due to 1 previous error | ||
|
||
For more information about this error, try `rustc --explain E0570`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
//@ compile-flags: --crate-type=lib | ||
//@ edition: 2018 | ||
#![feature(abi_gpu_kernel)] | ||
struct Test; | ||
|
||
impl Test { | ||
pub extern "gpu-kernel" fn test(val: &str) {} | ||
//~^ ERROR [E0570] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Error codes are pretty meaningless, making the test file hard to read. IMO it'd be better to have a snippet of the error message in the test file here. |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target | ||
--> $DIR/unsupported-extern-abi-in-type-impl.rs:7:16 | ||
| | ||
LL | pub extern "gpu-kernel" fn test(val: &str) {} | ||
| ^^^^^^^^^^^^ | ||
|
||
error: aborting due to 1 previous error | ||
|
||
For more information about this error, try `rustc --explain E0570`. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
//@ compile-flags: --crate-type=lib | ||
|
||
#![feature(abi_gpu_kernel)] | ||
|
||
trait T { | ||
extern "gpu-kernel" fn mu(); | ||
//~^ ERROR[E0570] | ||
} | ||
|
||
type TAU = extern "gpu-kernel" fn(); | ||
//~^ ERROR[E0570] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target | ||
--> $DIR/unsupported-trait-decl.rs:6:12 | ||
| | ||
LL | extern "gpu-kernel" fn mu(); | ||
| ^^^^^^^^^^^^ | ||
|
||
error[E0570]: `"gpu-kernel"` is not a supported ABI for the current target | ||
--> $DIR/unsupported-trait-decl.rs:10:19 | ||
| | ||
LL | type TAU = extern "gpu-kernel" fn(); | ||
| ^^^^^^^^^^^^ | ||
|
||
error: aborting due to 2 previous errors | ||
|
||
For more information about this error, try `rustc --explain E0570`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would we emit a stability error on top of the hard error? Usually we avoid showing more than one error for the same thing if possible.