Move FFI attribute validation to check_attr
This commit is contained in:
parent
3984bc5833
commit
05b7cc8370
@ -85,55 +85,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
||||
} else if attr.has_name(sym::rustc_allocator) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
|
||||
} else if attr.has_name(sym::ffi_returns_twice) {
|
||||
if tcx.is_foreign_item(did) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
|
||||
} else {
|
||||
// `#[ffi_returns_twice]` is only allowed `extern fn`s.
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0724,
|
||||
"`#[ffi_returns_twice]` may only be used on foreign functions"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
|
||||
} else if attr.has_name(sym::ffi_pure) {
|
||||
if tcx.is_foreign_item(did) {
|
||||
if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
|
||||
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0757,
|
||||
"`#[ffi_const]` function cannot be `#[ffi_pure]`"
|
||||
)
|
||||
.emit();
|
||||
} else {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
|
||||
}
|
||||
} else {
|
||||
// `#[ffi_pure]` is only allowed on foreign functions
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0755,
|
||||
"`#[ffi_pure]` may only be used on foreign functions"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_PURE;
|
||||
} else if attr.has_name(sym::ffi_const) {
|
||||
if tcx.is_foreign_item(did) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
|
||||
} else {
|
||||
// `#[ffi_const]` is only allowed on foreign functions
|
||||
struct_span_err!(
|
||||
tcx.sess,
|
||||
attr.span,
|
||||
E0756,
|
||||
"`#[ffi_const]` may only be used on foreign functions"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
|
||||
} else if attr.has_name(sym::rustc_nounwind) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
|
||||
} else if attr.has_name(sym::rustc_reallocator) {
|
||||
|
@ -182,6 +182,18 @@ passes_has_incoherent_inherent_impl =
|
||||
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
|
||||
.label = only adts, extern types and traits are supported
|
||||
|
||||
passes_both_ffi_const_and_pure =
|
||||
`#[ffi_const]` function cannot be `#[ffi_pure]`
|
||||
|
||||
passes_ffi_pure_invalid_target =
|
||||
`#[ffi_pure]` may only be used on foreign functions
|
||||
|
||||
passes_ffi_const_invalid_target =
|
||||
`#[ffi_const]` may only be used on foreign functions
|
||||
|
||||
passes_ffi_returns_twice_invalid_target =
|
||||
`#[ffi_returns_twice]` may only be used on foreign functions
|
||||
|
||||
passes_must_use_async =
|
||||
`must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
|
||||
.label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
|
||||
|
@ -150,6 +150,9 @@ fn check_attributes(
|
||||
sym::rustc_has_incoherent_inherent_impls => {
|
||||
self.check_has_incoherent_inherent_impls(&attr, span, target)
|
||||
}
|
||||
sym::ffi_pure => self.check_ffi_pure(hir_id, attr.span, attrs),
|
||||
sym::ffi_const => self.check_ffi_const(hir_id, attr.span),
|
||||
sym::ffi_returns_twice => self.check_ffi_returns_twice(hir_id, attr.span),
|
||||
sym::rustc_const_unstable
|
||||
| sym::rustc_const_stable
|
||||
| sym::unstable
|
||||
@ -1171,6 +1174,38 @@ fn check_has_incoherent_inherent_impls(
|
||||
}
|
||||
}
|
||||
|
||||
fn check_ffi_pure(&self, hir_id: HirId, attr_span: Span, attrs: &[Attribute]) -> bool {
|
||||
if !self.tcx.is_foreign_item(self.tcx.hir().local_def_id(hir_id)) {
|
||||
self.tcx.sess.emit_err(errors::FfiPureInvalidTarget { attr_span });
|
||||
return false;
|
||||
}
|
||||
if attrs.iter().any(|a| a.has_name(sym::ffi_const)) {
|
||||
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
|
||||
self.tcx.sess.emit_err(errors::BothFfiConstAndPure { attr_span });
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
fn check_ffi_const(&self, hir_id: HirId, attr_span: Span) -> bool {
|
||||
if self.tcx.is_foreign_item(self.tcx.hir().local_def_id(hir_id)) {
|
||||
true
|
||||
} else {
|
||||
self.tcx.sess.emit_err(errors::FfiConstInvalidTarget { attr_span });
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fn check_ffi_returns_twice(&self, hir_id: HirId, attr_span: Span) -> bool {
|
||||
if self.tcx.is_foreign_item(self.tcx.hir().local_def_id(hir_id)) {
|
||||
true
|
||||
} else {
|
||||
self.tcx.sess.emit_err(errors::FfiReturnsTwiceInvalidTarget { attr_span });
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Warns against some misuses of `#[must_use]`
|
||||
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
|
||||
if !matches!(
|
||||
|
@ -347,6 +347,34 @@ pub struct HasIncoherentInherentImpl {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_both_ffi_const_and_pure, code = "E0757")]
|
||||
pub struct BothFfiConstAndPure {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_ffi_pure_invalid_target, code = "E0755")]
|
||||
pub struct FfiPureInvalidTarget {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_ffi_const_invalid_target, code = "E0756")]
|
||||
pub struct FfiConstInvalidTarget {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(passes_ffi_returns_twice_invalid_target, code = "E0724")]
|
||||
pub struct FfiReturnsTwiceInvalidTarget {
|
||||
#[primary_span]
|
||||
pub attr_span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_must_use_async)]
|
||||
pub struct MustUseAsync {
|
||||
|
Loading…
Reference in New Issue
Block a user