Skip to content

Conversation

@anforowicz
Copy link
Contributor

This PR is an implementation of the RFC tracked in #151425

@rustbot
Copy link
Collaborator

rustbot commented Jan 20, 2026

Some changes occurred in compiler/rustc_hir/src/attrs

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_passes/src/check_attr.rs

cc @jdonszelmann, @JonathanBrouwer

Some changes occurred in compiler/rustc_attr_parsing

cc @jdonszelmann, @JonathanBrouwer

@rustbot rustbot added A-attributes Area: Attributes (`#[…]`, `#![…]`) S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 20, 2026
@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jan 20, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 20, 2026

r? @chenyukang

rustbot has assigned @chenyukang.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@Kivooeo
Copy link
Member

Kivooeo commented Jan 20, 2026

i had a quick look, mostly looks good, but i'd like to maybe @JonathanBrouwer take a look on this as well, i may overlooked something

r? JonathanBrouwer

@JonathanBrouwer
Copy link
Contributor

Would like to take a look, will do so tomorrow :)

@rust-bors

This comment has been minimized.

Copy link
Contributor

@JonathanBrouwer JonathanBrouwer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some minor questions, looks good on a high level :)

View changes since this review

return None;
};
let Ok(visibility) = ExportVisibilityAttrValue::from_str(sv.as_str()) else {
cx.emit_err(InvalidExportVisibility {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this use cx.expected_specific_argument_strings instead?
(not sure)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am also not sure. Right now the new attribute expects a string literal as an argument (e.g. #[export_visibility = "target_default"] - this is the syntax that has been used so far by the RFC) . And it seems that expected_specific_argument_strings is meant to be used with symbols rather than with string literals (e.g. #[export_visibility = target_default]). Do you think the new attribute should use the latter syntax?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the attribute should continue to use the #[export_visibility = "target_default"] syntax.
If expected_specific_argument_strings does not give the proper suggestions, could you make a new method that does?

Copy link
Contributor Author

@anforowicz anforowicz Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My apologies for the delay in replying. I appreciate the feedback and didn't forget about this comment. I just need more time to figure out how to do this right.

(My hesitation to use expected_specific_argument_strings mostly stems from not wanting to define possible attribute values as symbols. But I agree that having a helper that can take &[&str] of possible inputs would indeed be nice here. And I probably should introduce such a separate helper, but when doing this 1) I think I should also add a UI test that checks if a slightly misspelled value results in a proper fix/edit suggestion, and 2) I should spend some time trying to understand how expected_specific_argument_strings works so that the new helper can reuse as much code as possible.)

Copy link
Contributor

@JonathanBrouwer JonathanBrouwer Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From taking another look at the code, it seems like expected_specific_argument_strings does already suggest quotes in the error messages. It uses a symbol as an argument, but renders it as a quoted string
For example, see: https://github.com/rust-lang/rust/blob/1dbe831e471710b71e886bd1f6a97bc47b17b1ea/tests/ui/coverage-attr/name-value.stderr

Regarding your "1" point, this would actually be really nice to have :3 But that is better to do in a separate PR

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 21, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 21, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

@rustbot
Copy link
Collaborator

rustbot commented Jan 24, 2026

This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@rustbot rustbot added the A-run-make Area: port run-make Makefiles to rmake.rs label Jan 27, 2026
@anforowicz anforowicz force-pushed the export-visibility branch 3 times, most recently from 88ddd87 to a741ebc Compare January 27, 2026 22:55

fn main() {
// Compile a cdylib
rustc().input("foo.rs").arg("-Zdefault-visibility=hidden").run();
Copy link
Contributor

@tgross35 tgross35 Jan 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe the test should build one version each with protected, hidden, interposable, and without the flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess building with and without -Zdefault-visibility=hidden is useful to verify that #[export_visibility = "target_default" actually takes -Zdefault-visibility=... into account. Done.

OTOH, I think hidden, protected, etc., would start to test -Zdefault-visibility=... more than actually testing #[export_visibility = .... Maybe such a rmake test (using various -Zdefault-visibility=... without using #[export_visibility = ...] in the test) should be added. But I am not sure if this should be done in this PR. WDYT?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's up to you how much you'd like to do :) I don't think there is any harm in testing them together since it's the same test setup and they're pretty related features.

(there's also a bit higher runtime overhead for run-make tests compared to others, so having one test is a bit better than two if they're going to be mostly the same rmake.rs file)

Comment on lines 13 to 21
let out =
llvm_readobj().arg("--dyn-symbols").input(dynamic_lib_name("foo")).run().stdout_utf8();

// `#[no_mangle]` with no other attributes means: publicly exported function.
assert!(out.contains("test_fn_no_attr"), "{out}");

// `#[no_mangle]` with `#[export_visibility = "target_default"]` means
// that visibility is inherited from `-Zdefault-visibility=hidden`.
assert!(!out.contains("test_fn_export_visibility_asks_for_target_default"), "{out}");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The run_make_support::object module may be helpful here so it gives a symbol dump on failure:

assert_eq!(object_contains_all_symbols(path, ["test_fn_no_attr"]), ContainsAllSymbolsOutcome::Ok);

assert!(!object_contains_any_symbols(path, ["test_fn_export_visibility_asks_for_target_default"]));

Or, more complicated but maybe useful if there are more properties to check down the line, inspect the file directly.

use run_make_support::object;

let obj = object::File::parse(path).unwrap();
let s = obj.symbol_by_name("test_fn_no_attr").unwrap();

assert!(s.is_global());
assert!(!s.is_undefined());
// ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The run_make_support::object module may be helpful here so it gives a symbol dump on failure:

assert_eq!(object_contains_all_symbols(path, ["test_fn_no_attr"]), ContainsAllSymbolsOutcome::Ok);

assert!(!object_contains_any_symbols(path, ["test_fn_export_visibility_asks_for_target_default"]));

Thank you for the pointer - this is very helpful. I refactored the new test to be based on object::File rather than on llvm_readobj.

OTOH, I did not use object_contains_all_symbols nor object_contains_any_symbols, because AFAICT these helpers check for existence of symbols and don't check if the symbols are exported vs hidden/private.

Or, more complicated but maybe useful if there are more properties to check down the line, inspect the file directly.

use run_make_support::object;

let obj = object::File::parse(path).unwrap();
let s = obj.symbol_by_name("test_fn_no_attr").unwrap();

assert!(s.is_global());
assert!(!s.is_undefined());
// ...

Ack. Maybe using exported_dynamic_symbol_names is sufficient for now?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-attributes Area: Attributes (`#[…]`, `#![…]`) A-run-make Area: port run-make Makefiles to rmake.rs S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants