Skip to content

Commit aa26225

Browse files
committed
Add new unstable attribute: #[export_visibility = ...].
1 parent d222ddc commit aa26225

26 files changed

+405
-8
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ attr_parsing_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
8686
.suggestion = remove the `unsafe(...)`
8787
.note = extraneous unsafe is not allowed in attributes
8888
89+
attr_parsing_invalid_export_visibility =
90+
invalid export visibility: {$unrecognized_visibility}
91+
8992
attr_parsing_invalid_issue_string =
9093
`issue` must be a non-zero numeric string or "none"
9194
.must_not_be_zero = `issue` must not be "0", use "none" instead

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
1-
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy};
1+
use std::str::FromStr;
2+
3+
use rustc_hir::attrs::{
4+
CoverageAttrKind, ExportVisibilityAttrValue, OptimizeAttr, RtsanSetting, SanitizerSet, UsedBy,
5+
};
26
use rustc_session::parse::feature_err;
37

48
use super::prelude::*;
59
use crate::session_diagnostics::{
6-
NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector,
7-
ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral,
10+
InvalidExportVisibility, NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass,
11+
NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral,
812
};
913
use crate::target_checking::Policy::AllowSilent;
1014

@@ -153,6 +157,36 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
153157
}
154158
}
155159

160+
pub(crate) struct ExportVisibilityParser;
161+
162+
impl<S: Stage> SingleAttributeParser<S> for ExportVisibilityParser {
163+
const PATH: &[rustc_span::Symbol] = &[sym::export_visibility];
164+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
165+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
166+
const ALLOWED_TARGETS: AllowedTargets =
167+
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::Static)]);
168+
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "visibility");
169+
170+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
171+
let Some(nv) = args.name_value() else {
172+
cx.expected_name_value(cx.attr_span, None);
173+
return None;
174+
};
175+
let Some(sv) = nv.value_as_str() else {
176+
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
177+
return None;
178+
};
179+
let Ok(visibility) = ExportVisibilityAttrValue::from_str(sv.as_str()) else {
180+
cx.emit_err(InvalidExportVisibility {
181+
span: nv.value_span,
182+
unrecognized_visibility: sv.to_string(),
183+
});
184+
return None;
185+
};
186+
Some(AttributeKind::ExportVisibility { visibility, span: cx.attr_span })
187+
}
188+
}
189+
156190
pub(crate) struct ObjcClassParser;
157191

