Move FFI attribute validation to check_attr
This commit is contained in:
parent
3984bc5833
commit
05b7cc8370
4 changed files with 78 additions and 47 deletions
|
@ -85,55 +85,11 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
|
||||||
} else if attr.has_name(sym::rustc_allocator) {
|
} else if attr.has_name(sym::rustc_allocator) {
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR;
|
||||||
} else if attr.has_name(sym::ffi_returns_twice) {
|
} else if attr.has_name(sym::ffi_returns_twice) {
|
||||||
if tcx.is_foreign_item(did) {
|
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_RETURNS_TWICE;
|
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();
|
|
||||||
}
|
|
||||||
} else if attr.has_name(sym::ffi_pure) {
|
} 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;
|
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();
|
|
||||||
}
|
|
||||||
} else if attr.has_name(sym::ffi_const) {
|
} else if attr.has_name(sym::ffi_const) {
|
||||||
if tcx.is_foreign_item(did) {
|
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FFI_CONST;
|
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();
|
|
||||||
}
|
|
||||||
} else if attr.has_name(sym::rustc_nounwind) {
|
} else if attr.has_name(sym::rustc_nounwind) {
|
||||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
|
codegen_fn_attrs.flags |= CodegenFnAttrFlags::NEVER_UNWIND;
|
||||||
} else if attr.has_name(sym::rustc_reallocator) {
|
} 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.
|
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits.
|
||||||
.label = only adts, extern types and traits are supported
|
.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 =
|
passes_must_use_async =
|
||||||
`must_use` attribute on `async` functions applies to the anonymous `Future` returned by the function, not the value within
|
`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`
|
.label = this attribute does nothing, the `Future`s returned by async functions are already `must_use`
|
||||||
|
|
|
@ -150,6 +150,9 @@ impl CheckAttrVisitor<'_> {
|
||||||
sym::rustc_has_incoherent_inherent_impls => {
|
sym::rustc_has_incoherent_inherent_impls => {
|
||||||
self.check_has_incoherent_inherent_impls(&attr, span, target)
|
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_unstable
|
||||||
| sym::rustc_const_stable
|
| sym::rustc_const_stable
|
||||||
| sym::unstable
|
| sym::unstable
|
||||||
|
@ -1171,6 +1174,38 @@ impl CheckAttrVisitor<'_> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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]`
|
/// Warns against some misuses of `#[must_use]`
|
||||||
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
|
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) -> bool {
|
||||||
if !matches!(
|
if !matches!(
|
||||||
|
|
|
@ -347,6 +347,34 @@ pub struct HasIncoherentInherentImpl {
|
||||||
pub span: Span,
|
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)]
|
#[derive(LintDiagnostic)]
|
||||||
#[diag(passes_must_use_async)]
|
#[diag(passes_must_use_async)]
|
||||||
pub struct MustUseAsync {
|
pub struct MustUseAsync {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue