Port the #[linkage] attribute to the new attribute system

This commit is contained in:
Sasha Pourcelot 2025-08-12 20:22:45 +02:00
parent 350d0ef0ec
commit d435197afc
27 changed files with 207 additions and 124 deletions

View file

@ -1,6 +1,6 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
use rustc_hir::attrs::{AttributeKind, Linkage};
use rustc_span::{Span, Symbol, sym};
use crate::attributes::{
@ -129,3 +129,77 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
Some(LinkOrdinal { ordinal, span: cx.attr_span })
}
}
pub(crate) struct LinkageParser;
impl<S: Stage> SingleAttributeParser<S> for LinkageParser {
const PATH: &[Symbol] = &[sym::linkage];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: [
"available_externally",
"common",
"extern_weak",
"external",
"internal",
"linkonce",
"linkonce_odr",
"weak",
"weak_odr",
]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let Some(name_value) = args.name_value() else {
cx.expected_name_value(cx.attr_span, Some(sym::linkage));
return None;
};
let Some(value) = name_value.value_as_str() else {
cx.expected_string_literal(name_value.value_span, Some(name_value.value_as_lit()));
return None;
};
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
// applicable to variable declarations and may not really make sense for
// Rust code in the first place but allow them anyway and trust that the
// user knows what they're doing. Who knows, unanticipated use cases may pop
// up in the future.
//
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
// and don't have to be, LLVM treats them as no-ops.
let linkage = match value {
sym::available_externally => Linkage::AvailableExternally,
sym::common => Linkage::Common,
sym::extern_weak => Linkage::ExternalWeak,
sym::external => Linkage::External,
sym::internal => Linkage::Internal,
sym::linkonce => Linkage::LinkOnceAny,
sym::linkonce_odr => Linkage::LinkOnceODR,
sym::weak => Linkage::WeakAny,
sym::weak_odr => Linkage::WeakODR,
_ => {
cx.expected_specific_argument(
name_value.value_span,
vec![
"available_externally",
"common",
"extern_weak",
"external",
"internal",
"linkonce",
"linkonce_odr",
"weak",
"weak_odr",
],
);
return None;
}
};
Some(AttributeKind::Linkage(linkage, cx.attr_span))
}
}

View file

