Skip to content

Commit 1e1924b

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

File tree

21 files changed

+336
-8
lines changed

21 files changed

+336
-8
lines changed

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,9 @@ attr_parsing_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
8383
.suggestion = remove the `unsafe(...)`
8484
.note = extraneous unsafe is not allowed in attributes
8585
86+
attr_parsing_invalid_export_visibility =
87+
invalid export visibility: {$unrecognized_visibility}
88+
8689
attr_parsing_invalid_issue_string =
8790
`issue` must be a non-zero numeric string or "none"
8891
.must_not_be_zero = `issue` must not be "0", use "none" instead

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,15 @@
1-
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
1+
use std::str::FromStr;
2+
3+
use rustc_feature::{AttributeTemplate, template};
4+
use rustc_hir::attrs::{
5+
CoverageAttrKind, ExportVisibilityAttrValue, OptimizeAttr, SanitizerSet, UsedBy,
6+
};
27
use rustc_session::parse::feature_err;
38

49
use super::prelude::*;
510
use crate::session_diagnostics::{
6-
NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector,
7-
ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral,
11+
InvalidExportVisibility, NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass,
12+
NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral,
813
};
914
use crate::target_checking::Policy::AllowSilent;
1015

@@ -154,6 +159,39 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
154159
}
155160
}
156161

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

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

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ use crate::attributes::allow_unstable::{
1919
};
2020
use crate::attributes::body::CoroutineParser;
2121
use crate::attributes::codegen_attrs::{
22-
ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
23-
NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser, SanitizeParser,
24-
TargetFeatureParser, TrackCallerParser, UsedParser,
22+
ColdParser, CoverageParser, ExportNameParser, ExportVisibilityParser, ForceTargetFeatureParser,
23+
NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
24+
SanitizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
2525
};
2626
use crate::attributes::confusables::ConfusablesParser;
2727
use crate::attributes::crate_level::{
@@ -179,6 +179,7 @@ attribute_parsers!(
179179
Single<DeprecationParser>,
180180
Single<DummyParser>,
181181
Single<ExportNameParser>,
182+
Single<ExportVisibilityParser>,
182183
Single<IgnoreParser>,
183184
Single<InlineParser>,
184185
Single<LinkNameParser>,

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,14 @@ pub(crate) struct IllFormedAttributeInputLint {
445445
pub suggestions: DiagArgValue,
446446
}
447447

448+
#[derive(Diagnostic)]
449+
#[diag(attr_parsing_invalid_export_visibility, code = E0648)] // DO NOT SUBMIT: fix error number?
450+
pub(crate) struct InvalidExportVisibility {
451+
#[primary_span]
452+
pub span: Span,
453+
pub unrecognized_visibility: String,
454+
}
455+
448456
#[derive(Diagnostic)]
449457
#[diag(attr_parsing_null_on_export, code = E0648)]
450458
pub(crate) struct NullOnExport {

compiler/rustc_codegen_ssa/src/codegen_attrs.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use std::str::FromStr;
33
use rustc_abi::{Align, ExternAbi};
44
use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
55
use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr};
6-
use rustc_hir::attrs::{AttributeKind, InlineAttr, InstructionSetAttr, UsedBy};
6+
use rustc_hir::attrs::{
7+
AttributeKind, ExportVisibilityAttrValue, InlineAttr, InstructionSetAttr, UsedBy,
8+
};
79
use rustc_hir::def::DefKind;
810
use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
911
use rustc_hir::{self as hir, Attribute, LangItem, find_attr, lang_items};
@@ -160,6 +162,22 @@ fn process_builtin_attrs(
160162
codegen_fn_attrs.inline = *inline;
161163
interesting_spans.inline = Some(*span);
162164
}
165+
AttributeKind::ExportVisibility { visibility, span } => {
166+
if !tcx.features().export_visibility() {
167+
feature_err(
168+
&tcx.sess,
169+
sym::export_visibility,
170+
*span,
171+
"`#[export_visibility = ...]` is currently unstable",
172+
)
173+
.emit();
174+
}
175+
codegen_fn_attrs.export_visibility = Some(match visibility {
176+
ExportVisibilityAttrValue::TargetDefault => {
177+
tcx.sess.default_visibility().into()
178+
}
179+
});
180+
}
163181
AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED,
164182
AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align),
165183
AttributeKind::LinkName { name, .. } => {
@@ -546,6 +564,17 @@ fn handle_lang_items(
546564
}
547565
err.emit();
548566
}
567+
568+
if codegen_fn_attrs.export_visibility.is_some() && !codegen_fn_attrs.contains_extern_indicator()
569+
{
570+
let export_visibility_span =
571+
find_attr!(attrs, AttributeKind::ExportVisibility{span, ..} => *span)
572+
.unwrap_or_default();
573+
tcx.dcx().span_err(
574+
export_visibility_span,
575+
"export visibility will be ignored without `export_name`, `no_mangle`, or similar attribute",
576+
);
577+
}
549578
}
550579

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

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
627627
template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute"),
628628
FutureWarnPreceding, EncodeCrossCrate::No
629629
),
630+
ungated!(export_visibility, Normal, template!(NameValueStr: "visibility"), ErrorPreceding, EncodeCrossCrate::No),
630631
ungated!(
631632
unsafe(Edition2024) link_section, Normal,
632633
template!(NameValueStr: "name", "https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute"),

compiler/rustc_feature/src/unstable.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,9 @@ declare_features! (
498498
(incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
499499
/// Allows using `#[export_stable]` which indicates that an item is exportable.
500500
(incomplete, export_stable, "1.88.0", Some(139939)),
501+
/// Allows `#[export_visibility]` on definitions of statics and/or functions.
502+
/* FIXME / DO NOT SUBMIT - use actual bug number */
503+
(unstable, export_visibility, "CURRENT_RUSTC_VERSION", Some(123456)),
501504
/// Allows using `system` as a calling convention with varargs.
502505
(unstable, extern_system_varargs, "1.86.0", Some(136946)),
503506
/// 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;
@@ -145,6 +146,26 @@ impl Deprecation {
145146
}
146147
}
147148

149+
/// Pre-parsed value of `#[export_visibility = ...]` attribute.
150+
///
151+
/// In a future RFC we may consider adding support for `Hidden`, `Protected`, and/or
152+
/// `Interposable`.
153+
#[derive(Clone, Copy, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
154+
pub enum ExportVisibilityAttrValue {
155+
TargetDefault,
156+
}
157+
158+
impl FromStr for ExportVisibilityAttrValue {
159+
type Err = String;
160+
161+
fn from_str(s: &str) -> Result<ExportVisibilityAttrValue, Self::Err> {
162+
match s {
163+
"target_default" => Ok(ExportVisibilityAttrValue::TargetDefault),
164+
_ => Err(format!("'{s}' is not a valid value for #[export_visibility = ...]",)),
165+
}
166+
}
167+
}
168+
148169
/// There are three valid forms of the attribute:
149170
/// `#[used]`, which is equivalent to `#[used(linker)]` on targets that support it, but `#[used(compiler)]` if not.
150171
/// `#[used(compiler)]`
@@ -533,6 +554,9 @@ pub enum AttributeKind {
533554
/// Represents `#[export_stable]`.
534555
ExportStable,
535556

557+
/// Represents [`#[export_visibility = ...]`](https://github.com/rust-lang/rfcs/pull/3834)
558+
ExportVisibility { visibility: ExportVisibilityAttrValue, span: Span },
559+
536560
/// Represents `#[ffi_const]`.
537561
FfiConst(Span),
538562

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ impl AttributeKind {
4545
Dummy => No,
4646
ExportName { .. } => Yes,
4747
ExportStable => No,
48+
ExportVisibility { .. } => Yes,
4849
FfiConst(..) => No,
4950
FfiPure(..) => No,
5051
Fundamental { .. } => Yes,

compiler/rustc_middle/src/middle/codegen_fn_attrs.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable};
66
use rustc_span::Symbol;
77
use rustc_target::spec::SanitizerSet;
88

9+
use crate::mir::mono::Visibility;
910
use crate::ty::{InstanceKind, TyCtxt};
1011

1112
impl<'tcx> TyCtxt<'tcx> {
@@ -43,6 +44,12 @@ pub struct CodegenFnAttrs {
4344
/// be set when `link_name` is set. This is for foreign items with the
4445
/// "raw-dylib" kind.
4546
pub link_ordinal: Option<u16>,
47+
/// The `#[export_visibility = "..."]` attribute, with values interpreted
48+
/// as follows:
49+
/// * `None` - use the "inherent" visibility (either based on the target platform, or provided via
50+
/// `-Zdefault-visibility=...` command-line flag)
51+
/// * `Some(...)` - use the item/symbol-specific visibility
52+
pub export_visibility: Option<Visibility>,
4653
/// The `#[target_feature(enable = "...")]` attribute and the enabled
4754
/// features (only enabled features are supported right now).
4855
/// Implied target features have already been applied.
@@ -180,6 +187,7 @@ impl CodegenFnAttrs {
180187
optimize: OptimizeAttr::Default,
181188
symbol_name: None,
182189
link_ordinal: None,
190+
export_visibility: None,
183191
target_features: vec![],
184192
safe_target_features: false,
185193
linkage: None,

0 commit comments

Comments
 (0)