158192
impl<S: Stage> SingleAttributeParser<S> for ObjcClassParser {

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ use crate::attributes::allow_unstable::{
2121
use crate::attributes::body::CoroutineParser;
2222
use crate::attributes::cfi_encoding::CfiEncodingParser;
2323
use crate::attributes::codegen_attrs::{
24-
ColdParser, CoverageParser, EiiForeignItemParser, ExportNameParser, ForceTargetFeatureParser,
25-
NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
26-
PatchableFunctionEntryParser, RustcPassIndirectlyInNonRusticAbisParser, SanitizeParser,
27-
TargetFeatureParser, ThreadLocalParser, TrackCallerParser, UsedParser,
24+
ColdParser, CoverageParser, EiiForeignItemParser, ExportNameParser, ExportVisibilityParser,
25+
ForceTargetFeatureParser, NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser,
26+
OptimizeParser, PatchableFunctionEntryParser, RustcPassIndirectlyInNonRusticAbisParser,
27+
SanitizeParser, TargetFeatureParser, ThreadLocalParser, TrackCallerParser, UsedParser,
2828
};
2929
use crate::attributes::confusables::ConfusablesParser;
3030
use crate::attributes::crate_level::{
@@ -212,6 +212,7 @@ attribute_parsers!(
212212
Single<DoNotRecommendParser>,
213213
Single<DummyParser>,
214214
Single<ExportNameParser>,
215+
Single<ExportVisibilityParser>,
215216
Single<IgnoreParser>,
216217
Single<InlineParser>,
217218
Single<InstructionSetParser>,

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,14 @@ pub(crate) struct UnusedMultiple {
389389
pub name: Symbol,
390390
}
391391

392+
#[derive(Diagnostic)]
393+
#[diag(attr_parsing_invalid_export_visibility)]
394+
pub(crate) struct InvalidExportVisibility {
395+
#[primary_span]
396+
pub span: Span,
397+
pub unrecognized_visibility: String,
398+
}
399+
392400
#[derive(Diagnostic)]
393401
#[diag(attr_parsing_null_on_export, code = E0648)]
394402
pub(crate) struct NullOnExport {

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,12 @@ codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$err
4848
codegen_ssa_error_writing_def_file =
4949
error writing .DEF file: {$error}
5050
51+
codegen_ssa_export_visibility_with_rustc_std_internal_symbol =
52+
`#[export_visibility = ...]` cannot be used on internal language items
53+
54+
codegen_ssa_export_visibility_without_no_mangle_nor_export_name =
55+
`#[export_visibility = ...]` will be ignored without `export_name`, `no_mangle`, or similar attribute
56+
5157
codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
5258
5359
codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error}

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ use rustc_abi::{Align, ExternAbi};
44
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
55
use rustc_ast::{LitKind, MetaItem, MetaItemInner};
66
use rustc_hir::attrs::{
7-
AttributeKind, EiiImplResolution, InlineAttr, Linkage, RtsanSetting, UsedBy,
7+
AttributeKind, EiiImplResolution, ExportVisibilityAttrValue, InlineAttr, Linkage, RtsanSetting,
8+
UsedBy,
89
};
910
use rustc_hir::def::DefKind;
1011
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
@@ -75,6 +76,13 @@ fn process_builtin_attrs(
7576
match attr {
7677
AttributeKind::Cold(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD,
7778
AttributeKind::ExportName { name, .. } => codegen_fn_attrs.symbol_name = Some(*name),
79+
AttributeKind::ExportVisibility { visibility, .. } => {
80+
codegen_fn_attrs.export_visibility = Some(match visibility {
81+
ExportVisibilityAttrValue::TargetDefault => {
82+
tcx.sess.default_visibility().into()
83+
}
84+
});
85+
}
7886
AttributeKind::Inline(inline, span) => {
7987
codegen_fn_attrs.inline = *inline;
8088
interesting_spans.inline = Some(*span);
@@ -542,6 +550,17 @@ fn handle_lang_items(
542550
}
543551
err.emit();
544552
}
553+
554+
if codegen_fn_attrs.export_visibility.is_some() {
555+
let span = find_attr!(attrs, AttributeKind::ExportVisibility{span, ..} => *span)
556+
.unwrap_or_default();
557+
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
558+
tcx.dcx().emit_err(errors::ExportVisibilityWithRustcStdInternalSymbol { span });
559+
}
560+
if !codegen_fn_attrs.contains_extern_indicator() {
561+
tcx.dcx().emit_err(errors::ExportVisibilityWithoutNoMangleNorExportName { span });
562+
}
563+
}
545564
}
546565

547566
/// Generate the [`CodegenFnAttrs`] for an item (identified by the [`LocalDefId`]).

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,3 +1254,17 @@ pub(crate) struct LtoProcMacro;
12541254
#[diag(codegen_ssa_dynamic_linking_with_lto)]
12551255
#[note]
12561256
pub(crate) struct DynamicLinkingWithLTO;
1257+
1258+
#[derive(Diagnostic)]
1259+
#[diag(codegen_ssa_export_visibility_with_rustc_std_internal_symbol)]
1260+
pub(crate) struct ExportVisibilityWithRustcStdInternalSymbol {
1261+
#[primary_span]
1262+
pub span: Span,
1263+
}
1264+
1265+
#[derive(Diagnostic)]
1266+
#[diag(codegen_ssa_export_visibility_without_no_mangle_nor_export_name)]
1267+
pub(crate) struct ExportVisibilityWithoutNoMangleNorExportName {
1268+
#[primary_span]
1269+
pub span: Span,
1270+
}

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
649649
template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute"),
650650
FutureWarnPreceding, EncodeCrossCrate::No
651651
),
652+
gated!(export_visibility, Normal, template!(NameValueStr: "visibility"), ErrorPreceding, EncodeCrossCrate::No, experimental!(export_visibility)),
652653
ungated!(
653654
unsafe(Edition2024) link_section, Normal,
654655
template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute"),

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -476,6 +476,8 @@ declare_features! (
476476
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
477477
/// Allows using `#[export_stable]` which indicates that an item is exportable.
478478
(incomplete, export_stable, "1.88.0", Some(139939)),
479+
/// Allows `#[export_visibility]` on definitions of statics and/or functions.
480+
(unstable, export_visibility, "CURRENT_RUSTC_VERSION", Some(151425)),
479481
/// Externally implementable items
480482
(unstable, extern_item_impls, "1.94.0", Some(125418)),
481483
/// Allows defining `extern type`s.

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::borrow::Cow;
22
use std::path::PathBuf;
3+
use std::str::FromStr;
34

45
pub use ReprAttr::*;
56
use rustc_abi::Align;
@@ -187,6 +188,26 @@ impl Deprecation {
187188
}
188189
}
189190

191+
/// Pre-parsed value of `#[export_visibility = ...]` attribute.
192+
///
193+
/// In a future RFC we may consider adding support for `Hidden`, `Protected`, and/or
194+
/// `Interposable`.
195+
#[derive(Clone, Copy, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
196+
pub enum ExportVisibilityAttrValue {
197+
TargetDefault,
198+
}
199+
200+
impl FromStr for ExportVisibilityAttrValue {
201+
type Err = ();
202+
203+
fn from_str(s: &str) -> Result<ExportVisibilityAttrValue, Self::Err> {
204+
match s {
205+
"target_default" => Ok(ExportVisibilityAttrValue::TargetDefault),
206+
_ => Err(()),
207+
}
208+
}
209+
}
210+
190211
/// There are three valid forms of the attribute:
191212
/// `#[used]`, which is equivalent to `#[used(linker)]` on targets that support it, but `#[used(compiler)]` if not.
192213
/// `#[used(compiler)]`
@@ -874,6 +895,9 @@ pub enum AttributeKind {
874895
/// Represents `#[export_stable]`.
875896
ExportStable,
876897

898+
/// Represents [`#[export_visibility = ...]`](https://github.com/rust-lang/rust/issues/151425)
899+
ExportVisibility { visibility: ExportVisibilityAttrValue, span: Span },
900+
877901
/// Represents `#[ffi_const]`.
878902
FfiConst(Span),
879903

0 commit comments

Comments
 (0)