Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 31 additions & 10 deletions compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ use super::util::parse_single_integer;
use crate::attributes::AttributeSafety;
use crate::attributes::cfg::parse_cfg_entry;
use crate::session_diagnostics::{
AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic,
ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier,
InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple, LinkOrdinalOutOfRange,
LinkRequiresName, MultipleModifiers, NullOnLinkName, NullOnLinkSection, RawDylibOnlyWindows,
WholeArchiveNeedsStatic,
AsNeededCompatibility, BothFfiConstAndPure, BundleNeedsStatic, EmptyLinkName,
ExportSymbolsNeedsStatic, ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink,
InvalidLinkModifier, InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple,
LinkOrdinalOutOfRange, LinkRequiresName, MultipleModifiers, NullOnLinkName, NullOnLinkSection,
RawDylibOnlyWindows, UnusedMultiple, WholeArchiveNeedsStatic,
};

pub(crate) struct LinkNameParser;
Expand Down Expand Up @@ -563,16 +563,37 @@ impl NoArgsAttributeParser for FfiConstParser {
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::FfiConst;
}

pub(crate) struct FfiPureParser;
impl NoArgsAttributeParser for FfiPureParser {
const PATH: &[Symbol] = &[sym::ffi_pure];
#[derive(Default)]
pub(crate) struct FfiPureParser {
first_span: Option<Span>,
}

impl AttributeParser for FfiPureParser {
const ATTRIBUTES: AcceptMapping<Self> =
Comment thread
obeis marked this conversation as resolved.
Outdated
&[(&[sym::ffi_pure], template!(Word), unstable!(ffi_pure), |this, cx, args| {
let _ = cx.expect_no_args(args);
let span = cx.attr_span;
// `#[ffi_pure]` may only appear once; mirror the previous `OnDuplicate::Error`.
if let Some(first) = this.first_span {
cx.emit_err(UnusedMultiple { this: span, other: first, name: sym::ffi_pure });
} else {
this.first_span = Some(span);
}
})];
const SAFETY: AttributeSafety = AttributeSafety::Unsafe {
note: "`#[ffi_pure]` functions shall have no effects except for its return value, which shall not change across two consecutive function calls with the same parameters.",
unsafe_since: None,
};
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
const STABILITY: AttributeStability = unstable!(ffi_pure);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;

fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
let span = self.first_span?;
// `#[ffi_const]` functions cannot be `#[ffi_pure]`.
if cx.all_attrs.iter().any(|a| a.word_is(sym::ffi_const)) {
cx.emit_err(BothFfiConstAndPure { attr_span: span });
}
Some(AttributeKind::FfiPure(span))
}
}

pub(crate) struct RustcStdInternalSymbolParser;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ attribute_parsers!(
ConfusablesParser,
ConstStabilityParser,
DocParser,
FfiPureParser,
MacroUseParser,
NakedParser,
OnConstParser,
Expand Down Expand Up @@ -246,7 +247,6 @@ attribute_parsers!(
Single<WithoutArgs<DefaultLibAllocatorParser>>,
Single<WithoutArgs<ExportStableParser>>,
Single<WithoutArgs<FfiConstParser>>,
Single<WithoutArgs<FfiPureParser>>,
Single<WithoutArgs<FundamentalParser>>,
Single<WithoutArgs<LoopMatchParser>>,
Single<WithoutArgs<MacroEscapeParser>>,
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ use rustc_target::spec::TargetTuple;
use crate::AttributeTemplate;
use crate::context::Suggestion;

#[derive(Diagnostic)]
#[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)]
pub(crate) struct BothFfiConstAndPure {
#[primary_span]
pub attr_span: Span,
}

#[derive(Diagnostic)]
#[diag("{$attr_str} attribute cannot have empty value")]
pub(crate) struct DocAliasEmpty<'a> {
Expand Down
9 changes: 1 addition & 8 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::NonExhaustive(attr_span) => {
self.check_non_exhaustive(*attr_span, span, target, item)
}
&AttributeKind::FfiPure(attr_span) => self.check_ffi_pure(attr_span, attrs),
AttributeKind::MayDangle(attr_span) => self.check_may_dangle(hir_id, *attr_span),
AttributeKind::Link(_, attr_span) => self.check_link(hir_id, *attr_span, target),
AttributeKind::MacroExport { span, .. } => {
Expand Down Expand Up @@ -271,6 +270,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
AttributeKind::ExportStable => (),
AttributeKind::Feature(..) => (),
AttributeKind::FfiConst => (),
AttributeKind::FfiPure(..) => (),
AttributeKind::Fundamental => (),
AttributeKind::Ignore { .. } => (),
AttributeKind::InstructionSet(..) => (),
Expand Down Expand Up @@ -1112,13 +1112,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute]) {
if find_attr!(attrs, FfiConst) {
// `#[ffi_const]` functions cannot be `#[ffi_pure]`
self.dcx().emit_err(diagnostics::BothFfiConstAndPure { attr_span });
}
}

/// Checks if `#[may_dangle]` is applied to a lifetime or type generic parameter in `Drop` impl.
fn check_may_dangle(&self, hir_id: HirId, attr_span: Span) {
if let hir::Node::GenericParam(param) = self.tcx.hir_node(hir_id)
Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_passes/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,6 @@ pub(crate) struct DocMaskedNotExternCrateSelf {
pub item_span: Span,
}

#[derive(Diagnostic)]
#[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)]
pub(crate) struct BothFfiConstAndPure {
#[primary_span]
pub attr_span: Span,
}

#[derive(Diagnostic)]
#[diag("`#[optimize(none)]` cannot be used with `#[inline]` attributes")]
pub(crate) struct BothOptimizeNoneAndInline {
Expand Down
Loading