@ -27,7 +27,7 @@ use crate::attributes::dummy::DummyParser;
use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
use crate::attributes::link_attrs::{
ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
LinkSectionParser, StdInternalSymbolParser,
LinkSectionParser, LinkageParser, StdInternalSymbolParser,
};
use crate::attributes::lint_helpers::{
AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
@ -167,6 +167,7 @@ attribute_parsers!(
Single<LinkNameParser>,
Single<LinkOrdinalParser>,
Single<LinkSectionParser>,
Single<LinkageParser>,
Single<MustUseParser>,
Single<OptimizeParser>,
Single<PathAttributeParser>,

View file

@ -281,8 +281,8 @@ fn data_id_for_static(
.abi
.bytes();
let linkage = if import_linkage == rustc_middle::mir::mono::Linkage::ExternalWeak
|| import_linkage == rustc_middle::mir::mono::Linkage::WeakAny
let linkage = if import_linkage == rustc_hir::attrs::Linkage::ExternalWeak
|| import_linkage == rustc_hir::attrs::Linkage::WeakAny
{
Linkage::Preemptible
} else {
@ -332,8 +332,8 @@ fn data_id_for_static(
let linkage = if definition {
crate::linkage::get_static_linkage(tcx, def_id)
} else if attrs.linkage == Some(rustc_middle::mir::mono::Linkage::ExternalWeak)
|| attrs.linkage == Some(rustc_middle::mir::mono::Linkage::WeakAny)
} else if attrs.linkage == Some(rustc_hir::attrs::Linkage::ExternalWeak)
|| attrs.linkage == Some(rustc_hir::attrs::Linkage::WeakAny)
{
Linkage::Preemptible
} else {

View file

@ -18,12 +18,11 @@ use rustc_codegen_ssa::{
use rustc_data_structures::profiling::SelfProfilerRef;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::sync::{IntoDynSyncSend, par_map};
use rustc_hir::attrs::Linkage as RLinkage;
use rustc_metadata::fs::copy_to_stdout;
use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::mono::{
CodegenUnit, Linkage as RLinkage, MonoItem, MonoItemData, Visibility,
};
use rustc_middle::mir::mono::{CodegenUnit, MonoItem, MonoItemData, Visibility};
use rustc_session::Session;
use rustc_session::config::{DebugInfo, OutFileName, OutputFilenames, OutputType};

View file

@ -1,4 +1,5 @@
use rustc_middle::mir::mono::{Linkage as RLinkage, MonoItem, Visibility};
use rustc_hir::attrs::Linkage as RLinkage;
use rustc_middle::mir::mono::{MonoItem, Visibility};
use crate::prelude::*;

View file

@ -8,8 +8,8 @@ use rustc_codegen_ssa::ModuleCodegen;
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
use rustc_codegen_ssa::mono_item::MonoItemExt;
use rustc_codegen_ssa::traits::DebugInfoCodegenMethods;
use rustc_hir::attrs::Linkage;
use rustc_middle::dep_graph;
use rustc_middle::mir::mono::Linkage;
#[cfg(feature = "master")]
use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::TyCtxt;

View file

@ -5,13 +5,13 @@ use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRang
use rustc_codegen_ssa::traits::{
BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
};
use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::interpret::{
self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint,
};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, Instance};
use rustc_middle::{bug, span_bug};

View file

@ -1,11 +1,12 @@
#[cfg(feature = "master")]
use gccjit::{FnAttribute, VarAttribute};
use rustc_codegen_ssa::traits::PreDefineCodegenMethods;
use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};

View file

@ -18,9 +18,10 @@ use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
use rustc_codegen_ssa::mono_item::MonoItemExt;
use rustc_codegen_ssa::traits::*;
use rustc_data_structures::small_c_str::SmallCStr;
use rustc_hir::attrs::Linkage;
use rustc_middle::dep_graph;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::TyCtxt;
use rustc_session::config::DebugInfo;
use rustc_span::Symbol;

View file

@ -4,6 +4,7 @@ use rustc_abi::{Align, HasDataLayout, Primitive, Scalar, Size, WrappingRange};
use rustc_codegen_ssa::common;
use rustc_codegen_ssa::traits::*;
use rustc_hir::LangItem;
use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
@ -11,7 +12,7 @@ use rustc_middle::mir::interpret::{
Allocation, ConstAllocation, ErrorHandled, InitChunk, Pointer, Scalar as InterpScalar,
read_target_uint,
};
use rustc_middle::mir::mono::{Linkage, MonoItem};
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance};
use rustc_middle::{bug, span_bug};

View file

@ -1,8 +1,9 @@
use rustc_codegen_ssa::traits::*;
use rustc_hir::attrs::Linkage;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_middle::bug;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_session::config::CrateType;

View file

@ -306,7 +306,8 @@ fn exported_generic_symbols_provider_local<'tcx>(
let mut symbols: Vec<_> = vec![];
if tcx.local_crate_exports_generics() {
use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
use rustc_hir::attrs::Linkage;
use rustc_middle::mir::mono::{MonoItem, Visibility};
use rustc_middle::ty::InstanceKind;
// Normally, we require that shared monomorphizations are not hidden,

View file

@ -11,7 +11,6 @@ use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
use rustc_middle::middle::codegen_fn_attrs::{
CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,
};
use rustc_middle::mir::mono::Linkage;
use rustc_middle::query::Providers;
use rustc_middle::span_bug;
use rustc_middle::ty::{self as ty, TyCtxt};
@ -26,31 +25,6 @@ use crate::target_features::{
check_target_feature_trait_unsafe, check_tied_features, from_target_feature_attr,
};
fn linkage_by_name(tcx: TyCtxt<'_>, def_id: LocalDefId, name: &str) -> Linkage {
use rustc_middle::mir::mono::Linkage::*;
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
// applicable to variable declarations and may not really make sense for
// Rust code in the first place but allow them anyway and trust that the
// user knows what they're doing. Who knows, unanticipated use cases may pop
// up in the future.
//
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
// and don't have to be, LLVM treats them as no-ops.
match name {
"available_externally" => AvailableExternally,
"common" => Common,
"extern_weak" => ExternalWeak,
"external" => External,
"internal" => Internal,
"linkonce" => LinkOnceAny,
"linkonce_odr" => LinkOnceODR,
"weak" => WeakAny,
"weak_odr" => WeakODR,
_ => tcx.dcx().span_fatal(tcx.def_span(def_id), "invalid linkage specified"),
}
}
/// In some cases, attributes are only valid on functions, but it's the `check_attr`
/// pass that checks that they aren't used anywhere else, rather than this module.
/// In these cases, we bail from performing further checks that are only meaningful for
@ -103,13 +77,6 @@ fn parse_instruction_set_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<Instr
}
}
// FIXME(jdonszelmann): remove when linkage becomes a parsed attr
fn parse_linkage_attr(tcx: TyCtxt<'_>, did: LocalDefId, attr: &Attribute) -> Option<Linkage> {
let val = attr.value_str()?;
let linkage = linkage_by_name(tcx, did, val.as_str());
Some(linkage)
}
// FIXME(jdonszelmann): remove when no_sanitize becomes a parsed attr
fn parse_no_sanitize_attr(tcx: TyCtxt<'_>, attr: &Attribute) -> Option<SanitizerSet> {
let list = attr.meta_item_list()?;
@ -332,6 +299,28 @@ fn process_builtin_attrs(
AttributeKind::StdInternalSymbol(_) => {
codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL
}
AttributeKind::Linkage(linkage, _) => {
let linkage = Some(*linkage);
if tcx.is_foreign_item(did) {
codegen_fn_attrs.import_linkage = linkage;
if tcx.is_mutable_static(did.into()) {
let mut diag = tcx.dcx().struct_span_err(
attr.span(),
"extern mutable statics are not allowed with `#[linkage]`",
);
diag.note(
"marking the extern static mutable would allow changing which \
symbol the static references rather than make the target of the \
symbol mutable",
);
diag.emit();
}
} else {
codegen_fn_attrs.linkage = linkage;
}
}
_ => {}
}
}
@ -349,28 +338,6 @@ fn process_builtin_attrs(
codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
}
sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
sym::linkage => {
let linkage = parse_linkage_attr(tcx, did, attr);
if tcx.is_foreign_item(did) {
codegen_fn_attrs.import_linkage = linkage;
if tcx.is_mutable_static(did.into()) {
let mut diag = tcx.dcx().struct_span_err(
attr.span(),
"extern mutable statics are not allowed with `#[linkage]`",
);
diag.note(
"marking the extern static mutable would allow changing which \
symbol the static references rather than make the target of the \
symbol mutable",
);
diag.emit();
}
} else {
codegen_fn_attrs.linkage = linkage;
}
}
sym::no_sanitize => {
interesting_spans.no_sanitize = Some(attr.span());
codegen_fn_attrs.no_sanitize |=

View file

@ -1,6 +1,6 @@
use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
use rustc_hir::attrs::InstructionSetAttr;
use rustc_middle::mir::mono::{Linkage, MonoItemData, Visibility};
use rustc_hir::attrs::{InstructionSetAttr, Linkage};
use rustc_middle::mir::mono::{MonoItemData, Visibility};
use rustc_middle::mir::{InlineAsmOperand, START_BLOCK};
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt};

View file

@ -1,5 +1,6 @@
use rustc_hir::attrs::Linkage;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::mono::{Linkage, MonoItem, MonoItemData, Visibility};
use rustc_middle::mir::mono::{MonoItem, MonoItemData, Visibility};
use rustc_middle::ty::layout::HasTyCtxt;
use tracing::debug;

View file

@ -1,5 +1,6 @@
use rustc_hir::attrs::Linkage;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::mono::{Linkage, Visibility};
use rustc_middle::mir::mono::Visibility;
use rustc_middle::ty::Instance;
pub trait PreDefineCodegenMethods<'tcx> {

View file

@ -187,6 +187,24 @@ pub enum CfgEntry {
Version(Option<RustcVersion>, Span),
}
/// Possible values for the `#[linkage]` attribute, allowing to specify the
/// linkage type for a `MonoItem`.
///
/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants.
#[derive(Encodable, Decodable, Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic, PrintAttribute)]
pub enum Linkage {
AvailableExternally,
Common,
ExternalWeak,
External,
Internal,
LinkOnceAny,
LinkOnceODR,
WeakAny,
WeakODR,
}
/// Represents parsed *built-in* inert attributes.
///
/// ## Overview
@ -360,6 +378,9 @@ pub enum AttributeKind {
/// Represents [`#[link_section]`](https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute)
LinkSection { name: Symbol, span: Span },
/// Represents `#[linkage]`.
Linkage(Linkage, Span),
/// Represents `#[loop_match]`.
LoopMatch(Span),

View file

@ -46,6 +46,7 @@ impl AttributeKind {
LinkName { .. } => Yes, // Needed for rustdoc
LinkOrdinal { .. } => No,
LinkSection { .. } => Yes, // Needed for rustdoc
Linkage(..) => No,
LoopMatch(..) => No,
MacroEscape(..) => No,
MacroTransparency(..) => Yes,

View file

@ -1311,6 +1311,7 @@ impl AttributeExt for Attribute {
Attribute::Parsed(AttributeKind::ShouldPanic { span, .. }) => *span,
Attribute::Parsed(AttributeKind::AutomaticallyDerived(span)) => *span,
Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span)) => *span,
Attribute::Parsed(AttributeKind::Linkage(_, span)) => *span,
a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
}
}

View file

@ -2,13 +2,12 @@ use std::borrow::Cow;
use rustc_abi::Align;
use rustc_ast::expand::autodiff_attrs::AutoDiffAttrs;
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, OptimizeAttr};
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr};
use rustc_hir::def_id::DefId;
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_span::Symbol;
use rustc_target::spec::SanitizerSet;
use crate::mir::mono::Linkage;
use crate::ty::{InstanceKind, TyCtxt};
impl<'tcx> TyCtxt<'tcx> {

View file

@ -10,7 +10,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHas
use rustc_data_structures::unord::UnordMap;
use rustc_hashes::Hash128;
use rustc_hir::ItemId;
use rustc_hir::attrs::InlineAttr;
use rustc_hir::attrs::{InlineAttr, Linkage};
use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_query_system::ich::StableHashingContext;
@ -368,22 +368,6 @@ pub struct MonoItemData {
pub size_estimate: usize,
}
/// Specifies the linkage type for a `MonoItem`.
///
/// See <https://llvm.org/docs/LangRef.html#linkage-types> for more details about these variants.
#[derive(Copy, Clone, PartialEq, Debug, TyEncodable, TyDecodable, HashStable)]
pub enum Linkage {
External,
AvailableExternally,
LinkOnceAny,
LinkOnceODR,
WeakAny,
WeakODR,
Internal,
ExternalWeak,
Common,
}
/// Specifies the symbol visibility with regards to dynamic linking.
///
/// Visibility doesn't have any effect when linkage is internal.

View file

@ -104,7 +104,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::sync;
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_hir::LangItem;
use rustc_hir::attrs::InlineAttr;
use rustc_hir::attrs::{InlineAttr, Linkage};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
use rustc_hir::definitions::DefPathDataName;
@ -112,7 +112,7 @@ use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
use rustc_middle::mir::mono::{
CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, Linkage, MonoItem, MonoItemData,
CodegenUnit, CodegenUnitNameBuilder, InstantiationMode, MonoItem, MonoItemData,
MonoItemPartitions, Visibility,
};
use rustc_middle::ty::print::{characteristic_def_id_of_type, with_no_trimmed_paths};

View file

@ -332,6 +332,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
&Attribute::Parsed(AttributeKind::Coroutine(attr_span)) => {
self.check_coroutine(attr_span, target)
}
&Attribute::Parsed(AttributeKind::Linkage(_, attr_span)) => {
self.check_linkage(attr_span, span, target);
}
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
match attr.path().as_slice() {
@ -395,7 +398,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
self.check_autodiff(hir_id, attr, span, target)
}
[sym::linkage, ..] => self.check_linkage(attr, span, target),
[
// ok
sym::allow
@ -2707,7 +2709,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_linkage(&self, attr: &Attribute, span: Span, target: Target) {
fn check_linkage(&self, attr_span: Span, span: Span, target: Target) {
match target {
Target::Fn
| Target::Method(..)
@ -2715,7 +2717,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| Target::ForeignStatic
| Target::ForeignFn => {}
_ => {
self.dcx().emit_err(errors::Linkage { attr_span: attr.span(), span });
self.dcx().emit_err(errors::Linkage { attr_span, span });
}
}
}

View file

@ -545,6 +545,7 @@ symbols! {
autodiff_forward,
autodiff_reverse,
automatically_derived,
available_externally,
avx,
avx10_target_feature,
avx512_target_feature,
@ -676,6 +677,7 @@ symbols! {
cold_path,
collapse_debuginfo,
column,
common,
compare_bytes,
compare_exchange,
compare_exchange_weak,
@ -956,6 +958,7 @@ symbols! {
extern_prelude,
extern_system_varargs,
extern_types,
extern_weak,
external,
external_doc,
f,
@ -1213,6 +1216,7 @@ symbols! {
instruction_set,
integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
integral,
internal,
internal_features,
into_async_iter_into_iter,
into_future,
@ -1287,6 +1291,8 @@ symbols! {
linkage,
linker,
linker_messages,
linkonce,
linkonce_odr,
lint_reasons,
literal,
load,
@ -2360,6 +2366,8 @@ symbols! {
wasm_abi,
wasm_import_module,
wasm_target_feature,
weak,
weak_odr,
where_clause_attrs,
while_let,
width,

View file

@ -90,25 +90,6 @@ error: malformed `cfi_encoding` attribute input
LL | #[cfi_encoding]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
error: malformed `linkage` attribute input
--> $DIR/malformed-attrs.rs:170:5
|
LL | #[linkage]
| ^^^^^^^^^^
|
= note: for more information, visit <https://doc.rust-lang.org/reference/linkage.html>
help: the following are the possible correct uses
|
LL | #[linkage = "available_externally"]
| ++++++++++++++++++++++++
LL | #[linkage = "common"]
| ++++++++++
LL | #[linkage = "extern_weak"]
| +++++++++++++++
LL | #[linkage = "external"]
| ++++++++++++
= and 5 other candidates
error: malformed `allow` attribute input
--> $DIR/malformed-attrs.rs:175:1
|
@ -659,6 +640,24 @@ LL | #[unsafe(ffi_const = 1)]
| | didn't expect any arguments here
| help: must be of the form: `#[ffi_const]`
error[E0539]: malformed `linkage` attribute input
--> $DIR/malformed-attrs.rs:170:5
|
LL | #[linkage]
| ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
|
help: try changing it to one of the following valid forms of the attribute
|
LL | #[linkage = "available_externally"]
| ++++++++++++++++++++++++
LL | #[linkage = "common"]
| ++++++++++
LL | #[linkage = "extern_weak"]
| +++++++++++++++
LL | #[linkage = "external"]
| ++++++++++++
= and 5 other candidates
error[E0565]: malformed `automatically_derived` attribute input
--> $DIR/malformed-attrs.rs:188:1
|

View file

@ -5,7 +5,7 @@
extern "C" {
#[linkage = "foo"]
static foo: *const i32;
//~^ ERROR: invalid linkage specified
//~^^ ERROR: malformed `linkage` attribute input [E0539]
}
fn main() {

View file

@ -1,8 +1,27 @@
error: invalid linkage specified
--> $DIR/linkage3.rs:7:5
error[E0539]: malformed `linkage` attribute input
--> $DIR/linkage3.rs:6:5
|
LL | static foo: *const i32;
| ^^^^^^^^^^^^^^^^^^^^^^
LL | #[linkage = "foo"]
| ^^^^^^^^^^^^-----^
| |
| valid arguments are `available_externally`, `common`, `extern_weak`, `external`, `internal`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr`
|
help: try changing it to one of the following valid forms of the attribute
|
LL - #[linkage = "foo"]
LL + #[linkage = "available_externally"]
|
LL - #[linkage = "foo"]
LL + #[linkage = "common"]
|
LL - #[linkage = "foo"]
LL + #[linkage = "extern_weak"]
|
LL - #[linkage = "foo"]
LL + #[linkage = "external"]
|
= and 5 other candidates
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0539`.